1use alloc::string::{FromUtf8Error, String};
5use core::{convert::Infallible, fmt};
6
7use crypto::Error as CryptoError;
8use prefix_hex::Error as HexError;
9use primitive_types::U256;
10
11use crate::{
12 input::UtxoInput,
13 output::{
14 feature::FeatureCount, unlock_condition::UnlockConditionCount, AliasId, MetadataFeatureLength,
15 NativeTokenCount, NftId, OutputIndex, StateMetadataLength, TagFeatureLength,
16 },
17 parent::ParentCount,
18 payload::{
19 milestone::BinaryParametersLength, InputCount, MilestoneMetadataLength, MilestoneOptionCount, OutputCount,
20 ReceiptFundsCount, SignatureCount, TagLength, TaggedDataLength,
21 },
22 unlock::{UnlockCount, UnlockIndex},
23};
24
25#[derive(Debug, PartialEq)]
27#[allow(missing_docs)]
28pub enum Error {
29 CannotReplaceMissingField,
30 ConsumedAmountOverflow,
31 ConsumedNativeTokensAmountOverflow,
32 CreatedAmountOverflow,
33 CreatedNativeTokensAmountOverflow,
34 CryptoError(CryptoError),
35 DuplicateSignatureUnlock(u16),
36 DuplicateUtxo(UtxoInput),
37 ExpirationUnlockConditionZero,
38 FeaturesNotUniqueSorted,
39 InputUnlockCountMismatch { input_count: usize, unlock_count: usize },
40 InvalidAddress,
41 InvalidAddressKind(u8),
42 InvalidAliasIndex(<UnlockIndex as TryFrom<u16>>::Error),
43 InvalidControllerKind(u8),
44 InvalidStorageDepositAmount(u64),
45 InsufficientStorageDepositAmount { amount: u64, required: u64 },
47 StorageDepositReturnExceedsOutputAmount { deposit: u64, amount: u64 },
48 InsufficientStorageDepositReturnAmount { deposit: u64, required: u64 },
49 InvalidBinaryParametersLength(<BinaryParametersLength as TryFrom<usize>>::Error),
50 InvalidEssenceKind(u8),
51 InvalidFeatureCount(<FeatureCount as TryFrom<usize>>::Error),
52 InvalidFeatureKind(u8),
53 InvalidFoundryOutputSupply { minted: U256, melted: U256, max: U256 },
54 HexError(HexError),
55 InvalidInputKind(u8),
56 InvalidInputCount(<InputCount as TryFrom<usize>>::Error),
57 InvalidInputOutputIndex(<OutputIndex as TryFrom<u16>>::Error),
58 InvalidBech32Hrp(FromUtf8Error),
59 InvalidBlockLength(usize),
60 InvalidStateMetadataLength(<StateMetadataLength as TryFrom<usize>>::Error),
61 InvalidMetadataFeatureLength(<MetadataFeatureLength as TryFrom<usize>>::Error),
62 InvalidMilestoneMetadataLength(<MilestoneMetadataLength as TryFrom<usize>>::Error),
63 InvalidMilestoneOptionCount(<MilestoneOptionCount as TryFrom<usize>>::Error),
64 InvalidMilestoneOptionKind(u8),
65 InvalidMigratedFundsEntryAmount(u64),
66 InvalidNativeTokenCount(<NativeTokenCount as TryFrom<usize>>::Error),
67 InvalidNetworkName(FromUtf8Error),
68 InvalidNftIndex(<UnlockIndex as TryFrom<u16>>::Error),
69 InvalidOutputAmount(u64),
70 InvalidOutputCount(<OutputCount as TryFrom<usize>>::Error),
71 InvalidOutputKind(u8),
72 InvalidParentCount(<ParentCount as TryFrom<usize>>::Error),
73 InvalidPayloadKind(u32),
74 InvalidPayloadLength { expected: usize, actual: usize },
75 InvalidReceiptFundsCount(<ReceiptFundsCount as TryFrom<usize>>::Error),
76 InvalidReceiptFundsSum(u128),
77 InvalidReferenceIndex(<UnlockIndex as TryFrom<u16>>::Error),
78 InvalidSignature,
79 InvalidSignatureKind(u8),
80 InvalidStringPrefix(<u8 as TryFrom<usize>>::Error),
81 InvalidTaggedDataLength(<TaggedDataLength as TryFrom<usize>>::Error),
82 InvalidTagFeatureLength(<TagFeatureLength as TryFrom<usize>>::Error),
83 InvalidTagLength(<TagLength as TryFrom<usize>>::Error),
84 InvalidTailTransactionHash,
85 InvalidTokenSchemeKind(u8),
86 InvalidTransactionAmountSum(u128),
87 InvalidTransactionNativeTokensCount(u16),
88 InvalidTreasuryOutputAmount(u64),
89 InvalidUnlockCount(<UnlockCount as TryFrom<usize>>::Error),
90 InvalidUnlockKind(u8),
91 InvalidUnlockReference(u16),
92 InvalidUnlockAlias(u16),
93 InvalidUnlockNft(u16),
94 InvalidUnlockConditionCount(<UnlockConditionCount as TryFrom<usize>>::Error),
95 InvalidUnlockConditionKind(u8),
96 MigratedFundsNotSorted,
97 MilestoneInvalidSignatureCount(<SignatureCount as TryFrom<usize>>::Error),
98 MilestonePublicKeysSignaturesCountMismatch { key_count: usize, sig_count: usize },
99 MilestoneOptionsNotUniqueSorted,
100 MilestoneSignaturesNotUniqueSorted,
101 MissingAddressUnlockCondition,
102 MissingGovernorUnlockCondition,
103 MissingPayload,
104 MissingRequiredSenderBlock,
105 MissingStateControllerUnlockCondition,
106 NativeTokensNotUniqueSorted,
107 NativeTokensNullAmount,
108 NativeTokensOverflow,
109 NetworkIdMismatch { expected: u64, actual: u64 },
110 NonZeroStateIndexOrFoundryCounter,
111 ParentsNotUniqueSorted,
112 ProtocolVersionMismatch { expected: u8, actual: u8 },
113 ReceiptFundsNotUniqueSorted,
114 RemainingBytesAfterBlock,
115 SelfControlledAliasOutput(AliasId),
116 SelfDepositNft(NftId),
117 SignaturePublicKeyMismatch { expected: String, actual: String },
118 StorageDepositReturnOverflow,
119 TailTransactionHashNotUnique { previous: usize, current: usize },
120 TimelockUnlockConditionZero,
121 UnallowedFeature { index: usize, kind: u8 },
122 UnallowedUnlockCondition { index: usize, kind: u8 },
123 UnlockConditionsNotUniqueSorted,
124 UnsupportedOutputKind(u8),
125}
126
127#[cfg(feature = "std")]
128impl std::error::Error for Error {}
129
130impl fmt::Display for Error {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 match self {
133 Error::CannotReplaceMissingField => write!(f, "cannot replace missing field"),
134 Error::ConsumedAmountOverflow => write!(f, "consumed amount overflow"),
135 Error::ConsumedNativeTokensAmountOverflow => write!(f, "consumed native tokens amount overflow"),
136 Error::CreatedAmountOverflow => write!(f, "created amount overflow"),
137 Error::CreatedNativeTokensAmountOverflow => write!(f, "created native tokens amount overflow"),
138 Error::CryptoError(e) => write!(f, "cryptographic error: {}", e),
139 Error::DuplicateSignatureUnlock(index) => {
140 write!(f, "duplicate signature unlock at index: {0}", index)
141 }
142 Error::DuplicateUtxo(utxo) => write!(f, "duplicate UTXO {:?} in inputs", utxo),
143 Error::ExpirationUnlockConditionZero => {
144 write!(
145 f,
146 "expiration unlock condition with milestone index and timestamp set to 0",
147 )
148 }
149 Error::FeaturesNotUniqueSorted => write!(f, "features are not unique and/or sorted"),
150 Error::InputUnlockCountMismatch {
151 input_count,
152 unlock_count,
153 } => {
154 write!(
155 f,
156 "input count and unlock count mismatch: {} != {}",
157 input_count, unlock_count
158 )
159 }
160 Error::InvalidAddress => write!(f, "invalid address provided"),
161 Error::InvalidAddressKind(k) => write!(f, "invalid address kind: {}", k),
162 Error::InvalidAliasIndex(index) => write!(f, "invalid alias index: {}", index),
163 Error::InvalidBech32Hrp(err) => write!(f, "invalid bech32 hrp: {err}"),
164 Error::InvalidBinaryParametersLength(length) => {
165 write!(f, "invalid binary parameters length: {length}")
166 }
167 Error::InvalidControllerKind(k) => write!(f, "invalid controller kind: {}", k),
168 Error::InvalidStorageDepositAmount(amount) => {
169 write!(f, "invalid storage deposit amount: {}", amount)
170 }
171 Error::InsufficientStorageDepositAmount { amount, required } => {
172 write!(
173 f,
174 "insufficient output amount for storage deposit: {amount} (should be at least {required})"
175 )
176 }
177 Error::InsufficientStorageDepositReturnAmount { deposit, required } => {
178 write!(
179 f,
180 "the return deposit ({deposit}) must be greater than the minimum storage deposit ({required})"
181 )
182 }
183 Error::StorageDepositReturnExceedsOutputAmount { deposit, amount } => write!(
184 f,
185 "storage deposit return of {deposit} exceeds the original output amount of {amount}"
186 ),
187 Error::InvalidEssenceKind(k) => write!(f, "invalid essence kind: {}", k),
188 Error::InvalidFeatureCount(count) => write!(f, "invalid feature count: {}", count),
189 Error::InvalidFeatureKind(k) => write!(f, "invalid feature kind: {}", k),
190 Error::InvalidFoundryOutputSupply { minted, melted, max } => write!(
191 f,
192 "invalid foundry output supply: minted {minted}, melted {melted} max {max}",
193 ),
194 Error::HexError(error) => write!(f, "hex error: {}", error),
195 Error::InvalidInputKind(k) => write!(f, "invalid input kind: {}", k),
196 Error::InvalidInputCount(count) => write!(f, "invalid input count: {}", count),
197 Error::InvalidInputOutputIndex(index) => write!(f, "invalid input or output index: {}", index),
198 Error::InvalidBlockLength(length) => write!(f, "invalid block length {}", length),
199 Error::InvalidStateMetadataLength(length) => write!(f, "invalid state metadata length {}", length),
200 Error::InvalidMetadataFeatureLength(length) => {
201 write!(f, "invalid metadata feature length {length}")
202 }
203 Error::InvalidMilestoneMetadataLength(length) => {
204 write!(f, "invalid milestone metadata length {length}")
205 }
206 Error::InvalidMilestoneOptionCount(count) => write!(f, "invalid milestone option count: {count}"),
207 Error::InvalidMilestoneOptionKind(k) => write!(f, "invalid milestone option kind: {k}"),
208 Error::InvalidMigratedFundsEntryAmount(amount) => {
209 write!(f, "invalid migrated funds entry amount: {amount}")
210 }
211 Error::InvalidNativeTokenCount(count) => write!(f, "invalid native token count: {}", count),
212 Error::InvalidNetworkName(err) => write!(f, "invalid network name: {err}"),
213 Error::InvalidNftIndex(index) => write!(f, "invalid nft index: {}", index),
214 Error::InvalidOutputAmount(amount) => write!(f, "invalid output amount: {}", amount),
215 Error::InvalidOutputCount(count) => write!(f, "invalid output count: {}", count),
216 Error::InvalidOutputKind(k) => write!(f, "invalid output kind: {}", k),
217 Error::InvalidParentCount(count) => {
218 write!(f, "invalid parents count: {}", count)
219 }
220 Error::InvalidPayloadKind(k) => write!(f, "invalid payload kind: {}", k),
221 Error::InvalidPayloadLength { expected, actual } => {
222 write!(f, "invalid payload length: expected {} but got {}", expected, actual)
223 }
224 Error::InvalidReceiptFundsCount(count) => write!(f, "invalid receipt funds count: {}", count),
225 Error::InvalidReceiptFundsSum(sum) => write!(f, "invalid receipt amount sum: {sum}"),
226 Error::InvalidReferenceIndex(index) => write!(f, "invalid reference index: {}", index),
227 Error::InvalidSignature => write!(f, "invalid signature provided"),
228 Error::InvalidSignatureKind(k) => write!(f, "invalid signature kind: {}", k),
229 Error::InvalidStringPrefix(p) => write!(f, "invalid string prefix: {p}"),
230 Error::InvalidTaggedDataLength(length) => {
231 write!(f, "invalid tagged data length {}", length)
232 }
233 Error::InvalidTagFeatureLength(length) => {
234 write!(f, "invalid tag feature length {}", length)
235 }
236 Error::InvalidTagLength(length) => {
237 write!(f, "invalid tag length {}", length)
238 }
239 Error::InvalidTailTransactionHash => write!(f, "invalid tail transaction hash"),
240 Error::InvalidTokenSchemeKind(k) => write!(f, "invalid token scheme kind {}", k),
241 Error::InvalidTransactionAmountSum(value) => write!(f, "invalid transaction amount sum: {}", value),
242 Error::InvalidTransactionNativeTokensCount(count) => {
243 write!(f, "invalid transaction native tokens count: {}", count)
244 }
245 Error::InvalidTreasuryOutputAmount(amount) => write!(f, "invalid treasury amount: {}", amount),
246 Error::InvalidUnlockCount(count) => write!(f, "invalid unlock count: {}", count),
247 Error::InvalidUnlockKind(k) => write!(f, "invalid unlock kind: {}", k),
248 Error::InvalidUnlockReference(index) => {
249 write!(f, "invalid unlock reference: {0}", index)
250 }
251 Error::InvalidUnlockAlias(index) => {
252 write!(f, "invalid unlock alias: {0}", index)
253 }
254 Error::InvalidUnlockNft(index) => {
255 write!(f, "invalid unlock nft: {0}", index)
256 }
257 Error::InvalidUnlockConditionCount(count) => write!(f, "invalid unlock condition count: {}", count),
258 Error::InvalidUnlockConditionKind(k) => write!(f, "invalid unlock condition kind: {}", k),
259 Error::MigratedFundsNotSorted => {
260 write!(f, "migrated funds are not sorted")
261 }
262 Error::MilestoneInvalidSignatureCount(count) => {
263 write!(f, "invalid milestone signature count: {}", count)
264 }
265 Error::MilestonePublicKeysSignaturesCountMismatch { key_count, sig_count } => {
266 write!(
267 f,
268 "milestone public keys and signatures count mismatch: {0} != {1}",
269 key_count, sig_count
270 )
271 }
272 Error::MilestoneOptionsNotUniqueSorted => {
273 write!(f, "milestone options are not unique and/or sorted")
274 }
275 Error::MilestoneSignaturesNotUniqueSorted => {
276 write!(f, "milestone signatures are not unique and/or sorted")
277 }
278 Error::MissingAddressUnlockCondition => write!(f, "missing address unlock condition"),
279 Error::MissingGovernorUnlockCondition => write!(f, "missing governor unlock condition"),
280 Error::MissingPayload => write!(f, "missing payload"),
281 Error::MissingRequiredSenderBlock => write!(f, "missing required sender block"),
282 Error::MissingStateControllerUnlockCondition => write!(f, "missing state controller unlock condition"),
283 Error::NativeTokensNotUniqueSorted => write!(f, "native tokens are not unique and/or sorted"),
284 Error::NativeTokensNullAmount => write!(f, "native tokens null amount"),
285 Error::NativeTokensOverflow => write!(f, "native tokens overflow"),
286 Error::NetworkIdMismatch { expected, actual } => {
287 write!(f, "network ID mismatch: expected {expected} but got {actual}")
288 }
289 Error::NonZeroStateIndexOrFoundryCounter => {
290 write!(f, "non zero state index or foundry counter while alias ID is all zero")
291 }
292 Error::ParentsNotUniqueSorted => {
293 write!(f, "parents are not unique and/or sorted")
294 }
295 Error::ProtocolVersionMismatch { expected, actual } => {
296 write!(f, "protocol version mismatch: expected {expected} but got {actual}")
297 }
298 Error::ReceiptFundsNotUniqueSorted => {
299 write!(f, "receipt funds are not unique and/or sorted")
300 }
301 Error::RemainingBytesAfterBlock => {
302 write!(f, "remaining bytes after block")
303 }
304 Error::SelfControlledAliasOutput(alias_id) => {
305 write!(f, "self controlled alias output, alias ID {}", alias_id)
306 }
307 Error::SelfDepositNft(nft_id) => {
308 write!(f, "self deposit nft output, NFT ID {}", nft_id)
309 }
310 Error::SignaturePublicKeyMismatch { expected, actual } => {
311 write!(
312 f,
313 "signature public key mismatch: expected {0} but got {1}",
314 expected, actual
315 )
316 }
317 Error::StorageDepositReturnOverflow => {
318 write!(f, "storage deposit return overflow",)
319 }
320 Error::TailTransactionHashNotUnique { previous, current } => {
321 write!(
322 f,
323 "tail transaction hash is not unique at indices: {0} and {1}",
324 previous, current
325 )
326 }
327 Error::TimelockUnlockConditionZero => {
328 write!(
329 f,
330 "timelock unlock condition with milestone index and timestamp set to 0",
331 )
332 }
333 Error::UnallowedFeature { index, kind } => {
334 write!(f, "unallowed feature at index {} with kind {}", index, kind)
335 }
336 Error::UnallowedUnlockCondition { index, kind } => {
337 write!(f, "unallowed unlock condition at index {} with kind {}", index, kind)
338 }
339 Error::UnlockConditionsNotUniqueSorted => write!(f, "unlock conditions are not unique and/or sorted"),
340 Error::UnsupportedOutputKind(k) => write!(f, "unsupported output kind: {k}"),
341 }
342 }
343}
344
345impl From<CryptoError> for Error {
346 fn from(error: CryptoError) -> Self {
347 Error::CryptoError(error)
348 }
349}
350
351impl From<Infallible> for Error {
352 fn from(err: Infallible) -> Self {
353 match err {}
354 }
355}
356
357#[cfg(feature = "dto")]
358#[allow(missing_docs)]
359pub mod dto {
360 use super::*;
361
362 #[derive(Debug)]
363 pub enum DtoError {
364 InvalidField(&'static str),
365 Block(Error),
366 }
367
368 impl fmt::Display for DtoError {
369 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
370 match self {
371 DtoError::InvalidField(field) => write!(f, "{field}"),
372 DtoError::Block(error) => write!(f, "{error}"),
373 }
374 }
375 }
376
377 impl From<Error> for DtoError {
378 fn from(error: Error) -> Self {
379 DtoError::Block(error)
380 }
381 }
382
383 #[cfg(feature = "std")]
384 impl std::error::Error for DtoError {}
385}
386
387#[cfg(feature = "inx")]
388#[allow(missing_docs)]
389pub mod inx {
390 use super::*;
391
392 #[derive(Debug)]
393 #[allow(missing_docs)]
394 pub enum InxError {
395 InvalidId(&'static str, Vec<u8>),
396 InvalidString(String),
397 InvalidRawBytes(String),
398 MissingField(&'static str),
399 Block(Error),
400 }
401
402 impl fmt::Display for InxError {
403 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
404 match self {
405 InxError::InvalidId(ty, bytes) => write!(f, "invalid `{ty}` with bytes `{}`", hex::encode(bytes)),
406 InxError::InvalidString(error) => write!(f, "invalid string: {error}"),
407 InxError::InvalidRawBytes(error) => write!(f, "invalid raw bytes: {error}"),
408 InxError::MissingField(field) => write!(f, "missing field `{field}`"),
409 InxError::Block(error) => write!(f, "{error}"),
410 }
411 }
412 }
413
414 impl From<Error> for InxError {
415 fn from(error: Error) -> Self {
416 InxError::Block(error)
417 }
418 }
419
420 #[cfg(feature = "std")]
421 impl std::error::Error for InxError {}
422}