iota_source_validation/
error.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::fmt;
6
7use iota_json_rpc_types::IotaRawMoveObject;
8use iota_package_management::PublishedAtError;
9use iota_sdk::error::Error as SdkError;
10use iota_types::{base_types::ObjectID, error::IotaObjectResponseError};
11use move_core_types::account_address::AccountAddress;
12use move_symbol_pool::Symbol;
13
14#[derive(Debug, thiserror::Error)]
15pub struct AggregateError(pub(crate) Vec<Error>);
16
17#[derive(Debug, thiserror::Error)]
18pub enum Error {
19    #[error("Cannot check local module for {package}: {message}")]
20    CannotCheckLocalModules { package: Symbol, message: String },
21
22    #[error("Could not read a dependency's on-chain object: {0:?}")]
23    DependencyObjectReadFailure(SdkError),
24
25    #[error("On-chain package {0} is empty")]
26    EmptyOnChainPackage(AccountAddress),
27
28    #[error("Invalid module {name} with error: {message}")]
29    InvalidModuleFailure { name: String, message: String },
30
31    #[error("Local version of dependency {address}::{module} was not found.")]
32    LocalDependencyNotFound {
33        address: AccountAddress,
34        module: Symbol,
35    },
36
37    #[error("Source package depends on {0} which is not in the linkage table.")]
38    MissingDependencyInLinkageTable(AccountAddress),
39
40    #[error("On-chain package depends on {0} which is not a source dependency.")]
41    MissingDependencyInSourcePackage(AccountAddress),
42
43    #[error(
44        "Local dependency did not match its on-chain version at {address}::{package}::{module}"
45    )]
46    ModuleBytecodeMismatch {
47        address: AccountAddress,
48        package: Symbol,
49        module: Symbol,
50    },
51
52    #[error("Dependency ID contains an IOTA object, not a Move package: {}", .0.0)]
53    ObjectFoundWhenPackageExpected(Box<(ObjectID, IotaRawMoveObject)>),
54
55    #[error("Could not deserialize on-chain dependency {address}::{module}.")]
56    OnChainDependencyDeserializationError {
57        address: AccountAddress,
58        module: Symbol,
59    },
60
61    #[error("On-chain version of dependency {package}::{module} was not found.")]
62    OnChainDependencyNotFound { package: Symbol, module: Symbol },
63
64    #[error("{0}. Please supply an explicit on-chain address for the package")]
65    PublishedAt(#[from] PublishedAtError),
66
67    #[error("Dependency object does not exist or was deleted: {0:?}")]
68    IotaObjectRefFailure(IotaObjectResponseError),
69
70    #[error("On-chain address cannot be zero")]
71    ZeroOnChainAddressSpecifiedFailure,
72}
73
74impl fmt::Display for AggregateError {
75    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76        let Self(errors) = self;
77        match &errors[..] {
78            [] => unreachable!("Aggregate error with no errors"),
79            [error] => write!(f, "{}", error)?,
80            errors => {
81                writeln!(f, "Multiple source verification errors found:")?;
82                for error in errors {
83                    write!(f, "\n- {}", error)?;
84                }
85                return Ok(());
86            }
87        };
88        Ok(())
89    }
90}
91
92impl From<Error> for AggregateError {
93    fn from(error: Error) -> Self {
94        Self(vec![error])
95    }
96}