You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: errors.rs
    path of file: ./repos/nearcore/core/primitives/src
    
    the code of the file until where you have to start completion: use crate::hash::CryptoHash;
use crate::serialize::dec_format;
use crate::types::{AccountId, Balance, EpochId, Gas, Nonce};
use borsh::{BorshDeserialize, BorshSerialize};
use near_crypto::PublicKey;
use near_primitives_core::types::ProtocolVersion;
use near_rpc_error_macro::RpcError;
use std::fmt::{Debug, Display};

/// Error returned in the ExecutionOutcome in case of failure
#[derive(
    BorshSerialize,
    BorshDeserialize,
    Debug,
    Clone,
    PartialEq,
    Eq,
    RpcError,
    serde::Deserialize,
    serde::Serialize,
)]
pub enum TxExecutionError {
    /// An error happened during Action execution
    ActionError(ActionError),
    /// An error happened during Transaction execution
    InvalidTxError(InvalidTxError),
}

impl std::error::Error for TxExecutionError {}

impl Display for TxExecutionError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
        match self {
            TxExecutionError::ActionError(e) => write!(f, "{}", e),
            TxExecutionError::InvalidTxError(e) => write!(f, "{}", e),
        }
    
    
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            EpochError::ThresholdError { stake_sum, num_seats } => write!(
                f,
                "Total stake {} must be higher than the number of seats {}",
                stake_sum, num_seats
            ),
            EpochError::EpochOutOfBounds(epoch_id) => {
                write!(f, "Epoch {:?} is out of bounds", epoch_id)
            }
            EpochError::MissingBlock(hash) => write!(f, "Missing block {}", hash),
            EpochError::IOErr(err) => write!(f, "IO: {}", err),
            EpochError::NotAValidator(account_id, epoch_id) => {
                write!(f, "{} is not a validator in epoch {:?}", account_id, epoch_id)
            }
            EpochError::ShardingError(err) => write!(f, "Sharding Error: {}", err),
            EpochError::NotEnoughValidators { num_shards, num_validators } => {
                write!(f, "There were not enough validator proposals to fill all shards. num_proposals: {}, num_shards: {}", num_validators, num_shards)
            }
            EpochError::ChunkValidatorSelectionError(err) => {
                write!(f, "Error selecting validators for a chunk: {}", err)
            }
            EpochError::ChunkProducerSelectionError(err) => {
                write!(f, "Error selecting chunk producer: {}", err)
            }
        }
    }