From acc459df7537892ab5403556e03bcb588f02cff5 Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Fri, 1 Sep 2023 12:39:04 +0200 Subject: [PATCH 01/10] Docs cleanup from TIPs --- sdk/src/types/block/output/basic.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sdk/src/types/block/output/basic.rs b/sdk/src/types/block/output/basic.rs index b25f3e2c4f..428b4a238d 100644 --- a/sdk/src/types/block/output/basic.rs +++ b/sdk/src/types/block/output/basic.rs @@ -25,7 +25,7 @@ use crate::types::{ ValidationParams, }; -/// +/// Builder for a [`BasicOutput`]. #[derive(Clone)] #[must_use] pub struct BasicOutputBuilder { @@ -214,15 +214,18 @@ impl From<&BasicOutput> for BasicOutputBuilder { #[packable(unpack_error = Error)] #[packable(unpack_visitor = ProtocolParameters)] pub struct BasicOutput { - // Amount of IOTA tokens held by the output. + /// Amount of IOTA tokens to deposit with this output. #[packable(verify_with = verify_output_amount_packable)] amount: u64, + /// Amount of stored Mana held by this output. mana: u64, - // Native tokens held by the output. + /// Native tokens held by this output. native_tokens: NativeTokens, + /// Define how the output can be unlocked in a transaction. #[packable(verify_with = verify_unlock_conditions_packable)] unlock_conditions: UnlockConditions, #[packable(verify_with = verify_features_packable)] + /// Features of the output. features: Features, } @@ -285,7 +288,7 @@ impl BasicOutput { /// #[inline(always)] pub fn address(&self) -> &Address { - // An BasicOutput must have an AddressUnlockCondition. + // A BasicOutput must have an AddressUnlockCondition. self.unlock_conditions .address() .map(|unlock_condition| unlock_condition.address()) @@ -365,18 +368,15 @@ pub(crate) mod dto { utils::serde::string, }; - /// Describes a basic output. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct BasicOutputDto { #[serde(rename = "type")] pub kind: u8, - // Amount of IOTA tokens held by the output. #[serde(with = "string")] pub amount: u64, #[serde(with = "string")] pub mana: u64, - // Native tokens held by the output. #[serde(skip_serializing_if = "Vec::is_empty", default)] pub native_tokens: Vec, pub unlock_conditions: Vec, From cfb3989e4afd0368ea8a35f24e7ccad49b416415 Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Fri, 1 Sep 2023 13:00:33 +0200 Subject: [PATCH 02/10] blocks -> features --- sdk/src/types/block/output/basic.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/src/types/block/output/basic.rs b/sdk/src/types/block/output/basic.rs index 428b4a238d..a1695d1e96 100644 --- a/sdk/src/types/block/output/basic.rs +++ b/sdk/src/types/block/output/basic.rs @@ -341,16 +341,16 @@ fn verify_unlock_conditions_packable( verify_unlock_conditions::(unlock_conditions) } -fn verify_features(blocks: &Features) -> Result<(), Error> { +fn verify_features(features: &Features) -> Result<(), Error> { if VERIFY { - verify_allowed_features(blocks, BasicOutput::ALLOWED_FEATURES) + verify_allowed_features(features, BasicOutput::ALLOWED_FEATURES) } else { Ok(()) } } -fn verify_features_packable(blocks: &Features, _: &ProtocolParameters) -> Result<(), Error> { - verify_features::(blocks) +fn verify_features_packable(features: &Features, _: &ProtocolParameters) -> Result<(), Error> { + verify_features::(features) } #[cfg(feature = "serde")] From 579521186fc41dc6fa78d8d4e1272e458f716d04 Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Mon, 4 Sep 2023 10:33:17 +0200 Subject: [PATCH 03/10] NFT cleanup --- sdk/src/types/block/output/nft.rs | 16 ++++++++-------- sdk/src/types/block/unlock/account.rs | 1 - sdk/src/types/block/unlock/nft.rs | 1 - sdk/src/types/block/unlock/reference.rs | 2 -- sdk/src/types/block/unlock/signature.rs | 1 - 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/sdk/src/types/block/output/nft.rs b/sdk/src/types/block/output/nft.rs index 541a782fca..933476c84f 100644 --- a/sdk/src/types/block/output/nft.rs +++ b/sdk/src/types/block/output/nft.rs @@ -30,7 +30,7 @@ use crate::types::{ ValidationParams, }; -/// +/// Builder for an [`NftOutput`]. #[derive(Clone)] #[must_use] pub struct NftOutputBuilder { @@ -261,15 +261,19 @@ impl From<&NftOutput> for NftOutputBuilder { /// Describes an NFT output, a globally unique token with metadata attached. #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct NftOutput { - // Amount of IOTA tokens held by the output. + /// Amount of IOTA tokens to deposit with this output. amount: u64, + /// Amount of stored Mana held by this output. mana: u64, - // Native tokens held by the output. + /// Native tokens held by this output. native_tokens: NativeTokens, - // Unique identifier of the NFT. + /// Unique identifier of the NFT. nft_id: NftId, + /// Define how the output can be unlocked in a transaction. unlock_conditions: UnlockConditions, + /// Features of the output. features: Features, + /// Immutable features of the output. immutable_features: Features, } @@ -519,21 +523,17 @@ pub(crate) mod dto { utils::serde::string, }; - /// Describes an NFT output, a globally unique token with metadata attached. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct NftOutputDto { #[serde(rename = "type")] pub kind: u8, - // Amount of IOTA tokens held by the output. #[serde(with = "string")] pub amount: u64, #[serde(with = "string")] pub mana: u64, - // Native tokens held by the output. #[serde(skip_serializing_if = "Vec::is_empty", default)] pub native_tokens: Vec, - // Unique identifier of the NFT. pub nft_id: NftId, pub unlock_conditions: Vec, #[serde(skip_serializing_if = "Vec::is_empty", default)] diff --git a/sdk/src/types/block/unlock/account.rs b/sdk/src/types/block/unlock/account.rs index 4a301733b9..3da5fd0e43 100644 --- a/sdk/src/types/block/unlock/account.rs +++ b/sdk/src/types/block/unlock/account.rs @@ -41,7 +41,6 @@ mod dto { use super::*; - /// Points to the unlock of a consumed account output. #[derive(Serialize, Deserialize)] struct AccountUnlockDto { #[serde(rename = "type")] diff --git a/sdk/src/types/block/unlock/nft.rs b/sdk/src/types/block/unlock/nft.rs index 97d766a4f5..e77bdb0746 100644 --- a/sdk/src/types/block/unlock/nft.rs +++ b/sdk/src/types/block/unlock/nft.rs @@ -42,7 +42,6 @@ pub(crate) mod dto { use super::*; - /// Points to the unlock of a consumed NFT output. #[derive(Serialize, Deserialize)] struct NftUnlockDto { #[serde(rename = "type")] diff --git a/sdk/src/types/block/unlock/reference.rs b/sdk/src/types/block/unlock/reference.rs index b56599d146..8a72d608c1 100644 --- a/sdk/src/types/block/unlock/reference.rs +++ b/sdk/src/types/block/unlock/reference.rs @@ -39,8 +39,6 @@ pub(crate) mod dto { use super::*; - /// References a previous unlock in order to substitute the duplication of the same unlock data for inputs which - /// unlock through the same data. #[derive(Serialize, Deserialize)] struct ReferenceUnlockDto { #[serde(rename = "type")] diff --git a/sdk/src/types/block/unlock/signature.rs b/sdk/src/types/block/unlock/signature.rs index b2676d6a64..ba1aaff388 100644 --- a/sdk/src/types/block/unlock/signature.rs +++ b/sdk/src/types/block/unlock/signature.rs @@ -33,7 +33,6 @@ pub(crate) mod dto { use super::*; - /// Defines an unlock containing signature(s) unlocking input(s). #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct SignatureUnlockDto { #[serde(rename = "type")] From c47f3385dfe9e2723d96aecfe01bbdfeb841a3ba Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Mon, 4 Sep 2023 14:51:32 +0200 Subject: [PATCH 04/10] Move some tests around --- sdk/src/types/block/output/account.rs | 83 +-------------------- sdk/src/types/block/output/basic.rs | 58 +-------------- sdk/src/types/block/output/foundry.rs | 56 --------------- sdk/src/types/block/output/nft.rs | 60 +--------------- sdk/tests/types/mod.rs | 1 + sdk/tests/types/output/account.rs | 100 ++++++++++++++++++++++++++ sdk/tests/types/output/basic.rs | 73 +++++++++++++++++++ sdk/tests/types/output/foundry.rs | 71 ++++++++++++++++++ sdk/tests/types/output/mod.rs | 7 ++ sdk/tests/types/output/nft.rs | 72 +++++++++++++++++++ 10 files changed, 327 insertions(+), 254 deletions(-) create mode 100644 sdk/tests/types/output/account.rs create mode 100644 sdk/tests/types/output/basic.rs create mode 100644 sdk/tests/types/output/foundry.rs create mode 100644 sdk/tests/types/output/mod.rs create mode 100644 sdk/tests/types/output/nft.rs diff --git a/sdk/src/types/block/output/account.rs b/sdk/src/types/block/output/account.rs index acc1b5deee..8867b1fb97 100644 --- a/sdk/src/types/block/output/account.rs +++ b/sdk/src/types/block/output/account.rs @@ -882,18 +882,16 @@ pub(crate) mod dto { #[cfg(test)] mod tests { - use packable::PackableExt; use super::*; use crate::types::{ block::{ - address::AccountAddress, output::{dto::OutputDto, FoundryId, SimpleTokenScheme, TokenId}, protocol::protocol_parameters, rand::{ address::rand_account_address, output::{ - feature::{rand_allowed_features, rand_issuer_feature, rand_metadata_feature, rand_sender_feature}, + feature::rand_allowed_features, rand_account_id, rand_account_output, unlock_condition::{ rand_governor_address_unlock_condition_different_from, @@ -905,85 +903,6 @@ mod tests { TryFromDto, }; - #[test] - fn builder() { - let protocol_parameters = protocol_parameters(); - let account_id = rand_account_id(); - let foundry_id = FoundryId::build(&AccountAddress::from(account_id), 0, SimpleTokenScheme::KIND); - let gov_address_1 = rand_governor_address_unlock_condition_different_from(&account_id); - let gov_address_2 = rand_governor_address_unlock_condition_different_from(&account_id); - let state_address_1 = rand_state_controller_address_unlock_condition_different_from(&account_id); - let state_address_2 = rand_state_controller_address_unlock_condition_different_from(&account_id); - let sender_1 = rand_sender_feature(); - let sender_2 = rand_sender_feature(); - let issuer_1 = rand_issuer_feature(); - let issuer_2 = rand_issuer_feature(); - - let mut builder = AccountOutput::build_with_amount(0, account_id) - .add_native_token(NativeToken::new(TokenId::from(foundry_id), 1000).unwrap()) - .add_unlock_condition(gov_address_1) - .add_unlock_condition(state_address_1) - .add_feature(sender_1) - .replace_feature(sender_2) - .replace_immutable_feature(issuer_1) - .add_immutable_feature(issuer_2); - - let output = builder.clone().finish().unwrap(); - assert_eq!(output.unlock_conditions().governor_address(), Some(&gov_address_1)); - assert_eq!( - output.unlock_conditions().state_controller_address(), - Some(&state_address_1) - ); - assert_eq!(output.features().sender(), Some(&sender_2)); - assert_eq!(output.immutable_features().issuer(), Some(&issuer_1)); - - builder = builder - .clear_unlock_conditions() - .clear_features() - .clear_immutable_features() - .replace_unlock_condition(gov_address_2) - .replace_unlock_condition(state_address_2); - let output = builder.clone().finish().unwrap(); - assert_eq!(output.unlock_conditions().governor_address(), Some(&gov_address_2)); - assert_eq!( - output.unlock_conditions().state_controller_address(), - Some(&state_address_2) - ); - assert!(output.features().is_empty()); - assert!(output.immutable_features().is_empty()); - - let metadata = rand_metadata_feature(); - - let output = builder - .with_minimum_storage_deposit(protocol_parameters.rent_structure()) - .add_unlock_condition(rand_state_controller_address_unlock_condition_different_from( - &account_id, - )) - .add_unlock_condition(rand_governor_address_unlock_condition_different_from(&account_id)) - .with_features([Feature::from(metadata.clone()), sender_1.into()]) - .with_immutable_features([Feature::from(metadata.clone()), issuer_1.into()]) - .finish_with_params(ValidationParams::default().with_protocol_parameters(protocol_parameters.clone())) - .unwrap(); - - assert_eq!( - output.amount(), - Output::Account(output.clone()).rent_cost(protocol_parameters.rent_structure()) - ); - assert_eq!(output.features().metadata(), Some(&metadata)); - assert_eq!(output.features().sender(), Some(&sender_1)); - assert_eq!(output.immutable_features().metadata(), Some(&metadata)); - assert_eq!(output.immutable_features().issuer(), Some(&issuer_1)); - } - - #[test] - fn pack_unpack() { - let protocol_parameters = protocol_parameters(); - let output = rand_account_output(protocol_parameters.token_supply()); - let bytes = output.pack_to_vec(); - let output_unpacked = AccountOutput::unpack_verified(bytes, &protocol_parameters).unwrap(); - assert_eq!(output, output_unpacked); - } - #[test] fn to_from_dto() { let protocol_parameters = protocol_parameters(); diff --git a/sdk/src/types/block/output/basic.rs b/sdk/src/types/block/output/basic.rs index a1695d1e96..6b329dccbc 100644 --- a/sdk/src/types/block/output/basic.rs +++ b/sdk/src/types/block/output/basic.rs @@ -454,7 +454,6 @@ pub(crate) mod dto { #[cfg(test)] mod tests { - use packable::PackableExt; use super::*; use crate::types::{ @@ -464,68 +463,13 @@ mod tests { rand::{ address::rand_account_address, output::{ - feature::{rand_allowed_features, rand_metadata_feature, rand_sender_feature}, - rand_basic_output, - unlock_condition::rand_address_unlock_condition, + feature::rand_allowed_features, rand_basic_output, unlock_condition::rand_address_unlock_condition, }, }, }, TryFromDto, }; - #[test] - fn builder() { - let protocol_parameters = protocol_parameters(); - let foundry_id = FoundryId::build(&rand_account_address(), 0, SimpleTokenScheme::KIND); - let address_1 = rand_address_unlock_condition(); - let address_2 = rand_address_unlock_condition(); - let sender_1 = rand_sender_feature(); - let sender_2 = rand_sender_feature(); - - let mut builder = BasicOutput::build_with_amount(0) - .add_native_token(NativeToken::new(TokenId::from(foundry_id), 1000).unwrap()) - .add_unlock_condition(address_1) - .add_feature(sender_1) - .replace_feature(sender_2); - - let output = builder.clone().finish().unwrap(); - assert_eq!(output.unlock_conditions().address(), Some(&address_1)); - assert_eq!(output.features().sender(), Some(&sender_2)); - - builder = builder - .clear_unlock_conditions() - .clear_features() - .replace_unlock_condition(address_2); - let output = builder.clone().finish().unwrap(); - assert_eq!(output.unlock_conditions().address(), Some(&address_2)); - assert!(output.features().is_empty()); - - let metadata = rand_metadata_feature(); - - let output = builder - .with_minimum_storage_deposit(protocol_parameters.rent_structure()) - .add_unlock_condition(rand_address_unlock_condition()) - .with_features([Feature::from(metadata.clone()), sender_1.into()]) - .finish_with_params(ValidationParams::default().with_protocol_parameters(protocol_parameters.clone())) - .unwrap(); - - assert_eq!( - output.amount(), - Output::Basic(output.clone()).rent_cost(protocol_parameters.rent_structure()) - ); - assert_eq!(output.features().metadata(), Some(&metadata)); - assert_eq!(output.features().sender(), Some(&sender_1)); - } - - #[test] - fn pack_unpack() { - let protocol_parameters = protocol_parameters(); - let output = rand_basic_output(protocol_parameters.token_supply()); - let bytes = output.pack_to_vec(); - let output_unpacked = BasicOutput::unpack_verified(bytes, &protocol_parameters).unwrap(); - assert_eq!(output, output_unpacked); - } - #[test] fn to_from_dto() { let protocol_parameters = protocol_parameters(); diff --git a/sdk/src/types/block/output/foundry.rs b/sdk/src/types/block/output/foundry.rs index 17a28668f1..43c7b2c08a 100644 --- a/sdk/src/types/block/output/foundry.rs +++ b/sdk/src/types/block/output/foundry.rs @@ -737,7 +737,6 @@ pub(crate) mod dto { #[cfg(test)] mod tests { - use packable::PackableExt; use super::*; use crate::types::{ @@ -758,61 +757,6 @@ mod tests { TryFromDto, }; - #[test] - fn builder() { - let protocol_parameters = protocol_parameters(); - let foundry_id = FoundryId::build(&rand_account_address(), 0, SimpleTokenScheme::KIND); - let account_1 = ImmutableAccountAddressUnlockCondition::new(rand_account_address()); - let account_2 = ImmutableAccountAddressUnlockCondition::new(rand_account_address()); - let metadata_1 = rand_metadata_feature(); - let metadata_2 = rand_metadata_feature(); - - let mut builder = FoundryOutput::build_with_amount(0, 234, rand_token_scheme()) - .with_serial_number(85) - .add_native_token(NativeToken::new(TokenId::from(foundry_id), 1000).unwrap()) - .with_unlock_conditions([account_1]) - .add_feature(metadata_1.clone()) - .replace_feature(metadata_2.clone()) - .with_immutable_features([metadata_2.clone()]) - .replace_immutable_feature(metadata_1.clone()); - - let output = builder.clone().finish().unwrap(); - assert_eq!(output.serial_number(), 85); - assert_eq!(output.unlock_conditions().immutable_account_address(), Some(&account_1)); - assert_eq!(output.features().metadata(), Some(&metadata_2)); - assert_eq!(output.immutable_features().metadata(), Some(&metadata_1)); - - builder = builder - .clear_unlock_conditions() - .clear_features() - .clear_immutable_features() - .replace_unlock_condition(account_2); - let output = builder.clone().finish().unwrap(); - assert_eq!(output.unlock_conditions().immutable_account_address(), Some(&account_2)); - assert!(output.features().is_empty()); - assert!(output.immutable_features().is_empty()); - - let output = builder - .with_minimum_storage_deposit(protocol_parameters.rent_structure()) - .add_unlock_condition(ImmutableAccountAddressUnlockCondition::new(rand_account_address())) - .finish_with_params(&protocol_parameters) - .unwrap(); - - assert_eq!( - output.amount(), - Output::Foundry(output).rent_cost(protocol_parameters.rent_structure()) - ); - } - - #[test] - fn pack_unpack() { - let protocol_parameters = protocol_parameters(); - let output = rand_foundry_output(protocol_parameters.token_supply()); - let bytes = output.pack_to_vec(); - let output_unpacked = FoundryOutput::unpack_verified(bytes, &protocol_parameters).unwrap(); - assert_eq!(output, output_unpacked); - } - #[test] fn to_from_dto() { let protocol_parameters = protocol_parameters(); diff --git a/sdk/src/types/block/output/nft.rs b/sdk/src/types/block/output/nft.rs index 933476c84f..596bc806cc 100644 --- a/sdk/src/types/block/output/nft.rs +++ b/sdk/src/types/block/output/nft.rs @@ -622,7 +622,6 @@ pub(crate) mod dto { #[cfg(test)] mod tests { - use packable::PackableExt; use super::*; use crate::types::{ @@ -632,70 +631,13 @@ mod tests { rand::{ address::rand_account_address, output::{ - feature::{rand_allowed_features, rand_issuer_feature, rand_sender_feature}, - rand_nft_output, - unlock_condition::rand_address_unlock_condition, + feature::rand_allowed_features, rand_nft_output, unlock_condition::rand_address_unlock_condition, }, }, }, TryFromDto, }; - #[test] - fn builder() { - let protocol_parameters = protocol_parameters(); - let foundry_id = FoundryId::build(&rand_account_address(), 0, SimpleTokenScheme::KIND); - let address_1 = rand_address_unlock_condition(); - let address_2 = rand_address_unlock_condition(); - let sender_1 = rand_sender_feature(); - let sender_2 = rand_sender_feature(); - let issuer_1 = rand_issuer_feature(); - let issuer_2 = rand_issuer_feature(); - - let mut builder = NftOutput::build_with_amount(0, NftId::null()) - .add_native_token(NativeToken::new(TokenId::from(foundry_id), 1000).unwrap()) - .add_unlock_condition(address_1) - .add_feature(sender_1) - .replace_feature(sender_2) - .replace_immutable_feature(issuer_1) - .add_immutable_feature(issuer_2); - - let output = builder.clone().finish().unwrap(); - assert_eq!(output.unlock_conditions().address(), Some(&address_1)); - assert_eq!(output.features().sender(), Some(&sender_2)); - assert_eq!(output.immutable_features().issuer(), Some(&issuer_1)); - - builder = builder - .clear_unlock_conditions() - .clear_features() - .clear_immutable_features() - .replace_unlock_condition(address_2); - let output = builder.clone().finish().unwrap(); - assert_eq!(output.unlock_conditions().address(), Some(&address_2)); - assert!(output.features().is_empty()); - assert!(output.immutable_features().is_empty()); - - let output = builder - .with_minimum_storage_deposit(protocol_parameters.rent_structure()) - .add_unlock_condition(rand_address_unlock_condition()) - .finish_with_params(protocol_parameters.token_supply()) - .unwrap(); - - assert_eq!( - output.amount(), - Output::Nft(output).rent_cost(protocol_parameters.rent_structure()) - ); - } - - #[test] - fn pack_unpack() { - let protocol_parameters = protocol_parameters(); - let output = rand_nft_output(protocol_parameters.token_supply()); - let bytes = output.pack_to_vec(); - let output_unpacked = NftOutput::unpack_verified(bytes, &protocol_parameters).unwrap(); - assert_eq!(output, output_unpacked); - } - #[test] fn to_from_dto() { let protocol_parameters = protocol_parameters(); diff --git a/sdk/tests/types/mod.rs b/sdk/tests/types/mod.rs index d96861c900..4d873511da 100644 --- a/sdk/tests/types/mod.rs +++ b/sdk/tests/types/mod.rs @@ -8,6 +8,7 @@ mod block_id; mod ed25519_signature; mod foundry_id; mod input; +mod output; mod output_id; mod parents; mod payload; diff --git a/sdk/tests/types/output/account.rs b/sdk/tests/types/output/account.rs new file mode 100644 index 0000000000..a0d35ce25b --- /dev/null +++ b/sdk/tests/types/output/account.rs @@ -0,0 +1,100 @@ +// Copyright 2023 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use iota_sdk::types::{ + block::{ + address::AccountAddress, + output::{AccountOutput, Feature, FoundryId, NativeToken, Output, Rent, SimpleTokenScheme, TokenId}, + protocol::protocol_parameters, + rand::output::{ + feature::{rand_issuer_feature, rand_metadata_feature, rand_sender_feature}, + rand_account_id, rand_account_output, + unlock_condition::{ + rand_governor_address_unlock_condition_different_from, + rand_state_controller_address_unlock_condition_different_from, + }, + }, + }, + ValidationParams, +}; +use packable::PackableExt; + +#[test] +fn builder() { + let protocol_parameters = protocol_parameters(); + let account_id = rand_account_id(); + let foundry_id = FoundryId::build(&AccountAddress::from(account_id), 0, SimpleTokenScheme::KIND); + let gov_address_1 = rand_governor_address_unlock_condition_different_from(&account_id); + let gov_address_2 = rand_governor_address_unlock_condition_different_from(&account_id); + let state_address_1 = rand_state_controller_address_unlock_condition_different_from(&account_id); + let state_address_2 = rand_state_controller_address_unlock_condition_different_from(&account_id); + let sender_1 = rand_sender_feature(); + let sender_2 = rand_sender_feature(); + let issuer_1 = rand_issuer_feature(); + let issuer_2 = rand_issuer_feature(); + + let mut builder = AccountOutput::build_with_amount(0, account_id) + .add_native_token(NativeToken::new(TokenId::from(foundry_id), 1000).unwrap()) + .add_unlock_condition(gov_address_1) + .add_unlock_condition(state_address_1) + .add_feature(sender_1) + .replace_feature(sender_2) + .replace_immutable_feature(issuer_1) + .add_immutable_feature(issuer_2); + + let output = builder.clone().finish().unwrap(); + assert_eq!(output.unlock_conditions().governor_address(), Some(&gov_address_1)); + assert_eq!( + output.unlock_conditions().state_controller_address(), + Some(&state_address_1) + ); + assert_eq!(output.features().sender(), Some(&sender_2)); + assert_eq!(output.immutable_features().issuer(), Some(&issuer_1)); + + builder = builder + .clear_unlock_conditions() + .clear_features() + .clear_immutable_features() + .replace_unlock_condition(gov_address_2) + .replace_unlock_condition(state_address_2); + let output = builder.clone().finish().unwrap(); + assert_eq!(output.unlock_conditions().governor_address(), Some(&gov_address_2)); + assert_eq!( + output.unlock_conditions().state_controller_address(), + Some(&state_address_2) + ); + assert!(output.features().is_empty()); + assert!(output.immutable_features().is_empty()); + + let metadata = rand_metadata_feature(); + + let output = builder + .with_minimum_storage_deposit(protocol_parameters.rent_structure()) + .add_unlock_condition(rand_state_controller_address_unlock_condition_different_from( + &account_id, + )) + .add_unlock_condition(rand_governor_address_unlock_condition_different_from(&account_id)) + .with_features([Feature::from(metadata.clone()), sender_1.into()]) + .with_immutable_features([Feature::from(metadata.clone()), issuer_1.into()]) + .finish_with_params(ValidationParams::default().with_protocol_parameters(protocol_parameters.clone())) + .unwrap(); + + assert_eq!( + output.amount(), + Output::Account(output.clone()).rent_cost(protocol_parameters.rent_structure()) + ); + assert_eq!(output.features().metadata(), Some(&metadata)); + assert_eq!(output.features().sender(), Some(&sender_1)); + assert_eq!(output.immutable_features().metadata(), Some(&metadata)); + assert_eq!(output.immutable_features().issuer(), Some(&issuer_1)); +} + +#[test] +fn pack_unpack() { + let protocol_parameters = protocol_parameters(); + let output = rand_account_output(protocol_parameters.token_supply()); + let bytes = output.pack_to_vec(); + let output_unpacked = AccountOutput::unpack_verified(bytes, &protocol_parameters).unwrap(); + + assert_eq!(output, output_unpacked); +} diff --git a/sdk/tests/types/output/basic.rs b/sdk/tests/types/output/basic.rs new file mode 100644 index 0000000000..a8afef481f --- /dev/null +++ b/sdk/tests/types/output/basic.rs @@ -0,0 +1,73 @@ +// Copyright 2023 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use iota_sdk::types::{ + block::{ + output::{BasicOutput, Feature, FoundryId, NativeToken, Output, Rent, SimpleTokenScheme, TokenId}, + protocol::protocol_parameters, + rand::{ + address::rand_account_address, + output::{ + feature::{rand_metadata_feature, rand_sender_feature}, + rand_basic_output, + unlock_condition::rand_address_unlock_condition, + }, + }, + }, + ValidationParams, +}; +use packable::PackableExt; + +#[test] +fn builder() { + let protocol_parameters = protocol_parameters(); + let foundry_id = FoundryId::build(&rand_account_address(), 0, SimpleTokenScheme::KIND); + let address_1 = rand_address_unlock_condition(); + let address_2 = rand_address_unlock_condition(); + let sender_1 = rand_sender_feature(); + let sender_2 = rand_sender_feature(); + + let mut builder = BasicOutput::build_with_amount(0) + .add_native_token(NativeToken::new(TokenId::from(foundry_id), 1000).unwrap()) + .add_unlock_condition(address_1) + .add_feature(sender_1) + .replace_feature(sender_2); + + let output = builder.clone().finish().unwrap(); + assert_eq!(output.unlock_conditions().address(), Some(&address_1)); + assert_eq!(output.features().sender(), Some(&sender_2)); + + builder = builder + .clear_unlock_conditions() + .clear_features() + .replace_unlock_condition(address_2); + let output = builder.clone().finish().unwrap(); + assert_eq!(output.unlock_conditions().address(), Some(&address_2)); + assert!(output.features().is_empty()); + + let metadata = rand_metadata_feature(); + + let output = builder + .with_minimum_storage_deposit(protocol_parameters.rent_structure()) + .add_unlock_condition(rand_address_unlock_condition()) + .with_features([Feature::from(metadata.clone()), sender_1.into()]) + .finish_with_params(ValidationParams::default().with_protocol_parameters(protocol_parameters.clone())) + .unwrap(); + + assert_eq!( + output.amount(), + Output::Basic(output.clone()).rent_cost(protocol_parameters.rent_structure()) + ); + assert_eq!(output.features().metadata(), Some(&metadata)); + assert_eq!(output.features().sender(), Some(&sender_1)); +} + +#[test] +fn pack_unpack() { + let protocol_parameters = protocol_parameters(); + let output = rand_basic_output(protocol_parameters.token_supply()); + let bytes = output.pack_to_vec(); + let output_unpacked = BasicOutput::unpack_verified(bytes, &protocol_parameters).unwrap(); + + assert_eq!(output, output_unpacked); +} diff --git a/sdk/tests/types/output/foundry.rs b/sdk/tests/types/output/foundry.rs new file mode 100644 index 0000000000..a452418c8f --- /dev/null +++ b/sdk/tests/types/output/foundry.rs @@ -0,0 +1,71 @@ +// Copyright 2023 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use iota_sdk::types::block::{ + output::{ + unlock_condition::ImmutableAccountAddressUnlockCondition, FoundryId, FoundryOutput, NativeToken, Output, Rent, + SimpleTokenScheme, TokenId, + }, + protocol::protocol_parameters, + rand::{ + address::rand_account_address, + output::{feature::rand_metadata_feature, rand_foundry_output, rand_token_scheme}, + }, +}; +use packable::PackableExt; + +#[test] +fn builder() { + let protocol_parameters = protocol_parameters(); + let foundry_id = FoundryId::build(&rand_account_address(), 0, SimpleTokenScheme::KIND); + let account_1 = ImmutableAccountAddressUnlockCondition::new(rand_account_address()); + let account_2 = ImmutableAccountAddressUnlockCondition::new(rand_account_address()); + let metadata_1 = rand_metadata_feature(); + let metadata_2 = rand_metadata_feature(); + + let mut builder = FoundryOutput::build_with_amount(0, 234, rand_token_scheme()) + .with_serial_number(85) + .add_native_token(NativeToken::new(TokenId::from(foundry_id), 1000).unwrap()) + .with_unlock_conditions([account_1]) + .add_feature(metadata_1.clone()) + .replace_feature(metadata_2.clone()) + .with_immutable_features([metadata_2.clone()]) + .replace_immutable_feature(metadata_1.clone()); + + let output = builder.clone().finish().unwrap(); + assert_eq!(output.serial_number(), 85); + assert_eq!(output.unlock_conditions().immutable_account_address(), Some(&account_1)); + assert_eq!(output.features().metadata(), Some(&metadata_2)); + assert_eq!(output.immutable_features().metadata(), Some(&metadata_1)); + + builder = builder + .clear_unlock_conditions() + .clear_features() + .clear_immutable_features() + .replace_unlock_condition(account_2); + let output = builder.clone().finish().unwrap(); + assert_eq!(output.unlock_conditions().immutable_account_address(), Some(&account_2)); + assert!(output.features().is_empty()); + assert!(output.immutable_features().is_empty()); + + let output = builder + .with_minimum_storage_deposit(protocol_parameters.rent_structure()) + .add_unlock_condition(ImmutableAccountAddressUnlockCondition::new(rand_account_address())) + .finish_with_params(&protocol_parameters) + .unwrap(); + + assert_eq!( + output.amount(), + Output::Foundry(output).rent_cost(protocol_parameters.rent_structure()) + ); +} + +#[test] +fn pack_unpack() { + let protocol_parameters = protocol_parameters(); + let output = rand_foundry_output(protocol_parameters.token_supply()); + let bytes = output.pack_to_vec(); + let output_unpacked = FoundryOutput::unpack_verified(bytes, &protocol_parameters).unwrap(); + + assert_eq!(output, output_unpacked); +} diff --git a/sdk/tests/types/output/mod.rs b/sdk/tests/types/output/mod.rs new file mode 100644 index 0000000000..7c0be69755 --- /dev/null +++ b/sdk/tests/types/output/mod.rs @@ -0,0 +1,7 @@ +// Copyright 2023 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +mod account; +mod basic; +mod foundry; +mod nft; diff --git a/sdk/tests/types/output/nft.rs b/sdk/tests/types/output/nft.rs new file mode 100644 index 0000000000..3fe62773b7 --- /dev/null +++ b/sdk/tests/types/output/nft.rs @@ -0,0 +1,72 @@ +// Copyright 2023 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use iota_sdk::types::block::{ + output::{FoundryId, NativeToken, NftId, NftOutput, Output, Rent, SimpleTokenScheme, TokenId}, + protocol::protocol_parameters, + rand::{ + address::rand_account_address, + output::{ + feature::{rand_issuer_feature, rand_sender_feature}, + rand_nft_output, + unlock_condition::rand_address_unlock_condition, + }, + }, +}; +use packable::PackableExt; + +#[test] +fn builder() { + let protocol_parameters = protocol_parameters(); + let foundry_id = FoundryId::build(&rand_account_address(), 0, SimpleTokenScheme::KIND); + let address_1 = rand_address_unlock_condition(); + let address_2 = rand_address_unlock_condition(); + let sender_1 = rand_sender_feature(); + let sender_2 = rand_sender_feature(); + let issuer_1 = rand_issuer_feature(); + let issuer_2 = rand_issuer_feature(); + + let mut builder = NftOutput::build_with_amount(0, NftId::null()) + .add_native_token(NativeToken::new(TokenId::from(foundry_id), 1000).unwrap()) + .add_unlock_condition(address_1) + .add_feature(sender_1) + .replace_feature(sender_2) + .replace_immutable_feature(issuer_1) + .add_immutable_feature(issuer_2); + + let output = builder.clone().finish().unwrap(); + assert_eq!(output.unlock_conditions().address(), Some(&address_1)); + assert_eq!(output.features().sender(), Some(&sender_2)); + assert_eq!(output.immutable_features().issuer(), Some(&issuer_1)); + + builder = builder + .clear_unlock_conditions() + .clear_features() + .clear_immutable_features() + .replace_unlock_condition(address_2); + let output = builder.clone().finish().unwrap(); + assert_eq!(output.unlock_conditions().address(), Some(&address_2)); + assert!(output.features().is_empty()); + assert!(output.immutable_features().is_empty()); + + let output = builder + .with_minimum_storage_deposit(protocol_parameters.rent_structure()) + .add_unlock_condition(rand_address_unlock_condition()) + .finish_with_params(protocol_parameters.token_supply()) + .unwrap(); + + assert_eq!( + output.amount(), + Output::Nft(output).rent_cost(protocol_parameters.rent_structure()) + ); +} + +#[test] +fn pack_unpack() { + let protocol_parameters = protocol_parameters(); + let output = rand_nft_output(protocol_parameters.token_supply()); + let bytes = output.pack_to_vec(); + let output_unpacked = NftOutput::unpack_verified(bytes, &protocol_parameters).unwrap(); + + assert_eq!(output, output_unpacked); +} From 32eb395956523b11ed825b853741bd46081f6869 Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Tue, 5 Sep 2023 22:31:30 +0200 Subject: [PATCH 05/10] Nits --- sdk/src/types/block/output/foundry.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sdk/src/types/block/output/foundry.rs b/sdk/src/types/block/output/foundry.rs index b1b3ed3482..cc6118bdf6 100644 --- a/sdk/src/types/block/output/foundry.rs +++ b/sdk/src/types/block/output/foundry.rs @@ -32,7 +32,7 @@ use crate::types::{ ValidationParams, }; -/// +/// Builder for a [`FoundryOutput`]. #[derive(Clone)] #[must_use] pub struct FoundryOutputBuilder { @@ -280,15 +280,19 @@ impl From<&FoundryOutput> for FoundryOutputBuilder { /// Describes a foundry output that is controlled by an account. #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct FoundryOutput { - // Amount of IOTA tokens held by the output. + /// Amount of IOTA tokens to deposit with this output. amount: u64, - // Native tokens held by the output. + /// Native tokens held by this output. native_tokens: NativeTokens, - // The serial number of the foundry with respect to the controlling account. + /// The serial number of the foundry with respect to the controlling account. serial_number: u32, + /// Define the supply control scheme of the native tokens controlled by the foundry. token_scheme: TokenScheme, + /// Define how the output can be unlocked in a transaction. unlock_conditions: UnlockConditions, + /// Features of the output. features: Features, + /// Immutable features of the output. immutable_features: Features, } @@ -627,19 +631,15 @@ pub(crate) mod dto { utils::serde::string, }; - /// Describes a foundry output that is controlled by an account. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct FoundryOutputDto { #[serde(rename = "type")] pub kind: u8, - // Amount of IOTA tokens held by the output. #[serde(with = "string")] pub amount: u64, - // Native tokens held by the output. #[serde(skip_serializing_if = "Vec::is_empty", default)] pub native_tokens: Vec, - // The serial number of the foundry with respect to the controlling account. pub serial_number: u32, pub token_scheme: TokenScheme, pub unlock_conditions: Vec, From 4e34d2271323e39adfe3672cf529cdcd7410aedd Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Wed, 13 Sep 2023 10:12:55 +0200 Subject: [PATCH 06/10] Some slots related changes --- sdk/src/types/block/mod.rs | 2 +- sdk/src/types/block/slot/commitment.rs | 33 +------------------------- sdk/src/types/block/slot/roots_id.rs | 2 +- sdk/tests/types/mod.rs | 1 + sdk/tests/types/slot.rs | 29 ++++++++++++++++++++++ 5 files changed, 33 insertions(+), 34 deletions(-) create mode 100644 sdk/tests/types/slot.rs diff --git a/sdk/src/types/block/mod.rs b/sdk/src/types/block/mod.rs index 004f8d997b..bc27b7bd79 100644 --- a/sdk/src/types/block/mod.rs +++ b/sdk/src/types/block/mod.rs @@ -62,4 +62,4 @@ pub use self::{ issuer_id::IssuerId, }; -pub(crate) const PROTOCOL_VERSION: u8 = 3; +pub const PROTOCOL_VERSION: u8 = 3; diff --git a/sdk/src/types/block/slot/commitment.rs b/sdk/src/types/block/slot/commitment.rs index 19dd7da10e..31496281fe 100644 --- a/sdk/src/types/block/slot/commitment.rs +++ b/sdk/src/types/block/slot/commitment.rs @@ -24,7 +24,7 @@ pub struct SlotCommitment { /// The commitment ID of the previous slot. #[cfg_attr(feature = "serde", serde(rename = "prevId"))] previous_slot_commitment_id: SlotCommitmentId, - /// A BLAKE2b-256 hash of concatenating multiple sparse merkle tree roots of a slot. + /// The digest of multiple sparse merkle tree roots of this slot. roots_id: RootsId, /// The sum of previous slot commitment cumulative weight and weight of issuers of accepted blocks within this /// slot. It is just an indication of "committed into" this slot, and can not strictly be used for evaluating @@ -89,34 +89,3 @@ impl SlotCommitment { SlotCommitmentId::from(bytes) } } - -#[cfg(test)] -mod test { - use core::str::FromStr; - - use super::SlotCommitment; - use crate::types::block::{ - slot::{RootsId, SlotCommitmentId, SlotIndex}, - PROTOCOL_VERSION, - }; - - #[test] - fn test() { - let commitment = SlotCommitment::new( - PROTOCOL_VERSION, - SlotIndex::new(10), - SlotCommitmentId::from_str( - "0x20e07a0ea344707d69a08b90be7ad14eec8326cf2b8b86c8ec23720fab8dcf8ec43a30e4a8cc3f1f", - ) - .unwrap(), - RootsId::from_str("0xcf077d276686ba64c0404b9eb2d15556782113c5a1985f262b70f9964d3bbd7f").unwrap(), - 5, - 10, - ); - // TODO: Independently verify this value - assert_eq!( - &commitment.id().to_string(), - "0x2f3ad38aa65d20ede9dcd6a045dccdd3332cf38192c4875308bb77116e8650880a00000000000000" - ) - } -} diff --git a/sdk/src/types/block/slot/roots_id.rs b/sdk/src/types/block/slot/roots_id.rs index bb3e7907ae..d9873d7303 100644 --- a/sdk/src/types/block/slot/roots_id.rs +++ b/sdk/src/types/block/slot/roots_id.rs @@ -1,7 +1,7 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -impl_id!(pub RootsId, 32, "A BLAKE2b-256 hash of concatenating multiple sparse merkle tree roots of a slot."); +impl_id!(pub RootsId, 32, "The digest of multiple sparse merkle tree roots of a slot."); #[cfg(feature = "serde")] string_serde_impl!(RootsId); diff --git a/sdk/tests/types/mod.rs b/sdk/tests/types/mod.rs index 4d873511da..1dcad12360 100644 --- a/sdk/tests/types/mod.rs +++ b/sdk/tests/types/mod.rs @@ -13,6 +13,7 @@ mod output_id; mod parents; mod payload; mod rent; +mod slot; mod tagged_data_payload; mod transaction_essence; mod transaction_id; diff --git a/sdk/tests/types/slot.rs b/sdk/tests/types/slot.rs new file mode 100644 index 0000000000..6282245160 --- /dev/null +++ b/sdk/tests/types/slot.rs @@ -0,0 +1,29 @@ +// Copyright 2023 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use core::str::FromStr; + +use iota_sdk::types::block::{ + slot::{RootsId, SlotCommitment, SlotCommitmentId, SlotIndex}, + PROTOCOL_VERSION, +}; + +#[test] +fn slot_commitment_id() { + let commitment = SlotCommitment::new( + PROTOCOL_VERSION, + SlotIndex::new(10), + SlotCommitmentId::from_str( + "0x20e07a0ea344707d69a08b90be7ad14eec8326cf2b8b86c8ec23720fab8dcf8ec43a30e4a8cc3f1f", + ) + .unwrap(), + RootsId::from_str("0xcf077d276686ba64c0404b9eb2d15556782113c5a1985f262b70f9964d3bbd7f").unwrap(), + 5, + 10, + ); + // TODO: Independently verify this value + assert_eq!( + &commitment.id().to_string(), + "0x2f3ad38aa65d20ede9dcd6a045dccdd3332cf38192c4875308bb77116e8650880a00000000000000" + ) +} From e787de9a0489f4b9b18d4072faf392d46d005935 Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Wed, 13 Sep 2023 10:22:06 +0200 Subject: [PATCH 07/10] Add missing getters --- sdk/src/types/block/slot/commitment.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sdk/src/types/block/slot/commitment.rs b/sdk/src/types/block/slot/commitment.rs index 31496281fe..4ba5947655 100644 --- a/sdk/src/types/block/slot/commitment.rs +++ b/sdk/src/types/block/slot/commitment.rs @@ -56,6 +56,11 @@ impl SlotCommitment { } } + /// Returns the protocol version of the [`SlotCommitment`]. + pub fn protocol_version(&self) -> u8 { + self.protocol_version + } + /// Returns the index of the [`SlotCommitment`]. pub fn index(&self) -> SlotIndex { self.index @@ -66,7 +71,7 @@ impl SlotCommitment { &self.previous_slot_commitment_id } - /// Returns the [`RootsId`] of the [`SlotCommitment`]. + /// Returns the roots ID of the [`SlotCommitment`]. pub fn roots_id(&self) -> &RootsId { &self.roots_id } @@ -76,7 +81,12 @@ impl SlotCommitment { self.cumulative_weight } - /// Derives the [`SlotCommitmentId`] of the [`SlotCommitment`]. + /// Returns the reference mana cost of the [`SlotCommitment`]. + pub fn reference_mana_cost(&self) -> u64 { + self.reference_mana_cost + } + + /// Computes the [`SlotCommitmentId`] of the [`SlotCommitment`]. pub fn id(&self) -> SlotCommitmentId { let mut bytes = [0u8; SlotCommitmentId::LENGTH]; let mut packer = SlicePacker::new(&mut bytes); From 7c5471d79cf7226dfa1354a70254cfd549b66d3c Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Wed, 13 Sep 2023 10:32:09 +0200 Subject: [PATCH 08/10] Nits --- sdk/src/types/block/slot/commitment.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sdk/src/types/block/slot/commitment.rs b/sdk/src/types/block/slot/commitment.rs index 4ba5947655..6f3b03b54a 100644 --- a/sdk/src/types/block/slot/commitment.rs +++ b/sdk/src/types/block/slot/commitment.rs @@ -22,7 +22,7 @@ pub struct SlotCommitment { /// It is calculated based on genesis timestamp and the duration of a slot. index: SlotIndex, /// The commitment ID of the previous slot. - #[cfg_attr(feature = "serde", serde(rename = "prevId"))] + #[cfg_attr(feature = "serde", serde(rename = "previousCommitmentId"))] previous_slot_commitment_id: SlotCommitmentId, /// The digest of multiple sparse merkle tree roots of this slot. roots_id: RootsId, @@ -90,10 +90,11 @@ impl SlotCommitment { pub fn id(&self) -> SlotCommitmentId { let mut bytes = [0u8; SlotCommitmentId::LENGTH]; let mut packer = SlicePacker::new(&mut bytes); - let hash: [u8; 32] = Blake2b256::digest(self.pack_to_vec()).into(); + let content = self.pack_to_vec(); + let content_hash: [u8; 32] = Blake2b256::digest(content).into(); // PANIC: packing to an array of bytes can't fail. - hash.pack(&mut packer).unwrap(); + content_hash.pack(&mut packer).unwrap(); self.index.pack(&mut packer).unwrap(); SlotCommitmentId::from(bytes) From 9f43c98515f6554a1202adca8d01117f7f2e59f7 Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Fri, 15 Sep 2023 17:30:50 +0200 Subject: [PATCH 09/10] Use serde_json macro --- sdk/tests/types/slot.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/sdk/tests/types/slot.rs b/sdk/tests/types/slot.rs index 72840df33e..69a611fa40 100644 --- a/sdk/tests/types/slot.rs +++ b/sdk/tests/types/slot.rs @@ -7,18 +7,16 @@ use packable::PackableExt; #[test] fn slot_commitment_id() { // Test from https://github.com/iotaledger/tips-draft/blob/tip46/tips/TIP-0046/tip-0046.md#slot-commitment-id-1 - let slot_commitment_json = r#" - { - "version":3, - "index":"10", - "previousCommitmentId":"0x4b024b3e47280d05272a7d136f0c464e4e136b734e6c427749413e286162077560652c007e37241a", - "rootsId":"0x75614402763f5f045c040334631b791b4d755d626d504b134a505c001c516549", - "cumulativeWeight":"100", - "referenceManaCost":"6000" - } - "#; + let slot_commitment_json = serde_json::json!({ + "version":3, + "index":"10", + "previousCommitmentId":"0x4b024b3e47280d05272a7d136f0c464e4e136b734e6c427749413e286162077560652c007e37241a", + "rootsId":"0x75614402763f5f045c040334631b791b4d755d626d504b134a505c001c516549", + "cumulativeWeight":"100", + "referenceManaCost":"6000" + }); - let slot_commitment = serde_json::from_str::(slot_commitment_json).unwrap(); + let slot_commitment = serde_json::from_value::(slot_commitment_json).unwrap(); let slot_commitment_bytes = slot_commitment.pack_to_vec(); assert_eq!( From 66e2db8879f19d7044cd02b5c3b0293831ca1886 Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Fri, 15 Sep 2023 17:40:09 +0200 Subject: [PATCH 10/10] Another serde macro --- sdk/tests/types/transaction_id.rs | 92 +++++++++++++++---------------- 1 file changed, 45 insertions(+), 47 deletions(-) diff --git a/sdk/tests/types/transaction_id.rs b/sdk/tests/types/transaction_id.rs index d5d8160f49..cd7f60a0e3 100644 --- a/sdk/tests/types/transaction_id.rs +++ b/sdk/tests/types/transaction_id.rs @@ -57,59 +57,57 @@ fn pack_unpack_valid() { #[test] fn transaction_id() { // Test from https://github.com/iotaledger/tips-draft/blob/tip46/tips/TIP-0046/tip-0046.md#transaction-id - let transaction_payload_json = r#" - { - "type":6, - "essence":{ - "type":2, - "networkId":"3650798313638353144", - "creationSlot":"28", - "contextInputs":[], - "inputs":[ - { - "type":0, - "transactionId":"0x24ff9b3038506fb1b406306a496001c3e24e2be07c838317922bf21d686a078f", - "transactionOutputIndex":10 - } - ], - "inputsCommitment":"0xb70c6f86a1ea03a59a71d73dcd07e2082bbdf0ce971faa21748348bca22fb023", - "outputs":[ - { - "type":3, - "amount":"10000", - "mana":"0", - "unlockConditions":[ - { + let transaction_payload_json = serde_json::json!({ + "type":6, + "essence":{ + "type":2, + "networkId":"3650798313638353144", + "creationSlot":"28", + "contextInputs":[], + "inputs":[ + { + "type":0, + "transactionId":"0x24ff9b3038506fb1b406306a496001c3e24e2be07c838317922bf21d686a078f", + "transactionOutputIndex":10 + } + ], + "inputsCommitment":"0xb70c6f86a1ea03a59a71d73dcd07e2082bbdf0ce971faa21748348bca22fb023", + "outputs":[ + { + "type":3, + "amount":"10000", + "mana":"0", + "unlockConditions":[ + { + "type":0, + "address":{ "type":0, - "address":{ - "type":0, - "pubKeyHash":"0xd9f84458286dc41cd34789dec566cd096cf47de991aa36a97aebfaea14128f6d" - } + "pubKeyHash":"0xd9f84458286dc41cd34789dec566cd096cf47de991aa36a97aebfaea14128f6d" } - ] - } - ], - "allotments":[], - "payload":{ - "type":5, - "tag":"0x1d7b3e11697264111e130b0e", - "data":"0x1d7b3e11697264111e130b0e" + } + ] } - }, - "unlocks":[ - { + ], + "allotments":[], + "payload":{ + "type":5, + "tag":"0x1d7b3e11697264111e130b0e", + "data":"0x1d7b3e11697264111e130b0e" + } + }, + "unlocks":[ + { + "type":0, + "signature":{ "type":0, - "signature":{ - "type":0, - "publicKey":"0x803361fe1effc899dca7f931d8ad07c01ba23aaa93f986adb04d4c17cf6368d8", - "signature":"0xccddbac3aaac413e0193e16da3449f30c183d0e7eaa7f303dc12ae0dbc9fb890e449a52f9056e7d952ea796fd3e5645f60d9eb98ed91cb3261720fb528d2a105" - } + "publicKey":"0x803361fe1effc899dca7f931d8ad07c01ba23aaa93f986adb04d4c17cf6368d8", + "signature":"0xccddbac3aaac413e0193e16da3449f30c183d0e7eaa7f303dc12ae0dbc9fb890e449a52f9056e7d952ea796fd3e5645f60d9eb98ed91cb3261720fb528d2a105" } - ] - } - "#; + } + ] + }); - let transaction_payload_dto = serde_json::from_str::(transaction_payload_json).unwrap(); + let transaction_payload_dto = serde_json::from_value::(transaction_payload_json).unwrap(); let transaction_payload = TransactionPayload::try_from_dto(transaction_payload_dto).unwrap(); let transaction_payload_bytes = Payload::from(transaction_payload.clone()).pack_to_vec();