Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ImmutableAliasAddressUnlockCondition #1101

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -930,6 +930,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 @@ -971,6 +973,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
))
Comment on lines +978 to +981
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rustfmt why

})?,
),
_ => return Err(serde::de::Error::custom("invalid unlock condition type")),
},
)
Expand All @@ -991,6 +1001,7 @@ impl Serialize for UnlockConditionDto {
T4(&'a ExpirationUnlockConditionDto),
T5(&'a StateControllerAddressUnlockConditionDto),
T6(&'a GovernorAddressUnlockConditionDto),
T7(&'a ImmutableAliasAddressUnlockConditionDto),
}
#[derive(Serialize)]
struct TypedUnlockCondition<'a> {
Expand All @@ -1016,6 +1027,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 @@ -1175,6 +1189,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 @@ -1186,6 +1206,7 @@ impl UnlockConditionDto {
Self::Expiration(_) => ExpirationUnlockCondition::KIND,
Self::StateControllerAddress(_) => StateControllerAddressUnlockCondition::KIND,
Self::GovernorAddress(_) => GovernorAddressUnlockCondition::KIND,
Self::ImmutableAliasAddress(_) => ImmutableAliasAddressUnlockCondition::KIND,
}
}
}
Expand Down Expand Up @@ -1235,6 +1256,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 @@ -1302,6 +1329,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)
}
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