Skip to content

Commit

Permalink
Remove state_metadata from AnchorOutput (#1651)
Browse files Browse the repository at this point in the history
  • Loading branch information
thibault-martinez authored Nov 20, 2023
1 parent c19bb50 commit adac8ae
Show file tree
Hide file tree
Showing 6 changed files with 17 additions and 68 deletions.
7 changes: 0 additions & 7 deletions bindings/nodejs/lib/types/block/output/output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,32 +243,25 @@ class AnchorOutput extends ImmutableFeaturesOutput {
* The amount of (stored) Mana held by the output.
*/
readonly mana: u64;
/**
* Metadata that can only be changed by the state controller.
*/
readonly stateMetadata?: HexEncodedString;

/**
* @param amount The amount of the output.
* @param mana The amount of stored mana.
* @param anchorId The anchor ID as hex-encoded string.
* @param stateIndex A counter that must increase by 1 every time the anchor output is state transitioned.
* @param unlockConditions The unlock conditions of the output.
* @param stateMetadata Metadata that can only be changed by the state controller.
*/
constructor(
amount: u64,
mana: u64,
anchorId: AnchorId,
stateIndex: number,
unlockConditions: UnlockCondition[],
stateMetadata?: HexEncodedString,
) {
super(OutputType.Account, amount, unlockConditions);
this.anchorId = anchorId;
this.stateIndex = stateIndex;
this.mana = mana;
this.stateMetadata = stateMetadata;
}
}

Expand Down
3 changes: 0 additions & 3 deletions bindings/python/iota_sdk/types/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,6 @@ class AnchorOutput:
Features that add utility to the output but do not impose unlocking conditions.
immutable_features :
Features that add utility to the output but do not impose unlocking conditions. These features need to be kept in future transitions of the UTXO state machine.
state_metadata :
Metadata that can only be changed by the state controller.
type :
The type of output.
"""
Expand All @@ -166,7 +164,6 @@ class AnchorOutput:
metadata=config(
decoder=deserialize_features
))
state_metadata: Optional[HexStr] = None
type: int = field(
default_factory=lambda: int(
OutputType.Anchor),
Expand Down
5 changes: 1 addition & 4 deletions sdk/src/types/block/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ use crate::types::block::{
output::{
feature::{BlockIssuerKeyCount, FeatureCount},
unlock_condition::UnlockConditionCount,
AccountId, AnchorId, ChainId, MetadataFeatureLength, NativeTokenCount, NftId, OutputIndex, StateMetadataLength,
TagFeatureLength,
AccountId, AnchorId, ChainId, MetadataFeatureLength, NativeTokenCount, NftId, OutputIndex, TagFeatureLength,
},
payload::{ContextInputCount, InputCount, OutputCount, TagLength, TaggedDataLength},
protocol::ProtocolParametersHash,
Expand Down Expand Up @@ -101,7 +100,6 @@ pub enum Error {
byte: u8,
},
InvalidBlockLength(usize),
InvalidStateMetadataLength(<StateMetadataLength as TryFrom<usize>>::Error),
InvalidManaValue(u64),
InvalidMetadataFeatureLength(<MetadataFeatureLength as TryFrom<usize>>::Error),
InvalidNativeTokenCount(<NativeTokenCount as TryFrom<usize>>::Error),
Expand Down Expand Up @@ -300,7 +298,6 @@ impl fmt::Display for Error {
Self::InvalidInputCount(count) => write!(f, "invalid input count: {count}"),
Self::InvalidInputOutputIndex(index) => write!(f, "invalid input or output index: {index}"),
Self::InvalidBlockLength(length) => write!(f, "invalid block length {length}"),
Self::InvalidStateMetadataLength(length) => write!(f, "invalid state metadata length: {length}"),
Self::InvalidManaValue(mana) => write!(f, "invalid mana value: {mana}"),
Self::InvalidMetadataFeatureLength(length) => {
write!(f, "invalid metadata feature length: {length}")
Expand Down
68 changes: 16 additions & 52 deletions sdk/src/types/block/output/anchor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ use alloc::{collections::BTreeSet, vec::Vec};

use hashbrown::HashMap;
use packable::{
bounded::BoundedU16,
error::{UnpackError, UnpackErrorExt},
packer::Packer,
prefix::BoxedSlicePrefix,
unpacker::Unpacker,
Packable, PackableExt,
};
Expand Down Expand Up @@ -44,7 +42,11 @@ impl From<&OutputId> for AnchorId {
impl AnchorId {
///
pub fn or_from_output_id(self, output_id: &OutputId) -> Self {
if self.is_null() { Self::from(output_id) } else { self }
if self.is_null() {
Self::from(output_id)
} else {
self
}
}
}

Expand Down Expand Up @@ -94,7 +96,6 @@ pub struct AnchorOutputBuilder {
native_tokens: BTreeSet<NativeToken>,
anchor_id: AnchorId,
state_index: u32,
state_metadata: Vec<u8>,
unlock_conditions: BTreeSet<UnlockCondition>,
features: BTreeSet<Feature>,
immutable_features: BTreeSet<Feature>,
Expand All @@ -120,7 +121,6 @@ impl AnchorOutputBuilder {
native_tokens: BTreeSet::new(),
anchor_id,
state_index: 0,
state_metadata: Vec::new(),
unlock_conditions: BTreeSet::new(),
features: BTreeSet::new(),
immutable_features: BTreeSet::new(),
Expand Down Expand Up @@ -176,13 +176,6 @@ impl AnchorOutputBuilder {
self
}

///
#[inline(always)]
pub fn with_state_metadata(mut self, state_metadata: impl Into<Vec<u8>>) -> Self {
self.state_metadata = state_metadata.into();
self
}

/// Adds an [`UnlockCondition`] to the builder, if one does not already exist of that type.
#[inline(always)]
pub fn add_unlock_condition(mut self, unlock_condition: impl Into<UnlockCondition>) -> Self {
Expand Down Expand Up @@ -269,12 +262,6 @@ impl AnchorOutputBuilder {

///
pub fn finish(self) -> Result<AnchorOutput, Error> {
let state_metadata = self
.state_metadata
.into_boxed_slice()
.try_into()
.map_err(Error::InvalidStateMetadataLength)?;

verify_index_counter(&self.anchor_id, self.state_index)?;

let unlock_conditions = UnlockConditions::from_set(self.unlock_conditions)?;
Expand All @@ -295,7 +282,6 @@ impl AnchorOutputBuilder {
native_tokens: NativeTokens::from_set(self.native_tokens)?,
anchor_id: self.anchor_id,
state_index: self.state_index,
state_metadata,
unlock_conditions,
features,
immutable_features,
Expand Down Expand Up @@ -323,16 +309,13 @@ impl From<&AnchorOutput> for AnchorOutputBuilder {
native_tokens: output.native_tokens.iter().copied().collect(),
anchor_id: output.anchor_id,
state_index: output.state_index,
state_metadata: output.state_metadata.to_vec(),
unlock_conditions: output.unlock_conditions.iter().cloned().collect(),
features: output.features.iter().cloned().collect(),
immutable_features: output.immutable_features.iter().cloned().collect(),
}
}
}

pub(crate) type StateMetadataLength = BoundedU16<0, { AnchorOutput::STATE_METADATA_LENGTH_MAX }>;

/// Describes an anchor in the ledger that can be controlled by the state and governance controllers.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct AnchorOutput {
Expand All @@ -345,8 +328,6 @@ pub struct AnchorOutput {
anchor_id: AnchorId,
/// A counter that must increase by 1 every time the anchor is state transitioned.
state_index: u32,
/// Metadata that can only be changed by the state controller.
state_metadata: BoxedSlicePrefix<u8, StateMetadataLength>,
/// Define how the output can be unlocked in a transaction.
unlock_conditions: UnlockConditions,
/// Features of the output.
Expand All @@ -358,8 +339,6 @@ pub struct AnchorOutput {
impl AnchorOutput {
/// The [`Output`](crate::types::block::output::Output) kind of an [`AnchorOutput`].
pub const KIND: u8 = 2;
/// Maximum possible length in bytes of the state metadata.
pub const STATE_METADATA_LENGTH_MAX: u16 = 8192;
/// The set of allowed [`UnlockCondition`]s for an [`AnchorOutput`].
pub const ALLOWED_UNLOCK_CONDITIONS: UnlockConditionFlags =
UnlockConditionFlags::STATE_CONTROLLER_ADDRESS.union(UnlockConditionFlags::GOVERNOR_ADDRESS);
Expand Down Expand Up @@ -416,11 +395,12 @@ impl AnchorOutput {
self.state_index
}

///
#[inline(always)]
pub fn state_metadata(&self) -> &[u8] {
&self.state_metadata
}
// TODO https://github.com/iotaledger/iota-sdk/issues/1650
// ///
// #[inline(always)]
// pub fn state_metadata(&self) -> &[u8] {
// &self.state_metadata
// }

///
#[inline(always)]
Expand Down Expand Up @@ -527,9 +507,9 @@ impl AnchorOutput {
}
} else if next_state.state_index == current_state.state_index {
// Governance transition.
if current_state.amount != next_state.amount
|| current_state.native_tokens != next_state.native_tokens
|| current_state.state_metadata != next_state.state_metadata
if current_state.amount != next_state.amount || current_state.native_tokens != next_state.native_tokens
// TODO https://github.com/iotaledger/iota-sdk/issues/1650
// || current_state.state_metadata != next_state.state_metadata
{
return Err(StateTransitionError::MutatedFieldWithoutRights);
}
Expand Down Expand Up @@ -607,7 +587,6 @@ impl Packable for AnchorOutput {
self.native_tokens.pack(packer)?;
self.anchor_id.pack(packer)?;
self.state_index.pack(packer)?;
self.state_metadata.pack(packer)?;
self.unlock_conditions.pack(packer)?;
self.features.pack(packer)?;
self.immutable_features.pack(packer)?;
Expand All @@ -626,8 +605,6 @@ impl Packable for AnchorOutput {
let native_tokens = NativeTokens::unpack::<_, VERIFY>(unpacker, &())?;
let anchor_id = AnchorId::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
let state_index = u32::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
let state_metadata = BoxedSlicePrefix::<u8, StateMetadataLength>::unpack::<_, VERIFY>(unpacker, &())
.map_packable_err(|err| Error::InvalidStateMetadataLength(err.into_prefix_err().into()))?;

if VERIFY {
verify_index_counter(&anchor_id, state_index).map_err(UnpackError::Packable)?;
Expand Down Expand Up @@ -658,7 +635,6 @@ impl Packable for AnchorOutput {
native_tokens,
anchor_id,
state_index,
state_metadata,
unlock_conditions,
features,
immutable_features,
Expand Down Expand Up @@ -701,14 +677,13 @@ fn verify_unlock_conditions(unlock_conditions: &UnlockConditions, anchor_id: &An

#[cfg(feature = "serde")]
pub(crate) mod dto {
use alloc::boxed::Box;

use serde::{Deserialize, Serialize};

use super::*;
use crate::{
types::block::{output::unlock_condition::dto::UnlockConditionDto, Error},
utils::serde::{prefix_hex_bytes, string},
utils::serde::string,
};

/// Describes an anchor in the ledger that can be controlled by the state and governance controllers.
Expand All @@ -725,8 +700,6 @@ pub(crate) mod dto {
pub native_tokens: Vec<NativeToken>,
pub anchor_id: AnchorId,
pub state_index: u32,
#[serde(skip_serializing_if = "<[_]>::is_empty", default, with = "prefix_hex_bytes")]
pub state_metadata: Box<[u8]>,
pub unlock_conditions: Vec<UnlockConditionDto>,
#[serde(skip_serializing_if = "Vec::is_empty", default)]
pub features: Vec<Feature>,
Expand All @@ -743,7 +716,6 @@ pub(crate) mod dto {
native_tokens: value.native_tokens().to_vec(),
anchor_id: *value.anchor_id(),
state_index: value.state_index(),
state_metadata: value.state_metadata().into(),
unlock_conditions: value.unlock_conditions().iter().map(Into::into).collect::<_>(),
features: value.features().to_vec(),
immutable_features: value.immutable_features().to_vec(),
Expand All @@ -760,8 +732,7 @@ pub(crate) mod dto {
.with_state_index(dto.state_index)
.with_native_tokens(dto.native_tokens)
.with_features(dto.features)
.with_immutable_features(dto.immutable_features)
.with_state_metadata(dto.state_metadata);
.with_immutable_features(dto.immutable_features);

for u in dto.unlock_conditions {
builder = builder.add_unlock_condition(UnlockCondition::from(u));
Expand All @@ -779,7 +750,6 @@ pub(crate) mod dto {
native_tokens: Option<Vec<NativeToken>>,
anchor_id: &AnchorId,
state_index: u32,
state_metadata: Option<Vec<u8>>,
unlock_conditions: Vec<UnlockConditionDto>,
features: Option<Vec<Feature>>,
immutable_features: Option<Vec<Feature>>,
Expand All @@ -797,10 +767,6 @@ pub(crate) mod dto {
builder = builder.with_native_tokens(native_tokens);
}

if let Some(state_metadata) = state_metadata {
builder = builder.with_state_metadata(state_metadata);
}

let unlock_conditions = unlock_conditions
.into_iter()
.map(UnlockCondition::from)
Expand Down Expand Up @@ -852,7 +818,6 @@ mod tests {
Some(output.native_tokens().to_vec()),
output.anchor_id(),
output.state_index(),
output.state_metadata().to_owned().into(),
output.unlock_conditions().iter().map(Into::into).collect(),
Some(output.features().to_vec()),
Some(output.immutable_features().to_vec()),
Expand All @@ -871,7 +836,6 @@ mod tests {
Some(builder.native_tokens.iter().copied().collect()),
&builder.anchor_id,
builder.state_index,
builder.state_metadata.to_owned().into(),
builder.unlock_conditions.iter().map(Into::into).collect(),
Some(builder.features.iter().cloned().collect()),
Some(builder.immutable_features.iter().cloned().collect()),
Expand Down
1 change: 0 additions & 1 deletion sdk/src/types/block/output/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ pub use self::{
unlock_condition::{UnlockCondition, UnlockConditions},
};
pub(crate) use self::{
anchor::StateMetadataLength,
feature::{MetadataFeatureLength, TagFeatureLength},
native_token::NativeTokenCount,
output_id::OutputIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ where
/// address: None,
/// immutable_metadata: Some(b"some immutable account metadata".to_vec()),
/// metadata: Some(b"some account metadata".to_vec()),
/// state_metadata: Some(b"some account state metadata".to_vec()),
/// };
///
/// let transaction = account.create_account_output(params, None).await?;
Expand Down

0 comments on commit adac8ae

Please sign in to comment.