Skip to content

Commit

Permalink
Add ImmutableAliasAddressUnlockCondition (#1101)
Browse files Browse the repository at this point in the history
* Add ImmutableAliasAddressUnlockCondition

* Copyright date

* Doc

* Use ImmutableAliasAddressUnlockCondition in foundries

* Fix tests

* Fix clippy
  • Loading branch information
thibault-martinez authored Feb 8, 2022
1 parent e440ab2 commit 33d1117
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 35 deletions.
38 changes: 36 additions & 2 deletions bee-api/bee-rest-api/src/types/dtos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use bee_message::{
feature_block::{FeatureBlock, IssuerFeatureBlock, MetadataFeatureBlock, SenderFeatureBlock, TagFeatureBlock},
unlock_condition::{
AddressUnlockCondition, DustDepositReturnUnlockCondition, ExpirationUnlockCondition,
GovernorAddressUnlockCondition, StateControllerAddressUnlockCondition, TimelockUnlockCondition,
UnlockCondition,
GovernorAddressUnlockCondition, ImmutableAliasAddressUnlockCondition,
StateControllerAddressUnlockCondition, TimelockUnlockCondition, UnlockCondition,
},
AliasId, AliasOutput, AliasOutputBuilder, BasicOutput, BasicOutputBuilder, FoundryOutput, FoundryOutputBuilder,
NativeToken, NftId, NftOutput, NftOutputBuilder, Output, TokenId, TokenScheme, TreasuryOutput,
Expand Down Expand Up @@ -968,6 +968,8 @@ pub enum UnlockConditionDto {
StateControllerAddress(StateControllerAddressUnlockConditionDto),
/// A governor address unlock condition.
GovernorAddress(GovernorAddressUnlockConditionDto),
/// An immutable alias address unlock condition.
ImmutableAliasAddress(ImmutableAliasAddressUnlockConditionDto),
}

impl<'de> serde::Deserialize<'de> for UnlockConditionDto {
Expand Down Expand Up @@ -1009,6 +1011,14 @@ impl<'de> serde::Deserialize<'de> for UnlockConditionDto {
|e| serde::de::Error::custom(format!("cannot deserialize governor unlock condition: {}", e)),
)?)
}
ImmutableAliasAddressUnlockCondition::KIND => UnlockConditionDto::ImmutableAliasAddress(
ImmutableAliasAddressUnlockConditionDto::deserialize(value).map_err(|e| {
serde::de::Error::custom(format!(
"cannot deserialize immutable alias address unlock condition: {}",
e
))
})?,
),
_ => return Err(serde::de::Error::custom("invalid unlock condition type")),
},
)
Expand All @@ -1029,6 +1039,7 @@ impl Serialize for UnlockConditionDto {
T4(&'a ExpirationUnlockConditionDto),
T5(&'a StateControllerAddressUnlockConditionDto),
T6(&'a GovernorAddressUnlockConditionDto),
T7(&'a ImmutableAliasAddressUnlockConditionDto),
}
#[derive(Serialize)]
struct TypedUnlockCondition<'a> {
Expand All @@ -1054,6 +1065,9 @@ impl Serialize for UnlockConditionDto {
UnlockConditionDto::GovernorAddress(o) => TypedUnlockCondition {
unlock_condition: UnlockConditionDto_::T6(o),
},
UnlockConditionDto::ImmutableAliasAddress(o) => TypedUnlockCondition {
unlock_condition: UnlockConditionDto_::T7(o),
},
};
unlock_condition.serialize(serializer)
}
Expand Down Expand Up @@ -1213,6 +1227,12 @@ pub struct TagFeatureBlockDto {
pub kind: u8,
pub tag: String,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ImmutableAliasAddressUnlockConditionDto {
#[serde(rename = "type")]
pub kind: u8,
pub address: AliasAddressDto,
}

impl UnlockConditionDto {
/// Return the unlock condition kind of a `UnlockConditionDto`.
Expand All @@ -1224,6 +1244,7 @@ impl UnlockConditionDto {
Self::Expiration(_) => ExpirationUnlockCondition::KIND,
Self::StateControllerAddress(_) => StateControllerAddressUnlockCondition::KIND,
Self::GovernorAddress(_) => GovernorAddressUnlockCondition::KIND,
Self::ImmutableAliasAddress(_) => ImmutableAliasAddressUnlockCondition::KIND,
}
}
}
Expand Down Expand Up @@ -1273,6 +1294,12 @@ impl From<&UnlockCondition> for UnlockConditionDto {
kind: GovernorAddressUnlockCondition::KIND,
address: v.address().into(),
}),
UnlockCondition::ImmutableAliasAddress(v) => {
Self::ImmutableAliasAddress(ImmutableAliasAddressUnlockConditionDto {
kind: ImmutableAliasAddressUnlockCondition::KIND,
address: v.address().into(),
})
}
}
}
}
Expand Down Expand Up @@ -1340,6 +1367,13 @@ impl TryFrom<&UnlockConditionDto> for UnlockCondition {
.try_into()
.map_err(|_e| Error::InvalidField("GovernorAddressUnlockCondition"))?,
)),
UnlockConditionDto::ImmutableAliasAddress(v) => {
Self::ImmutableAliasAddress(ImmutableAliasAddressUnlockCondition::new(
(&v.address)
.try_into()
.map_err(|_e| Error::InvalidField("ImmutableAliasAddressUnlockCondition"))?,
))
}
})
}
}
Expand Down
15 changes: 0 additions & 15 deletions bee-message/src/output/alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,18 +372,3 @@ fn verify_unlock_conditions(unlock_conditions: &UnlockConditions, alias_id: &Ali

verify_allowed_unlock_conditions(unlock_conditions, AliasOutput::ALLOWED_UNLOCK_CONDITIONS)
}

