Skip to content

Commit

Permalink
feat: add block issuer feature (#984)
Browse files Browse the repository at this point in the history
* init

* init

* feat: block issuer feature

* add rand

* some fixes

* fix more issues

* change order in rand

* fix no_std for box

* fix no_std for macro

* remove unnecessary imports

* too much

* fix error order

* addressing comments

* Update sdk/src/types/block/rand/public_key.rs

Co-authored-by: Thoralf-M <[email protected]>

* Update sdk/src/types/block/output/feature/block_issuer.rs

Co-authored-by: Thoralf-M <[email protected]>

* Update sdk/src/types/block/output/feature/block_issuer.rs

Co-authored-by: Thoralf-M <[email protected]>

* Update sdk/src/types/block/output/feature/block_issuer.rs

Co-authored-by: Thoralf-M <[email protected]>

* fixing issues

* unused imports

* remove alloc

* add string ser-de for slot index

* fmt

* clippyt

* Update sdk/src/types/block/rand/output/feature.rs

Co-authored-by: Thoralf-M <[email protected]>

* Update sdk/src/types/block/output/feature/block_issuer.rs

Co-authored-by: Alexandcoats <[email protected]>

* Update sdk/src/types/block/output/feature/block_issuer.rs

Co-authored-by: Alexandcoats <[email protected]>

* address issues

* use btreeset

* fix

* add uniq and sorted public keys

* fmt

* fmt

* clippy

* fix non-std

* fmt

* remove default

---------

Co-authored-by: Thoralf-M <[email protected]>
Co-authored-by: Alexandcoats <[email protected]>
  • Loading branch information
3 people authored Aug 7, 2023
1 parent 46578d4 commit 901d363
Show file tree
Hide file tree
Showing 34 changed files with 270 additions and 52 deletions.
2 changes: 0 additions & 2 deletions sdk/src/types/block/address/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ impl core::fmt::Debug for AccountAddress {
}

mod dto {
use alloc::format;

use serde::{Deserialize, Serialize};

use super::*;
Expand Down
2 changes: 0 additions & 2 deletions sdk/src/types/block/address/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ impl core::fmt::Debug for Ed25519Address {
}

mod dto {
use alloc::format;

use serde::{Deserialize, Serialize};

use super::*;
Expand Down
2 changes: 0 additions & 2 deletions sdk/src/types/block/address/nft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ impl core::fmt::Debug for NftAddress {
}

mod dto {
use alloc::format;

use serde::{Deserialize, Serialize};

use super::*;
Expand Down
2 changes: 0 additions & 2 deletions sdk/src/types/block/context_input/block_issuance_credit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ impl BlockIssuanceCreditContextInput {
}

mod dto {
use alloc::format;

use serde::{Deserialize, Serialize};

use super::*;
Expand Down
2 changes: 0 additions & 2 deletions sdk/src/types/block/context_input/commitment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ impl CommitmentContextInput {
}

mod dto {
use alloc::format;

use serde::{Deserialize, Serialize};

use super::*;
Expand Down
2 changes: 0 additions & 2 deletions sdk/src/types/block/context_input/reward.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ impl RewardContextInput {
}

mod dto {
use alloc::format;

use serde::{Deserialize, Serialize};

use super::*;
Expand Down
6 changes: 5 additions & 1 deletion sdk/src/types/block/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crypto::Error as CryptoError;
use prefix_hex::Error as HexError;
use primitive_types::U256;

use super::{mana::AllotmentCount, protocol::ProtocolParametersHash};
use super::{mana::AllotmentCount, protocol::ProtocolParametersHash, public_key::PublicKeyCount};
use crate::types::block::{
input::UtxoInput,
output::{
Expand Down Expand Up @@ -94,6 +94,7 @@ pub enum Error {
expected: ProtocolParametersHash,
actual: ProtocolParametersHash,
},
InvalidPublicKeyCount(<PublicKeyCount as TryFrom<usize>>::Error),
InvalidReferenceIndex(<UnlockIndex as TryFrom<u16>>::Error),
InvalidSignature,
InvalidSignatureKind(u8),
Expand Down Expand Up @@ -132,6 +133,7 @@ pub enum Error {
expected: u8,
actual: u8,
},
PublicKeysNotUniqueSorted,
RemainingBytesAfterBlock,
SelfControlledAccountOutput(AccountId),
SelfDepositNft(NftId),
Expand Down Expand Up @@ -249,6 +251,7 @@ impl fmt::Display for Error {
"invalid protocol parameters hash: expected {expected} but got {actual}"
)
}
Self::InvalidPublicKeyCount(count) => write!(f, "invalid public key count: {count}"),
Self::InvalidReferenceIndex(index) => write!(f, "invalid reference index: {index}"),
Self::InvalidSignature => write!(f, "invalid signature provided"),
Self::InvalidSignatureKind(k) => write!(f, "invalid signature kind: {k}"),
Expand Down Expand Up @@ -308,6 +311,7 @@ impl fmt::Display for Error {
Self::ProtocolVersionMismatch { expected, actual } => {
write!(f, "protocol version mismatch: expected {expected} but got {actual}")
}
Self::PublicKeysNotUniqueSorted => write!(f, "public keys are not unique and/or sorted"),
Self::RemainingBytesAfterBlock => {
write!(f, "remaining bytes after block")
}
Expand Down
2 changes: 0 additions & 2 deletions sdk/src/types/block/input/utxo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ impl core::fmt::Debug for UtxoInput {
}

mod dto {
use alloc::format;

use serde::{Deserialize, Serialize};

use super::*;
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/types/block/macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ macro_rules! impl_serde_typed_dto {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let dto = <$dto>::deserialize(d)?;
if dto.kind != Self::KIND {
return Err(serde::de::Error::custom(format!(
return Err(serde::de::Error::custom(alloc::format!(
"invalid {} type: expected {}, found {}",
$type_str,
Self::KIND,
Expand Down
97 changes: 97 additions & 0 deletions sdk/src/types/block/output/feature/block_issuer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright 2023 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use alloc::vec::Vec;

use crate::types::block::{
public_key::{PublicKey, PublicKeys},
slot::SlotIndex,
Error,
};

/// This feature defines the public keys with which a signature from the containing
/// account's Block Issuance Credit can be verified in order to burn Mana.
#[derive(Clone, Debug, Eq, PartialEq, Hash, packable::Packable)]
#[packable(unpack_error = Error)]
pub struct BlockIssuerFeature {
/// The slot index at which the Block Issuer Feature expires and can be removed.
expiry_slot: SlotIndex,
/// The Block Issuer Keys.
public_keys: PublicKeys,
}

impl BlockIssuerFeature {
/// The [`Feature`](crate::types::block::output::Feature) kind of a [`BlockIssuerFeature`].
pub const KIND: u8 = 4;

/// Creates a new [`BlockIssuerFeature`].
#[inline(always)]
pub fn new(
expiry_slot: impl Into<SlotIndex>,
public_keys: impl IntoIterator<Item = PublicKey>,
) -> Result<Self, Error> {
let public_keys = PublicKeys::from_vec(public_keys.into_iter().collect::<Vec<PublicKey>>())?;
Ok(Self {
expiry_slot: expiry_slot.into(),
public_keys,
})
}

/// Returns the Slot Index at which the Block Issuer Feature expires and can be removed.
pub fn expiry_slot(&self) -> SlotIndex {
self.expiry_slot
}

/// Returns the Block Issuer Keys.
pub fn public_keys(&self) -> &[PublicKey] {
&self.public_keys
}
}

mod dto {
use alloc::vec::Vec;

use serde::{Deserialize, Serialize};

use super::BlockIssuerFeature;
use crate::types::block::{
public_key::{dto::PublicKeyDto, PublicKey},
slot::SlotIndex,
Error,
};

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct BlockIssuerFeatureDto {
#[serde(rename = "type")]
kind: u8,
expiry_slot: SlotIndex,
keys: Vec<PublicKeyDto>,
}

impl From<&BlockIssuerFeature> for BlockIssuerFeatureDto {
fn from(value: &BlockIssuerFeature) -> Self {
Self {
kind: BlockIssuerFeature::KIND,
expiry_slot: value.expiry_slot,
keys: value.public_keys.iter().map(|key| key.into()).collect(),
}
}
}

impl TryFrom<BlockIssuerFeatureDto> for BlockIssuerFeature {
type Error = Error;

fn try_from(value: BlockIssuerFeatureDto) -> Result<Self, Self::Error> {
let keys = value
.keys
.into_iter()
.map(PublicKey::try_from)
.collect::<Result<Vec<PublicKey>, Error>>()?;

Self::new(value.expiry_slot, keys)
}
}

impl_serde_typed_dto!(BlockIssuerFeature, BlockIssuerFeatureDto, "block issuer feature");
}
2 changes: 0 additions & 2 deletions sdk/src/types/block/output/feature/issuer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ impl IssuerFeature {
}

mod dto {
use alloc::format;

use serde::{Deserialize, Serialize};

use super::*;
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/types/block/output/feature/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl core::fmt::Debug for MetadataFeature {
}

mod dto {
use alloc::{borrow::Cow, format};
use alloc::borrow::Cow;

use serde::{Deserialize, Serialize};

Expand Down
32 changes: 31 additions & 1 deletion sdk/src/types/block/output/feature/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2021-2022 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

mod block_issuer;
mod issuer;
mod metadata;
mod sender;
Expand All @@ -15,7 +16,8 @@ use iterator_sorted::is_unique_sorted;
use packable::{bounded::BoundedU8, prefix::BoxedSlicePrefix, Packable};

pub use self::{
issuer::IssuerFeature, metadata::MetadataFeature, sender::SenderFeature, staking::StakingFeature, tag::TagFeature,
block_issuer::BlockIssuerFeature, issuer::IssuerFeature, metadata::MetadataFeature, sender::SenderFeature,
staking::StakingFeature, tag::TagFeature,
};
pub(crate) use self::{metadata::MetadataFeatureLength, tag::TagFeatureLength};
use crate::types::block::{create_bitflags, Error};
Expand All @@ -38,6 +40,9 @@ pub enum Feature {
/// A tag feature.
#[packable(tag = TagFeature::KIND)]
Tag(TagFeature),
/// A block issuer feature.
#[packable(tag = BlockIssuerFeature::KIND)]
BlockIssuer(BlockIssuerFeature),
/// A staking feature.
#[packable(tag = StakingFeature::KIND)]
Staking(StakingFeature),
Expand All @@ -62,6 +67,7 @@ impl core::fmt::Debug for Feature {
Self::Issuer(feature) => feature.fmt(f),
Self::Metadata(feature) => feature.fmt(f),
Self::Tag(feature) => feature.fmt(f),
Self::BlockIssuer(feature) => feature.fmt(f),
Self::Staking(feature) => feature.fmt(f),
}
}
Expand All @@ -75,6 +81,7 @@ impl Feature {
Self::Issuer(_) => IssuerFeature::KIND,
Self::Metadata(_) => MetadataFeature::KIND,
Self::Tag(_) => TagFeature::KIND,
Self::BlockIssuer(_) => BlockIssuerFeature::KIND,
Self::Staking(_) => StakingFeature::KIND,
}
}
Expand All @@ -86,6 +93,7 @@ impl Feature {
Self::Issuer(_) => FeatureFlags::ISSUER,
Self::Metadata(_) => FeatureFlags::METADATA,
Self::Tag(_) => FeatureFlags::TAG,
Self::BlockIssuer(_) => FeatureFlags::BLOCK_ISSUER,
Self::Staking(_) => FeatureFlags::STAKING,
}
}
Expand Down Expand Up @@ -150,6 +158,21 @@ impl Feature {
}
}

/// Checks whether the feature is a [`BlockIssuerFeature`].
pub fn is_block_issuer(&self) -> bool {
matches!(self, Self::BlockIssuer(_))
}

/// Gets the feature as an actual [`BlockIssuerFeature`].
/// NOTE: Will panic if the feature is not a [`BlockIssuerFeature`].
pub fn as_block_issuer(&self) -> &BlockIssuerFeature {
if let Self::BlockIssuer(feature) = self {
feature
} else {
panic!("invalid downcast of non-BlockIssuerFeature");
}
}

/// Checks whether the feature is a [`StakingFeature`].
pub fn is_staking(&self) -> bool {
matches!(self, Self::Staking(_))
Expand All @@ -175,6 +198,7 @@ create_bitflags!(
(ISSUER, IssuerFeature),
(METADATA, MetadataFeature),
(TAG, TagFeature),
(BLOCK_ISSUER, BlockIssuerFeature),
(STAKING, StakingFeature),
]
);
Expand Down Expand Up @@ -270,6 +294,11 @@ impl Features {
self.get(TagFeature::KIND).map(Feature::as_tag)
}

/// Gets a reference to a [`BlockIssuerFeature`], if any.
pub fn block_issuer(&self) -> Option<&BlockIssuerFeature> {
self.get(BlockIssuerFeature::KIND).map(Feature::as_block_issuer)
}

/// Gets a reference to a [`StakingFeature`], if any.
pub fn staking(&self) -> Option<&StakingFeature> {
self.get(StakingFeature::KIND).map(Feature::as_staking)
Expand Down Expand Up @@ -311,6 +340,7 @@ mod test {
FeatureFlags::ISSUER,
FeatureFlags::METADATA,
FeatureFlags::TAG,
FeatureFlags::BLOCK_ISSUER,
FeatureFlags::STAKING
]
);
Expand Down
2 changes: 0 additions & 2 deletions sdk/src/types/block/output/feature/sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ impl SenderFeature {
}

mod dto {
use alloc::format;

use serde::{Deserialize, Serialize};

use super::*;
Expand Down
2 changes: 0 additions & 2 deletions sdk/src/types/block/output/feature/staking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ impl StakingFeature {
}

mod dto {
use alloc::format;

use serde::{Deserialize, Serialize};

use super::*;
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/types/block/output/feature/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl core::fmt::Debug for TagFeature {
}

mod dto {
use alloc::{borrow::Cow, format};
use alloc::borrow::Cow;

use serde::{Deserialize, Serialize};

Expand Down
2 changes: 0 additions & 2 deletions sdk/src/types/block/output/token_scheme/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,6 @@ fn verify_supply(minted_tokens: &U256, melted_tokens: &U256, maximum_supply: &U2
}

mod dto {
use alloc::format;

use serde::{Deserialize, Serialize};

use super::*;
Expand Down
2 changes: 0 additions & 2 deletions sdk/src/types/block/output/unlock_condition/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ impl AddressUnlockCondition {
}

mod dto {
use alloc::format;

use serde::{Deserialize, Serialize};

use super::*;
Expand Down
2 changes: 0 additions & 2 deletions sdk/src/types/block/output/unlock_condition/expiration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ fn verify_timestamp<const VERIFY: bool>(timestamp: &u32, _: &()) -> Result<(), E
}

mod dto {
use alloc::format;

use serde::{Deserialize, Serialize};

use super::*;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ impl GovernorAddressUnlockCondition {
}

mod dto {
use alloc::format;

use serde::{Deserialize, Serialize};

use super::*;
Expand Down
Loading

0 comments on commit 901d363

Please sign in to comment.