Skip to content

Commit

Permalink
Add new TransactionFailureReason (#1525)
Browse files Browse the repository at this point in the history
* Add transaction caps related tx failures

* Use the errors

* Add to Python

* Nodejs

* camelCase

---------

Co-authored-by: /alex/ <[email protected]>
  • Loading branch information
thibault-martinez and Alex6323 authored Oct 30, 2023
1 parent 50a5139 commit fe71cca
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 21 deletions.
42 changes: 42 additions & 0 deletions bindings/nodejs/lib/types/models/transaction-failure-reason.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,36 @@ export enum TransactionFailureReason {
*/
failedToClaimDelegationReward = 20,

/**
* Burning of native tokens is not allowed in the transaction capabilities.
*/
transactionCapabilityNativeTokenBurningNotAllowed = 21,

/**
* Burning of mana is not allowed in the transaction capabilities.
*/
transactionCapabilityManaBurningNotAllowed = 22,

/**
* Destruction of accounts is not allowed in the transaction capabilities.
*/
transactionCapabilityAccountDestructionNotAllowed = 23,

/**
* Destruction of anchors is not allowed in the transaction capabilities.
*/
transactionCapabilityAnchorDestructionNotAllowed = 24,

/**
* Destruction of foundries is not allowed in the transaction capabilities.
*/
transactionCapabilityFoundryDestructionNotAllowed = 25,

/**
* Destruction of nfts is not allowed in the transaction capabilities.
*/
transactionCapabilityNftDestructionNotAllowed = 26,

/**
* The semantic validation failed for a reason not covered by the previous variants.
*/
Expand Down Expand Up @@ -158,6 +188,18 @@ export const TRANSACTION_FAILURE_REASON_STRINGS: {
'Failed to claim staking reward.',
[TransactionFailureReason.failedToClaimDelegationReward]:
'Failed to claim delegation reward.',
[TransactionFailureReason.transactionCapabilityNativeTokenBurningNotAllowed]:
'Burning of native tokens is not allowed in the transaction capabilities.',
[TransactionFailureReason.transactionCapabilityManaBurningNotAllowed]:
'Burning of mana is not allowed in the transaction capabilities.',
[TransactionFailureReason.transactionCapabilityAccountDestructionNotAllowed]:
'Destruction of accounts is not allowed in the transaction capabilities.',
[TransactionFailureReason.transactionCapabilityAnchorDestructionNotAllowed]:
'Destruction of anchors is not allowed in the transaction capabilities.',
[TransactionFailureReason.transactionCapabilityFoundryDestructionNotAllowed]:
'Destruction of foundries is not allowed in the transaction capabilities.',
[TransactionFailureReason.transactionCapabilityNftDestructionNotAllowed]:
'Destruction of nfts is not allowed in the transaction capabilities.',
[TransactionFailureReason.semanticValidationFailed]:
'The semantic validation failed for a reason not covered by the previous variants.',
};
18 changes: 18 additions & 0 deletions bindings/python/iota_sdk/types/block/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ class TransactionFailureReason(Enum):
MissingStakingFeature: Staking Feature is not provided in account output when claiming rewards.
FailedToClaimStakingReward: Failed to claim staking reward.
FailedToClaimDelegationReward: Failed to claim delegation reward.
TransactionCapabilityNativeTokenBurningNotAllowed: Burning of native tokens is not allowed in the transaction capabilities.
TransactionCapabilityManaBurningNotAllowed: Burning of mana is not allowed in the transaction capabilities.
TransactionCapabilityAccountDestructionNotAllowed: Destruction of accounts is not allowed in the transaction capabilities.
TransactionCapabilityAnchorDestructionNotAllowed: Destruction of anchors is not allowed in the transaction capabilities.
TransactionCapabilityFoundryDestructionNotAllowed: Destruction of foundries is not allowed in the transaction capabilities.
TransactionCapabilityNftDestructionNotAllowed: Destruction of nfts is not allowed in the transaction capabilities.
SemanticValidationFailed: The semantic validation failed for a reason not covered by the previous variants.
"""
InputUtxoAlreadySpent = 1
Expand All @@ -138,6 +144,12 @@ class TransactionFailureReason(Enum):
MissingStakingFeature = 18
FailedToClaimStakingReward = 19
FailedToClaimDelegationReward = 20
TransactionCapabilityNativeTokenBurningNotAllowed = 21
TransactionCapabilityManaBurningNotAllowed = 22
TransactionCapabilityAccountDestructionNotAllowed = 23
TransactionCapabilityAnchorDestructionNotAllowed = 24
TransactionCapabilityFoundryDestructionNotAllowed = 25
TransactionCapabilityNftDestructionNotAllowed = 26
SemanticValidationFailed = 255

def __str__(self):
Expand All @@ -162,5 +174,11 @@ def __str__(self):
18: "Staking Feature is not provided in account output when claiming rewards.",
19: "Failed to claim staking reward.",
20: "Failed to claim delegation reward.",
21: "Burning of native tokens is not allowed in the transaction capabilities.",
22: "Burning of mana is not allowed in the transaction capabilities.",
23: "Destruction of accounts is not allowed in the transaction capabilities.",
24: "Destruction of anchors is not allowed in the transaction capabilities.",
25: "Destruction of foundries is not allowed in the transaction capabilities.",
26: "Destruction of nfts is not allowed in the transaction capabilities.",
255: "The semantic validation failed for a reason not covered by the previous variants."
}[self.value]
3 changes: 1 addition & 2 deletions sdk/src/types/block/output/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,8 +544,7 @@ impl StateTransitionVerifier for AccountOutput {
.transaction
.has_capability(TransactionCapabilityFlag::DestroyAccountOutputs)
{
// TODO: add a variant https://github.com/iotaledger/iota-sdk/issues/1430
return Err(StateTransitionError::UnsupportedStateTransition);
return Err(TransactionFailureReason::TransactionCapabilityAccountDestructionNotAllowed)?;
}
Ok(())
}
Expand Down
3 changes: 1 addition & 2 deletions sdk/src/types/block/output/anchor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -604,8 +604,7 @@ impl StateTransitionVerifier for AnchorOutput {
.capabilities()
.has_capability(TransactionCapabilityFlag::DestroyAnchorOutputs)
{
// TODO: add a variant https://github.com/iotaledger/iota-sdk/issues/1430
return Err(StateTransitionError::UnsupportedStateTransition);
return Err(TransactionFailureReason::TransactionCapabilityAccountDestructionNotAllowed)?;
}
Ok(())
}
Expand Down
6 changes: 2 additions & 4 deletions sdk/src/types/block/output/foundry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,8 +532,7 @@ impl FoundryOutput {
let burned_diff = token_diff - melted_diff;

if !burned_diff.is_zero() && !capabilities.has_capability(TransactionCapabilityFlag::BurnNativeTokens) {
// TODO: add a variant https://github.com/iotaledger/iota-sdk/issues/1430
return Err(StateTransitionError::UnsupportedStateTransition);
return Err(TransactionFailureReason::TransactionCapabilityManaBurningNotAllowed)?;
}
}
}
Expand Down Expand Up @@ -594,8 +593,7 @@ impl StateTransitionVerifier for FoundryOutput {
.transaction
.has_capability(TransactionCapabilityFlag::DestroyFoundryOutputs)
{
// TODO: add a variant https://github.com/iotaledger/iota-sdk/issues/1430
return Err(StateTransitionError::UnsupportedStateTransition);
return Err(TransactionFailureReason::TransactionCapabilityFoundryDestructionNotAllowed)?;
}

let token_id = current_state.token_id();
Expand Down
3 changes: 1 addition & 2 deletions sdk/src/types/block/output/nft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,8 +464,7 @@ impl StateTransitionVerifier for NftOutput {
.transaction
.has_capability(TransactionCapabilityFlag::DestroyNftOutputs)
{
// TODO: add a variant https://github.com/iotaledger/iota-sdk/issues/1430
return Err(StateTransitionError::UnsupportedStateTransition);
return Err(TransactionFailureReason::TransactionCapabilityNftDestructionNotAllowed)?;
}
Ok(())
}
Expand Down
9 changes: 8 additions & 1 deletion sdk/src/types/block/output/state_transition.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2022 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use crate::types::block::semantic::SemanticValidationContext;
use crate::types::block::semantic::{SemanticValidationContext, TransactionFailureReason};

///
#[allow(missing_docs)]
Expand All @@ -28,6 +28,13 @@ pub enum StateTransitionError {
UnsortedCreatedFoundries,
UnsupportedStateIndexOperation { current_state: u32, next_state: u32 },
UnsupportedStateTransition,
TransactionFailure(TransactionFailureReason),
}

impl From<TransactionFailureReason> for StateTransitionError {
fn from(error: TransactionFailureReason) -> Self {
Self::TransactionFailure(error)
}
}

///
Expand Down
69 changes: 59 additions & 10 deletions sdk/src/types/block/semantic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use primitive_types::U256;

use crate::types::block::{
address::{Address, AddressCapabilityFlag},
output::{AnchorOutput, ChainId, FoundryId, NativeTokens, Output, OutputId, TokenId, UnlockCondition},
output::{
AnchorOutput, ChainId, FoundryId, NativeTokens, Output, OutputId, StateTransitionError, TokenId,
UnlockCondition,
},
payload::signed_transaction::{Transaction, TransactionCapabilityFlag, TransactionId, TransactionSigningHash},
unlock::Unlocks,
Error,
Expand Down Expand Up @@ -64,6 +67,18 @@ pub enum TransactionFailureReason {
FailedToClaimStakingReward = 19,
/// Failed to claim delegation reward.
FailedToClaimDelegationReward = 20,
/// Burning of native tokens is not allowed in the transaction capabilities.
TransactionCapabilityNativeTokenBurningNotAllowed = 21,
/// Burning of mana is not allowed in the transaction capabilities.
TransactionCapabilityManaBurningNotAllowed = 22,
/// Destruction of accounts is not allowed in the transaction capabilities.
TransactionCapabilityAccountDestructionNotAllowed = 23,
/// Destruction of anchors is not allowed in the transaction capabilities.
TransactionCapabilityAnchorDestructionNotAllowed = 24,
/// Destruction of foundries is not allowed in the transaction capabilities.
TransactionCapabilityFoundryDestructionNotAllowed = 25,
/// Destruction of nfts is not allowed in the transaction capabilities.
TransactionCapabilityNftDestructionNotAllowed = 26,
/// The semantic validation failed for a reason not covered by the previous variants.
SemanticValidationFailed = 255,
}
Expand Down Expand Up @@ -107,6 +122,28 @@ impl fmt::Display for TransactionFailureReason {
),
Self::FailedToClaimStakingReward => write!(f, "Failed to claim staking reward."),
Self::FailedToClaimDelegationReward => write!(f, "Failed to claim delegation reward."),
Self::TransactionCapabilityNativeTokenBurningNotAllowed => write!(
f,
"Burning of native tokens is not allowed in the transaction capabilities."
),
Self::TransactionCapabilityManaBurningNotAllowed => {
write!(f, "Burning of mana is not allowed in the transaction capabilities.")
}
Self::TransactionCapabilityAccountDestructionNotAllowed => write!(
f,
"Destruction of accounts is not allowed in the transaction capabilities."
),
Self::TransactionCapabilityAnchorDestructionNotAllowed => write!(
f,
"Destruction of anchors is not allowed in the transaction capabilities."
),
Self::TransactionCapabilityFoundryDestructionNotAllowed => write!(
f,
"Destruction of foundries is not allowed in the transaction capabilities."
),
Self::TransactionCapabilityNftDestructionNotAllowed => {
write!(f, "Destruction of nfts is not allowed in the transaction capabilities.")
}
Self::SemanticValidationFailed => write!(
f,
"The semantic validation failed for a reason not covered by the previous variants."
Expand Down Expand Up @@ -140,6 +177,12 @@ impl TryFrom<u8> for TransactionFailureReason {
18 => Self::MissingStakingFeature,
19 => Self::FailedToClaimStakingReward,
20 => Self::FailedToClaimDelegationReward,
21 => Self::TransactionCapabilityNativeTokenBurningNotAllowed,
22 => Self::TransactionCapabilityManaBurningNotAllowed,
23 => Self::TransactionCapabilityAccountDestructionNotAllowed,
24 => Self::TransactionCapabilityAnchorDestructionNotAllowed,
25 => Self::TransactionCapabilityFoundryDestructionNotAllowed,
26 => Self::TransactionCapabilityNftDestructionNotAllowed,
255 => Self::SemanticValidationFailed,
x => return Err(Self::Error::InvalidTransactionFailureReason(x)),
})
Expand Down Expand Up @@ -462,23 +505,29 @@ impl<'a> SemanticValidationContext<'a> {

// Validation of state transitions and destructions.
for (chain_id, current_state) in self.input_chains.iter() {
if Output::verify_state_transition(
match Output::verify_state_transition(
Some(current_state),
self.output_chains.get(chain_id).map(core::ops::Deref::deref),
&self,
)
.is_err()
{
return Ok(Some(TransactionFailureReason::InvalidChainStateTransition));
) {
Err(StateTransitionError::TransactionFailure(f)) => return Ok(Some(f)),
Err(_) => {
return Ok(Some(TransactionFailureReason::InvalidChainStateTransition));
}
_ => {}
}
}

// Validation of state creations.
for (chain_id, next_state) in self.output_chains.iter() {
if self.input_chains.get(chain_id).is_none()
&& Output::verify_state_transition(None, Some(next_state), &self).is_err()
{
return Ok(Some(TransactionFailureReason::InvalidChainStateTransition));
if self.input_chains.get(chain_id).is_none() {
match Output::verify_state_transition(None, Some(next_state), &self) {
Err(StateTransitionError::TransactionFailure(f)) => return Ok(Some(f)),
Err(_) => {
return Ok(Some(TransactionFailureReason::InvalidChainStateTransition));
}
_ => {}
}
}
}

Expand Down

0 comments on commit fe71cca

Please sign in to comment.