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