bee_tangle/
conflict.rs

1// Copyright 2020-2021 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use bee_common::packable::Packable;
5
6use serde::{Deserialize, Serialize};
7
8use std::io::{Read, Write};
9
10/// Errors related to ledger types.
11#[derive(Debug, thiserror::Error)]
12pub enum ConflictError {
13    /// I/O error.
14    #[error("I/O error: {0}")]
15    Io(#[from] std::io::Error),
16    /// Invalid conflict byte.
17    #[error("Invalid conflict byte")]
18    InvalidConflict(u8),
19}
20
21/// Represents the different reasons why a transaction can conflict with the ledger state.
22#[repr(u8)]
23#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
24pub enum ConflictReason {
25    /// The message has no conflict.
26    None = 0,
27    /// The referenced Utxo was already spent.
28    InputUtxoAlreadySpent = 1,
29    /// The referenced Utxo was already spent while confirming this milestone.
30    InputUtxoAlreadySpentInThisMilestone = 2,
31    /// The referenced Utxo cannot be found.
32    InputUtxoNotFound = 3,
33    /// The sum of the inputs and output values does not match.
34    InputOutputSumMismatch = 4,
35    /// The unlock block signature is invalid.
36    InvalidSignature = 5,
37    /// The dust allowance for the address is invalid.
38    InvalidDustAllowance = 6,
39    /// The semantic validation failed for a reason not covered by the previous variants.
40    SemanticValidationFailed = 255,
41}
42
43impl Default for ConflictReason {
44    fn default() -> Self {
45        Self::None
46    }
47}
48
49impl TryFrom<u8> for ConflictReason {
50    type Error = ConflictError;
51
52    fn try_from(c: u8) -> Result<Self, Self::Error> {
53        Ok(match c {
54            0 => Self::None,
55            1 => Self::InputUtxoAlreadySpent,
56            2 => Self::InputUtxoAlreadySpentInThisMilestone,
57            3 => Self::InputUtxoNotFound,
58            4 => Self::InputOutputSumMismatch,
59            5 => Self::InvalidSignature,
60            6 => Self::InvalidDustAllowance,
61            255 => Self::SemanticValidationFailed,
62            x => return Err(Self::Error::InvalidConflict(x)),
63        })
64    }
65}
66
67impl Packable for ConflictReason {
68    type Error = ConflictError;
69
70    fn packed_len(&self) -> usize {
71        (*self as u8).packed_len()
72    }
73
74    fn pack<W: Write>(&self, writer: &mut W) -> Result<(), Self::Error> {
75        Ok((*self as u8).pack(writer)?)
76    }
77
78    fn unpack_inner<R: Read + ?Sized, const CHECK: bool>(reader: &mut R) -> Result<Self, Self::Error>
79    where
80        Self: Sized,
81    {
82        u8::unpack_inner::<R, CHECK>(reader)?.try_into()
83    }
84}