// #[inline]
// fn verify_controller(controller: &Address, alias_id: &AliasId) -> Result<(), Error> {
// match controller {
// Address::Ed25519(_) => {}
// Address::Alias(address) => {
// if address.id() == alias_id {
// return Err(Error::SelfControlledAliasOutput(*alias_id));
// }
// }
// _ => return Err(Error::InvalidControllerKind(controller.kind())),
// };
//
// Ok(())
// }
32 changes: 17 additions & 15 deletions bee-message/src/output/foundry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
// SPDX-License-Identifier: Apache-2.0

use crate::{
address::Address,
address::AliasAddress,
output::{
feature_block::{verify_allowed_feature_blocks, FeatureBlock, FeatureBlockFlags, FeatureBlocks},
unlock_condition::{
verify_allowed_unlock_conditions, AddressUnlockCondition, UnlockCondition, UnlockConditionFlags,
UnlockConditions,
verify_allowed_unlock_conditions, ImmutableAliasAddressUnlockCondition, UnlockCondition,
UnlockConditionFlags, UnlockConditions,
},
FoundryId, NativeToken, NativeTokens, OutputAmount,
},
Expand Down Expand Up @@ -166,7 +166,7 @@ impl FoundryOutput {
pub const KIND: u8 = 5;

/// The set of allowed [`UnlockCondition`]s for an [`FoundryOutput`].
const ALLOWED_UNLOCK_CONDITIONS: UnlockConditionFlags = UnlockConditionFlags::ADDRESS;
const ALLOWED_UNLOCK_CONDITIONS: UnlockConditionFlags = UnlockConditionFlags::IMMUTABLE_ALIAS_ADDRESS;
/// The set of allowed [`FeatureBlock`]s for an [`FoundryOutput`].
pub const ALLOWED_FEATURE_BLOCKS: FeatureBlockFlags = FeatureBlockFlags::METADATA;

Expand Down Expand Up @@ -226,9 +226,13 @@ impl FoundryOutput {

///
#[inline(always)]
pub fn address(&self) -> &Address {
// A FoundryOutput must have an AddressUnlockCondition.
if let UnlockCondition::Address(address) = self.unlock_conditions.get(AddressUnlockCondition::KIND).unwrap() {
pub fn address(&self) -> &AliasAddress {
// A FoundryOutput must have an ImmutableAliasAddressUnlockCondition.
if let UnlockCondition::ImmutableAliasAddress(address) = self
.unlock_conditions
.get(ImmutableAliasAddressUnlockCondition::KIND)
.unwrap()
{
address.address()
} else {
unreachable!();
Expand Down Expand Up @@ -370,14 +374,12 @@ fn verify_supply(circulating_supply: &U256, maximum_supply: &U256) -> Result<(),
}

fn verify_unlock_conditions(unlock_conditions: &UnlockConditions) -> Result<(), Error> {
if let Some(UnlockCondition::Address(unlock_condition)) = unlock_conditions.get(AddressUnlockCondition::KIND) {
match unlock_condition.address() {
Address::Alias(_) => {}
_ => return Err(Error::InvalidAddressKind(unlock_condition.address().kind())),
};
if unlock_conditions
.get(ImmutableAliasAddressUnlockCondition::KIND)
.is_none()
{
Err(Error::MissingAddressUnlockCondition)
} else {
return Err(Error::MissingAddressUnlockCondition);
verify_allowed_unlock_conditions(unlock_conditions, FoundryOutput::ALLOWED_UNLOCK_CONDITIONS)
}

verify_allowed_unlock_conditions(unlock_conditions, FoundryOutput::ALLOWED_UNLOCK_CONDITIONS)
}
28 changes: 28 additions & 0 deletions bee-message/src/output/unlock_condition/immutable_alias_address.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2022 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use crate::address::AliasAddress;

use derive_more::From;

/// Defines the permanent [`AliasAddress`] that owns this output.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, From, packable::Packable)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub struct ImmutableAliasAddressUnlockCondition(AliasAddress);

impl ImmutableAliasAddressUnlockCondition {
/// The [`UnlockCondition`](crate::output::UnlockCondition) kind of an [`ImmutableAliasAddressUnlockCondition`].
pub const KIND: u8 = 6;

/// Creates a new [`ImmutableAliasAddressUnlockCondition`].
#[inline(always)]
pub fn new(address: AliasAddress) -> Self {
Self(address)
}

/// Returns the address of a [`ImmutableAliasAddressUnlockCondition`].
#[inline(always)]
pub fn address(&self) -> &AliasAddress {
&self.0
}
}
11 changes: 10 additions & 1 deletion bee-message/src/output/unlock_condition/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod address;
mod dust_deposit_return;
mod expiration;
mod governor_address;
mod immutable_alias_address;
mod state_controller_address;
mod timelock;

Expand All @@ -13,6 +14,7 @@ pub(crate) use dust_deposit_return::DustDepositAmount;
pub use dust_deposit_return::DustDepositReturnUnlockCondition;
pub use expiration::ExpirationUnlockCondition;
pub use governor_address::GovernorAddressUnlockCondition;
pub use immutable_alias_address::ImmutableAliasAddressUnlockCondition;
pub use state_controller_address::StateControllerAddressUnlockCondition;
pub use timelock::TimelockUnlockCondition;

Expand Down Expand Up @@ -51,6 +53,9 @@ pub enum UnlockCondition {
/// A governor address unlock condition.
#[packable(tag = GovernorAddressUnlockCondition::KIND)]
GovernorAddress(GovernorAddressUnlockCondition),
/// An immutable alias address unlock condition.
#[packable(tag = ImmutableAliasAddressUnlockCondition::KIND)]
ImmutableAliasAddress(ImmutableAliasAddressUnlockCondition),
}

impl UnlockCondition {
Expand All @@ -63,6 +68,7 @@ impl UnlockCondition {
Self::Expiration(_) => ExpirationUnlockCondition::KIND,
Self::StateControllerAddress(_) => StateControllerAddressUnlockCondition::KIND,
Self::GovernorAddress(_) => GovernorAddressUnlockCondition::KIND,
Self::ImmutableAliasAddress(_) => ImmutableAliasAddressUnlockCondition::KIND,
}
}

Expand All @@ -75,6 +81,7 @@ impl UnlockCondition {
Self::Expiration(_) => UnlockConditionFlags::EXPIRATION,
Self::StateControllerAddress(_) => UnlockConditionFlags::STATE_CONTROLLER_ADDRESS,
Self::GovernorAddress(_) => UnlockConditionFlags::GOVERNOR_ADDRESS,
Self::ImmutableAliasAddress(_) => UnlockConditionFlags::IMMUTABLE_ALIAS_ADDRESS,
}
}
}
Expand All @@ -90,6 +97,7 @@ create_bitflags!(
(EXPIRATION, ExpirationUnlockCondition),
(STATE_CONTROLLER_ADDRESS, StateControllerAddressUnlockCondition),
(GOVERNOR_ADDRESS, GovernorAddressUnlockCondition),
(IMMUTABLE_ALIAS_ADDRESS, ImmutableAliasAddressUnlockCondition),
]
);

Expand Down Expand Up @@ -179,7 +187,8 @@ mod test {
UnlockConditionFlags::TIMELOCK,
UnlockConditionFlags::EXPIRATION,
UnlockConditionFlags::STATE_CONTROLLER_ADDRESS,
UnlockConditionFlags::GOVERNOR_ADDRESS
UnlockConditionFlags::GOVERNOR_ADDRESS,
UnlockConditionFlags::IMMUTABLE_ALIAS_ADDRESS
]
);
}
Expand Down
6 changes: 4 additions & 2 deletions bee-test/src/rand/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ pub mod feature_block;
pub mod unlock_condition;

use bee_ledger::types::{ConsumedOutput, CreatedOutput, TreasuryOutput, Unspent};
use bee_message::output::{self, unlock_condition::AddressUnlockCondition, Output, OutputId, OUTPUT_INDEX_RANGE};
use bee_message::output::{
self, unlock_condition::ImmutableAliasAddressUnlockCondition, Output, OutputId, OUTPUT_INDEX_RANGE,
};

use primitive_types::U256;

Expand Down Expand Up @@ -88,7 +90,7 @@ pub fn rand_foundry_output() -> output::FoundryOutput {
)
.unwrap()
.with_feature_blocks(feature_blocks)
.add_unlock_condition(AddressUnlockCondition::new(rand_alias_address().into()).into())
.add_unlock_condition(ImmutableAliasAddressUnlockCondition::new(rand_alias_address()).into())
.finish()
.unwrap()
}
Expand Down

0 comments on commit 33d1117

Please sign in to comment.