cf3fd00350
* - standardise versions for all nym-sdk workspace dependencies - prepend sqlx-pool-guard with 'nym-' * Test remove nym-api from deps * Add oneliner to client_pool doc comments * Add note to commented out docs.rs link in sdk * remove nym-api from script * add publishing file * bring non-binary / contract / tools into workspace version * added more info to publishing.md * make deps workspace version * remove uploaded sphinx-types crate from script * remove erroueously included ignore-defaults * add zeroise to feature * chore: Release * add topology to batch * more cargo versioning * more cargo versioning - wasm utils * more cargo versioning - wasm utils * Add publish=false to manifest for cargo workspaces / crates.io publishing exclusion * remove script now switched to manifest based exclusion * rename import based on rename of contracts-common dep * Making workspace versions for publication + removing unnecessary crates from publication * Remove OOD info from publishing sdk guide * rename contract imports + remove package * temp commit: continuing with removal of path from cargo manifest and replacing with workspace version import for publication * continuing with cargo.toml updates * dryrun only erroring on known version problem crates * remove old published-crates file * Minor comment change * remove default features warning * Additional info on workspace dep comment re publish list * Add missing description to cargo.toml * Fix missing feature flags * Add missing descriptions * Fix remaining path import * Add workspace repo / homepage / documentation links to cargo.toml files * remove workspace version from excluded crate * Remove todo descriptions * Minor comment change * add homepage etc * move from bls git import to nym_bls_fork crate * Modify rest of imports from path to workspace import, excluding binaries * add directory/homepage info * fix cargo fmt * add notes to gitignore * better solution to contracts/ experiment * wasm -> nym_wasm crate renaming * fix fatfinger * add metadata to ecash cargo.toml * stub publishing guide * fix misrevolved netlink- version * Fixes and block publication of rebase re: LP * first pass @ workflows
323 lines
10 KiB
Rust
323 lines
10 KiB
Rust
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
use crate::nym_node::Role;
|
|
use crate::{
|
|
EpochEventId, EpochState, IntervalEventId, NodeId, OperatingCostRange, ProfitMarginRange,
|
|
};
|
|
use cosmwasm_std::{Addr, Coin, Decimal, Uint128};
|
|
use cw_controllers::AdminError;
|
|
use nym_contracts_common::Percent;
|
|
use nym_contracts_common::signing::verifier::ApiVerifierError;
|
|
use thiserror::Error;
|
|
|
|
#[derive(Error, Debug, PartialEq)]
|
|
pub enum MixnetContractError {
|
|
#[error("could not perform contract migration: {comment}")]
|
|
FailedMigration { comment: String },
|
|
|
|
#[error(transparent)]
|
|
Admin(#[from] AdminError),
|
|
|
|
#[error("{source}")]
|
|
StdErr {
|
|
#[from]
|
|
source: cosmwasm_std::StdError,
|
|
},
|
|
|
|
#[error("Attempted to subtract decimals with overflow ({minuend}.sub({subtrahend}))")]
|
|
OverflowDecimalSubtraction {
|
|
minuend: Decimal,
|
|
subtrahend: Decimal,
|
|
},
|
|
|
|
#[error("Attempted to subtract with overflow ({minuend}.sub({subtrahend}))")]
|
|
OverflowSubtraction { minuend: u64, subtrahend: u64 },
|
|
|
|
#[error("Not enough funds sent for node pledge. (received {received}, minimum {minimum})")]
|
|
InsufficientPledge { received: Coin, minimum: Coin },
|
|
|
|
#[error(
|
|
"the provided value for node host is too long. it must not be longer than 255 characters"
|
|
)]
|
|
HostTooLong,
|
|
|
|
#[error(
|
|
"the provided node identity public key is not a correctly encoded base58 slice of 32 bytes"
|
|
)]
|
|
InvalidPubKey,
|
|
|
|
#[error(
|
|
"Attempted to reduce node pledge ({current}{denom} - {decrease_by}{denom}) below the minimum amount: {minimum}{denom}"
|
|
)]
|
|
InvalidPledgeReduction {
|
|
current: Uint128,
|
|
decrease_by: Uint128,
|
|
minimum: Uint128,
|
|
denom: String,
|
|
},
|
|
|
|
#[error("A pledge change is already pending in this epoch. The event id: {pending_event_id}")]
|
|
PendingPledgeChange { pending_event_id: EpochEventId },
|
|
|
|
#[error(
|
|
"A cost params change is already pending in this epoch. The event id: {pending_event_id}"
|
|
)]
|
|
PendingParamsChange { pending_event_id: IntervalEventId },
|
|
|
|
#[error("Not enough funds sent for node delegation. (received {received}, minimum {minimum})")]
|
|
InsufficientDelegation { received: Coin, minimum: Coin },
|
|
|
|
#[error("Node ({node_id}) does not exist")]
|
|
NymNodeBondNotFound { node_id: NodeId },
|
|
|
|
#[error("Mixnode ({mix_id}) does not exist")]
|
|
MixNodeBondNotFound { mix_id: NodeId },
|
|
|
|
#[error("{owner} does not seem to own any mixnodes")]
|
|
NoAssociatedMixNodeBond { owner: Addr },
|
|
|
|
#[error("{owner} does not seem to own any gateways")]
|
|
NoAssociatedGatewayBond { owner: Addr },
|
|
|
|
#[error("{owner} does not seem to own any nodes")]
|
|
NoAssociatedNodeBond { owner: Addr },
|
|
|
|
#[error("This address has already bonded a mixnode")]
|
|
AlreadyOwnsMixnode,
|
|
|
|
#[error("This address has already bonded a gateway")]
|
|
AlreadyOwnsGateway,
|
|
|
|
#[error("This address has already bonded a nym-node")]
|
|
AlreadyOwnsNymNode,
|
|
|
|
#[error("Gateway with this identity already exists. Its owner is {owner}")]
|
|
DuplicateGateway { owner: Addr },
|
|
|
|
#[error("Unauthorized")]
|
|
Unauthorized,
|
|
|
|
#[error("No tokens were sent for the bonding")]
|
|
NoBondFound,
|
|
|
|
#[error("No funds were provided for the delegation")]
|
|
EmptyDelegation,
|
|
|
|
#[error("Wrong coin denomination. Received: {received}, expected: {expected}")]
|
|
WrongDenom { received: String, expected: String },
|
|
|
|
#[error("Received multiple coin types during staking")]
|
|
MultipleDenoms,
|
|
|
|
#[error("Proxy address ({received}) is not set to the vesting contract ({vesting_contract})")]
|
|
ProxyIsNotVestingContract {
|
|
received: Addr,
|
|
vesting_contract: Addr,
|
|
},
|
|
|
|
#[error("Failed to recover ed25519 public key from its base58 representation - {0}")]
|
|
MalformedEd25519IdentityKey(String),
|
|
|
|
#[error("Failed to recover ed25519 signature from its base58 representation - {0}")]
|
|
MalformedEd25519Signature(String),
|
|
|
|
#[error("Provided ed25519 signature did not verify correctly")]
|
|
InvalidEd25519Signature,
|
|
|
|
#[error(
|
|
"Can't perform the specified action as the current epoch is still progress. It started at {epoch_start} and finishes at {epoch_end}, while the current block time is {current_block_time}"
|
|
)]
|
|
EpochInProgress {
|
|
current_block_time: u64,
|
|
epoch_start: i64,
|
|
epoch_end: i64,
|
|
},
|
|
|
|
#[error("attempted to reward a gateway node - this has not been fully integrated yet")]
|
|
GatewayRewarding,
|
|
|
|
#[error(
|
|
"node {node_id} has already been rewarded during the current rewarding epoch ({absolute_epoch_id})"
|
|
)]
|
|
NodeAlreadyRewarded {
|
|
node_id: NodeId,
|
|
absolute_epoch_id: u32,
|
|
},
|
|
|
|
#[error("node {node_id} hasn't been assigned the role of {role} for this epoch")]
|
|
IncorrectEpochRole { node_id: NodeId, role: Role },
|
|
|
|
#[error("Mixnode {mix_id} is currently in the process of unbonding")]
|
|
MixnodeIsUnbonding { mix_id: NodeId },
|
|
|
|
#[error("Node {node_id} is currently in the process of unbonding")]
|
|
NodeIsUnbonding { node_id: NodeId },
|
|
|
|
#[error("Mixnode {mix_id} has already unbonded")]
|
|
MixnodeHasUnbonded { mix_id: NodeId },
|
|
|
|
#[error("The contract has ended up in a state that was deemed impossible: {comment}")]
|
|
InconsistentState { comment: String },
|
|
|
|
#[error(
|
|
"Could not find any delegation information associated with node {node_id} for {address} (proxy: {proxy:?})"
|
|
)]
|
|
NodeDelegationNotFound {
|
|
node_id: NodeId,
|
|
address: String,
|
|
proxy: Option<String>,
|
|
},
|
|
|
|
#[error("Provided message to update rewarding params did not contain any updates")]
|
|
EmptyParamsChangeMsg,
|
|
|
|
#[error("provided message to update state parameters did not contain any updates")]
|
|
EmptyStateUpdateMsg,
|
|
|
|
#[error("one of the roles in the new active set is empty")]
|
|
EmptyRoleAssignment,
|
|
|
|
#[error(
|
|
"the number of mixnodes in the rewarded set is not divisible by the number of mix-layers (3)"
|
|
)]
|
|
UnevenLayerAssignment,
|
|
|
|
#[error("provided active set is bigger than the rewarded set")]
|
|
InvalidActiveSetSize,
|
|
|
|
#[error("Invalid layer expected 1, 2 or 3, got {0}")]
|
|
InvalidLayer(u8),
|
|
|
|
#[error("Feature is not yet implemented")]
|
|
NotImplemented,
|
|
|
|
#[error("epochs_in_interval must be > 0")]
|
|
EpochsInIntervalZero,
|
|
|
|
#[error("epoch duration must be > 0")]
|
|
EpochDurationZero,
|
|
|
|
#[error("attempted to perform the operation with 0 coins. This is not allowed")]
|
|
ZeroCoinAmount,
|
|
|
|
#[error("key rotation validity below minimum value")]
|
|
TooShortRotationInterval,
|
|
|
|
#[error(
|
|
"this validator ({current_validator}) is not the one responsible for advancing this epoch. It's responsibility of {chosen_validator}."
|
|
)]
|
|
RewardingValidatorMismatch {
|
|
current_validator: Addr,
|
|
chosen_validator: Addr,
|
|
},
|
|
|
|
#[error(
|
|
"the epoch is currently in the process of being advanced. (the state is {current_state}) Please try sending your transaction again once this has finished"
|
|
)]
|
|
EpochAdvancementInProgress { current_state: EpochState },
|
|
|
|
#[error(
|
|
"the epoch is in an unexpected state. expected 'mix rewarding' state, but we're in {current_state} instead."
|
|
)]
|
|
UnexpectedNonRewardingEpochState { current_state: EpochState },
|
|
|
|
#[error(
|
|
"attempted to reward mixnode out of order. Attempted to reward {attempted_to_reward} while last rewarded was {last_rewarded}."
|
|
)]
|
|
RewardingOutOfOrder {
|
|
last_rewarded: NodeId,
|
|
attempted_to_reward: NodeId,
|
|
},
|
|
|
|
#[error(
|
|
"the epoch is currently not in the 'event reconciliation' state. (the state is {current_state})"
|
|
)]
|
|
EpochNotInEventReconciliationState { current_state: EpochState },
|
|
|
|
#[error(
|
|
"the epoch is currently not in the 'role assignment' state. (the state is {current_state})"
|
|
)]
|
|
EpochNotInRoleAssignmentState { current_state: EpochState },
|
|
|
|
#[error("unexpected role assignment. got: {got} while expected: {expected}")]
|
|
UnexpectedRoleAssignment { expected: Role, got: Role },
|
|
|
|
#[error(
|
|
"attempted to assign an invalid number of nodes for a role of {role}. got {assigned}, but the maximum allowed is {allowed}"
|
|
)]
|
|
IllegalRoleCount {
|
|
role: Role,
|
|
assigned: u32,
|
|
allowed: u32,
|
|
},
|
|
|
|
#[error(
|
|
"the epoch is currently not in the 'epoch advancement' state. (the state is {current_state})"
|
|
)]
|
|
EpochNotInAdvancementState { current_state: EpochState },
|
|
|
|
#[error("failed to verify message signature: {source}")]
|
|
SignatureVerificationFailure {
|
|
#[from]
|
|
source: ApiVerifierError,
|
|
},
|
|
|
|
#[error(
|
|
"this operation is no longer allowed to be performed with vesting tokens. please move them to your liquid balance and try again"
|
|
)]
|
|
DisabledVestingOperation,
|
|
|
|
#[error(
|
|
"this mixnode has not been bonded with the vesting tokens or has already been migrated"
|
|
)]
|
|
NotAVestingMixnode,
|
|
|
|
#[error(
|
|
"this delegation has not been performed with the vesting tokens or has already been migrated"
|
|
)]
|
|
NotAVestingDelegation,
|
|
|
|
#[error("the provided profit margin ({provided}) is outside the allowed range: {range}")]
|
|
ProfitMarginOutsideRange {
|
|
provided: Percent,
|
|
range: ProfitMarginRange,
|
|
},
|
|
|
|
#[error(
|
|
"the provided interval operating cost ({provided}{denom}) is outside the allowed range: {range}"
|
|
)]
|
|
OperatingCostOutsideRange {
|
|
denom: String,
|
|
provided: Uint128,
|
|
range: OperatingCostRange,
|
|
},
|
|
|
|
#[error(
|
|
"currently it's not possible to migrate nodes bonded with vesting tokens into a nym-node. please perform vesting->liquid migration first."
|
|
)]
|
|
VestingNodeMigration,
|
|
|
|
#[error("value {got} does not correspond to any known node role")]
|
|
UnknownRoleRepresentation { got: u8 },
|
|
|
|
#[error("the total work for this epoch seems to be bigger than 1.0!")]
|
|
TotalWorkAboveOne,
|
|
|
|
#[error("the provided nym-node version is not a valid semver. got: {provided}")]
|
|
InvalidNymNodeSemver { provided: String },
|
|
|
|
#[error(
|
|
"the provided nym-node version is not greater than the current one. got: {provided}. current: {current}"
|
|
)]
|
|
NonIncreasingSemver { provided: String, current: String },
|
|
}
|
|
|
|
impl MixnetContractError {
|
|
pub fn inconsistent_state<S: Into<String>>(comment: S) -> Self {
|
|
MixnetContractError::InconsistentState {
|
|
comment: comment.into(),
|
|
}
|
|
}
|
|
}
|