Skip to content

Commit

Permalink
Remove output transition_inners (#2136)
Browse files Browse the repository at this point in the history
* Remove output `transition_inner`s

* nit

---------

Co-authored-by: DaughterOfMars <[email protected]>
  • Loading branch information
thibault-martinez and DaughterOfMars authored Mar 5, 2024
1 parent a3ec61a commit c132578
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 233 deletions.
57 changes: 0 additions & 57 deletions sdk/src/types/block/output/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

use alloc::collections::BTreeSet;

use hashbrown::HashMap;
use packable::{
error::{UnpackError, UnpackErrorExt},
packer::Packer,
Expand All @@ -23,7 +22,6 @@ use crate::types::block::{
StorageScoreParameters,
},
protocol::{ProtocolParameters, WorkScore, WorkScoreParameters},
semantic::TransactionFailureReason,
slot::SlotIndex,
};

Expand Down Expand Up @@ -442,61 +440,6 @@ impl AccountOutput {
potential: potential_mana,
})
}

// Transition, just without full SemanticValidationContext
pub(crate) fn transition_inner(
current_state: &Self,
next_state: &Self,
input_chains: &HashMap<ChainId, (&OutputId, &Output)>,
outputs: &[Output],
) -> Result<(), TransactionFailureReason> {
if current_state.immutable_features != next_state.immutable_features {
return Err(TransactionFailureReason::ChainOutputImmutableFeaturesChanged);
}

// TODO update when TIP is updated
// // Governance transition.
// if current_state.amount != next_state.amount
// || current_state.foundry_counter != next_state.foundry_counter
// {
// return Err(StateTransitionError::MutatedFieldWithoutRights);
// }

// // State transition.
// if current_state.features.metadata() != next_state.features.metadata() {
// return Err(StateTransitionError::MutatedFieldWithoutRights);
// }

let created_foundries = outputs.iter().filter_map(|output| {
if let Output::Foundry(foundry) = output {
if foundry.account_address().account_id() == &next_state.account_id
&& !input_chains.contains_key(&foundry.chain_id())
{
Some(foundry)
} else {
None
}
} else {
None
}
});

let mut created_foundries_count = 0;

for foundry in created_foundries {
created_foundries_count += 1;

if foundry.serial_number() != current_state.foundry_counter + created_foundries_count {
return Err(TransactionFailureReason::FoundrySerialInvalid);
}
}

if current_state.foundry_counter + created_foundries_count != next_state.foundry_counter {
return Err(TransactionFailureReason::AccountInvalidFoundryCounter);
}

Ok(())
}
}

impl StorageScore for AccountOutput {
Expand Down
34 changes: 0 additions & 34 deletions sdk/src/types/block/output/anchor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

use alloc::collections::BTreeSet;

use hashbrown::HashMap;
use packable::{
error::{UnpackError, UnpackErrorExt},
packer::Packer,
Expand Down Expand Up @@ -498,39 +497,6 @@ impl AnchorOutput {
potential: potential_mana,
})
}

// Transition, just without full ValidationContext
pub(crate) fn transition_inner(
current_state: &Self,
next_state: &Self,
_input_chains: &HashMap<ChainId, (&OutputId, &Output)>,
_outputs: &[Output],
) -> Result<(), TransactionFailureReason> {
if current_state.immutable_features != next_state.immutable_features {
return Err(TransactionFailureReason::ChainOutputImmutableFeaturesChanged);
}

if next_state.state_index == current_state.state_index + 1 {
// State transition.
if current_state.state_controller_address() != next_state.state_controller_address()
|| current_state.governor_address() != next_state.governor_address()
|| current_state.features.metadata() != next_state.features.metadata()
{
return Err(TransactionFailureReason::AnchorInvalidStateTransition);
}
} else if next_state.state_index == current_state.state_index {
// Governance transition.
if current_state.amount != next_state.amount
|| current_state.features().state_metadata() != next_state.features().state_metadata()
{
return Err(TransactionFailureReason::AnchorInvalidGovernanceTransition);
}
} else {
return Err(TransactionFailureReason::AnchorInvalidStateTransition);
}

Ok(())
}
}

impl StorageScore for AnchorOutput {
Expand Down
17 changes: 0 additions & 17 deletions sdk/src/types/block/output/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use crate::types::block::{
StorageScoreParameters,
},
protocol::{ProtocolParameters, WorkScore, WorkScoreParameters},
semantic::TransactionFailureReason,
slot::{EpochIndex, SlotIndex},
};

Expand Down Expand Up @@ -383,22 +382,6 @@ impl DelegationOutput {
potential: potential_mana,
})
}

// Transition, just without full SemanticValidationContext.
pub(crate) fn transition_inner(current_state: &Self, next_state: &Self) -> Result<(), TransactionFailureReason> {
if !current_state.delegation_id.is_null() || next_state.delegation_id.is_null() {
return Err(TransactionFailureReason::DelegationOutputTransitionedTwice);
}

if current_state.delegated_amount != next_state.delegated_amount
|| current_state.start_epoch != next_state.start_epoch
|| current_state.validator_address != next_state.validator_address
{
return Err(TransactionFailureReason::DelegationModified);
}

Ok(())
}
}

