Skip to content

Commit

Permalink
fix semantic validation?
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Coats committed Oct 4, 2023
1 parent c8b9b35 commit 9dd4e28
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 52 deletions.
1 change: 1 addition & 0 deletions sdk/src/client/api/block_builder/input_selection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ impl InputSelection {
foundry_output,
input_native_tokens_builder.deref(),
output_native_tokens_builder.deref(),
Default::default(),
) {
log::debug!("validate_transitions error {err:?}");
return Err(Error::UnfulfillableRequirement(Requirement::Foundry(
Expand Down
11 changes: 10 additions & 1 deletion sdk/src/types/block/output/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use crate::types::{
NativeTokens, Output, OutputBuilderAmount, OutputId, Rent, RentStructure, StateTransitionError,
StateTransitionVerifier,
},
payload::transaction::TransactionCapabilityFlag,
protocol::ProtocolParameters,
semantic::{TransactionFailureReason, ValidationContext},
unlock::Unlock,
Expand Down Expand Up @@ -646,7 +647,15 @@ impl StateTransitionVerifier for AccountOutput {
)
}

fn destruction(_current_state: &Self, _context: &ValidationContext<'_>) -> Result<(), StateTransitionError> {
fn destruction(_current_state: &Self, context: &ValidationContext<'_>) -> Result<(), StateTransitionError> {
if context
.essence
.capabilities()
.has_capability(TransactionCapabilityFlag::DestroyAccountOutputs)
{
// TODO: is this correct?
return Err(StateTransitionError::UnsupportedStateTransition);
}
Ok(())
}
}
Expand Down
3 changes: 2 additions & 1 deletion sdk/src/types/block/output/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,8 @@ impl DelegationOutput {

// Transition, just without full ValidationContext.
pub(crate) fn transition_inner(current_state: &Self, next_state: &Self) -> Result<(), StateTransitionError> {
if !current_state.delegation_id.is_null() || next_state.delegation_id().is_null() {
#[allow(clippy::nonminimal_bool)]
if !(current_state.delegation_id.is_null() && !next_state.delegation_id().is_null()) {
return Err(StateTransitionError::NonDelayedClaimingTransition);
}

Expand Down
17 changes: 17 additions & 0 deletions sdk/src/types/block/output/foundry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use crate::types::{
NativeTokens, Output, OutputBuilderAmount, OutputId, Rent, RentStructure, StateTransitionError,
StateTransitionVerifier, TokenId, TokenScheme,
},
payload::transaction::{TransactionCapabilities, TransactionCapabilityFlag},
protocol::ProtocolParameters,
semantic::{TransactionFailureReason, ValidationContext},
unlock::Unlock,
Expand Down Expand Up @@ -457,6 +458,7 @@ impl FoundryOutput {
next_state: &Self,
input_native_tokens: &BTreeMap<TokenId, U256>,
output_native_tokens: &BTreeMap<TokenId, U256>,
capabilities: TransactionCapabilities,
) -> Result<(), StateTransitionError> {
if current_state.account_address() != next_state.account_address()
|| current_state.serial_number != next_state.serial_number
Expand Down Expand Up @@ -510,6 +512,11 @@ impl FoundryOutput {
Ordering::Greater => {
// Melt / Burn

if capabilities.has_capability(TransactionCapabilityFlag::BurnNativeTokens) {
// TODO: is this correct?
return Err(StateTransitionError::UnsupportedStateTransition);
}

if current_token_scheme.melted_tokens() != next_token_scheme.melted_tokens()
&& current_token_scheme.minted_tokens() != next_token_scheme.minted_tokens()
{
Expand Down Expand Up @@ -574,10 +581,20 @@ impl StateTransitionVerifier for FoundryOutput {
next_state,
&context.input_native_tokens,
&context.output_native_tokens,
context.essence.capabilities(),
)
}

fn destruction(current_state: &Self, context: &ValidationContext<'_>) -> Result<(), StateTransitionError> {
if context
.essence
.capabilities()
.has_capability(TransactionCapabilityFlag::DestroyFoundryOutputs)
{
// TODO: is this correct?
return Err(StateTransitionError::UnsupportedStateTransition);
}

let token_id = current_state.token_id();
let input_tokens = context.input_native_tokens.get(&token_id).copied().unwrap_or_default();
let TokenScheme::Simple(ref current_token_scheme) = current_state.token_scheme;
Expand Down
11 changes: 10 additions & 1 deletion sdk/src/types/block/output/nft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::types::{
NativeTokens, Output, OutputBuilderAmount, OutputId, Rent, RentStructure, StateTransitionError,
StateTransitionVerifier,
},
payload::transaction::TransactionCapabilityFlag,
protocol::ProtocolParameters,
semantic::{TransactionFailureReason, ValidationContext},
unlock::Unlock,
Expand Down Expand Up @@ -456,7 +457,15 @@ impl StateTransitionVerifier for NftOutput {
Self::transition_inner(current_state, next_state)
}

fn destruction(_current_state: &Self, _context: &ValidationContext<'_>) -> Result<(), StateTransitionError> {
fn destruction(_current_state: &Self, context: &ValidationContext<'_>) -> Result<(), StateTransitionError> {
if context
.essence
.capabilities()
.has_capability(TransactionCapabilityFlag::DestroyNftOutputs)
{
// TODO: is this correct?
return Err(StateTransitionError::UnsupportedStateTransition);
}
Ok(())
}
}
Expand Down
49 changes: 0 additions & 49 deletions sdk/src/types/block/semantic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,45 +268,6 @@ pub fn semantic_validation(
),
};

if let Output::Account(consumed) = consumed_output {
let match_fn = |created_output: &Output| matches!(created_output, Output::Account(created) if created.account_id() == consumed.account_id());
if !context.essence.outputs().iter().any(match_fn)
&& !context
.essence
.capabilities()
.has_capability(TransactionCapabilityFlag::DestroyAccountOutputs)
{
// TODO: better failure reason incoming?
return Ok(Some(TransactionFailureReason::SemanticValidationFailed));
}
}

if let Output::Foundry(consumed) = consumed_output {
let match_fn = |created_output: &Output| matches!(created_output, Output::Foundry(created) if created.id() == consumed.id());
if !context.essence.outputs().iter().any(match_fn)
&& !context
.essence
.capabilities()
.has_capability(TransactionCapabilityFlag::DestroyFoundryOutputs)
{
// TODO: better failure reason incoming?
return Ok(Some(TransactionFailureReason::SemanticValidationFailed));
}
}

if let Output::Nft(consumed) = consumed_output {
let match_fn = |created_output: &Output| matches!(created_output, Output::Nft(created) if created.nft_id() == consumed.nft_id());
if !context.essence.outputs().iter().any(match_fn)
&& !context
.essence
.capabilities()
.has_capability(TransactionCapabilityFlag::DestroyNftOutputs)
{
// TODO: better failure reason incoming?
return Ok(Some(TransactionFailureReason::SemanticValidationFailed));
}
}

if let Err(conflict) = conflict {
return Ok(Some(conflict));
}
Expand Down Expand Up @@ -450,16 +411,6 @@ pub fn semantic_validation(
// Validation of input native tokens.
for (token_id, _input_amount) in context.input_native_tokens.iter() {
native_token_ids.insert(token_id);

if !context.output_native_tokens.contains_key(token_id)
&& context
.essence
.capabilities()
.has_capability(TransactionCapabilityFlag::BurnNativeTokens)
{
// TODO: better failure reason incoming?
return Ok(Some(TransactionFailureReason::SemanticValidationFailed));
}
}

// Validation of output native tokens.
Expand Down

0 comments on commit 9dd4e28

Please sign in to comment.