impl StorageScore for DelegationOutput {
Expand Down
92 changes: 1 addition & 91 deletions sdk/src/types/block/output/foundry.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
// Copyright 2021 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use alloc::collections::{BTreeMap, BTreeSet};
use core::cmp::Ordering;
use alloc::collections::BTreeSet;

use packable::{
error::{UnpackError, UnpackErrorExt},
packer::{Packer, SlicePacker},
unpacker::Unpacker,
Packable, PackableExt,
};
use primitive_types::U256;

use crate::types::block::{
address::{AccountAddress, Address},
Expand All @@ -21,9 +19,7 @@ use crate::types::block::{
ChainId, DecayedMana, MinimumOutputAmount, NativeToken, Output, OutputBuilderAmount, OutputError, StorageScore,
StorageScoreParameters, TokenId, TokenScheme,
},
payload::signed_transaction::{TransactionCapabilities, TransactionCapabilityFlag},
protocol::{ProtocolParameters, WorkScore, WorkScoreParameters},
semantic::TransactionFailureReason,
slot::SlotIndex,
};

Expand Down Expand Up @@ -455,92 +451,6 @@ impl FoundryOutput {
potential: potential_mana,
})
}

// Transition, just without full SemanticValidationContext
pub(crate) fn transition_inner(
current_state: &Self,
next_state: &Self,
input_native_tokens: &BTreeMap<TokenId, U256>,
output_native_tokens: &BTreeMap<TokenId, U256>,
capabilities: &TransactionCapabilities,
) -> Result<(), TransactionFailureReason> {
if current_state.account_address() != next_state.account_address()
|| current_state.serial_number != next_state.serial_number
|| current_state.immutable_features != next_state.immutable_features
{
return Err(TransactionFailureReason::ChainOutputImmutableFeaturesChanged);
}

let token_id = next_state.token_id();
let input_tokens = input_native_tokens.get(&token_id).copied().unwrap_or_default();
let output_tokens = output_native_tokens.get(&token_id).copied().unwrap_or_default();
let TokenScheme::Simple(ref current_token_scheme) = current_state.token_scheme;
let TokenScheme::Simple(ref next_token_scheme) = next_state.token_scheme;

if current_token_scheme.maximum_supply() != next_token_scheme.maximum_supply() {
return Err(TransactionFailureReason::SimpleTokenSchemeMaximumSupplyChanged);
}

if current_token_scheme.minted_tokens() > next_token_scheme.minted_tokens()
|| current_token_scheme.melted_tokens() > next_token_scheme.melted_tokens()
{
return Err(TransactionFailureReason::SimpleTokenSchemeMintedMeltedTokenDecrease);
}

match input_tokens.cmp(&output_tokens) {
Ordering::Less => {
// Mint

// This can't underflow as it is known that current_minted_tokens <= next_minted_tokens.
let minted_diff = next_token_scheme.minted_tokens() - current_token_scheme.minted_tokens();
// This can't underflow as it is known that input_tokens < output_tokens (Ordering::Less).
let token_diff = output_tokens - input_tokens;

if minted_diff != token_diff {
return Err(TransactionFailureReason::NativeTokenSumUnbalanced);
}

if current_token_scheme.melted_tokens() != next_token_scheme.melted_tokens() {
return Err(TransactionFailureReason::NativeTokenSumUnbalanced);
}
}
Ordering::Equal => {
// Transition

if current_token_scheme.minted_tokens() != next_token_scheme.minted_tokens()
|| current_token_scheme.melted_tokens() != next_token_scheme.melted_tokens()
{
return Err(TransactionFailureReason::NativeTokenSumUnbalanced);
}
}
Ordering::Greater => {
// Melt / Burn

if current_token_scheme.melted_tokens() != next_token_scheme.melted_tokens()
&& current_token_scheme.minted_tokens() != next_token_scheme.minted_tokens()
{
return Err(TransactionFailureReason::NativeTokenSumUnbalanced);
}

// This can't underflow as it is known that current_melted_tokens <= next_melted_tokens.
let melted_diff = next_token_scheme.melted_tokens() - current_token_scheme.melted_tokens();
// This can't underflow as it is known that input_tokens > output_tokens (Ordering::Greater).
let token_diff = input_tokens - output_tokens;

if melted_diff > token_diff {
return Err(TransactionFailureReason::NativeTokenSumUnbalanced);
}

let burned_diff = token_diff - melted_diff;

if !burned_diff.is_zero() && !capabilities.has_capability(TransactionCapabilityFlag::BurnNativeTokens) {
return Err(TransactionFailureReason::CapabilitiesNativeTokenBurningNotAllowed)?;
}
}
}

Ok(())
}
}

impl StorageScore for FoundryOutput {
Expand Down
10 changes: 0 additions & 10 deletions sdk/src/types/block/output/nft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ use crate::types::block::{
OutputId, StorageScore, StorageScoreParameters,
},
protocol::{ProtocolParameters, WorkScore, WorkScoreParameters},
semantic::TransactionFailureReason,
slot::SlotIndex,
};

Expand Down Expand Up @@ -453,15 +452,6 @@ impl NftOutput {
potential: potential_mana,
})
}

// Transition, just without full SemanticValidationContext
pub(crate) fn transition_inner(current_state: &Self, next_state: &Self) -> Result<(), TransactionFailureReason> {
if current_state.immutable_features != next_state.immutable_features {
return Err(TransactionFailureReason::ChainOutputImmutableFeaturesChanged);
}

Ok(())
}
}

impl StorageScore for NftOutput {
Expand Down
Loading

0 comments on commit c132578

Please sign in to comment.