307 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			307 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #pragma once
 | |
| 
 | |
| #include <boost/filesystem/operations.hpp>
 | |
| #include <boost/system/error_code.hpp>
 | |
| 
 | |
| #include <algorithm>
 | |
| #include <functional>
 | |
| #include <memory>
 | |
| #include <string>
 | |
| #include <system_error>
 | |
| #include <type_traits>
 | |
| 
 | |
| namespace nano
 | |
| {
 | |
| /** Common error codes */
 | |
| enum class error_common
 | |
| {
 | |
| 	generic = 1,
 | |
| 	exception,
 | |
| 	access_denied,
 | |
| 	account_not_found,
 | |
| 	account_not_found_wallet,
 | |
| 	account_exists,
 | |
| 	bad_account_number,
 | |
| 	bad_balance,
 | |
| 	bad_link,
 | |
| 	bad_previous,
 | |
| 	bad_representative_number,
 | |
| 	bad_source,
 | |
| 	bad_signature,
 | |
| 	bad_private_key,
 | |
| 	bad_public_key,
 | |
| 	bad_seed,
 | |
| 	bad_threshold,
 | |
| 	bad_wallet_number,
 | |
| 	bad_work_format,
 | |
| 	disabled_local_work_generation,
 | |
| 	disabled_work_generation,
 | |
| 	failure_work_generation,
 | |
| 	missing_account,
 | |
| 	missing_balance,
 | |
| 	missing_link,
 | |
| 	missing_previous,
 | |
| 	missing_representative,
 | |
| 	missing_signature,
 | |
| 	missing_work,
 | |
| 	invalid_amount,
 | |
| 	invalid_amount_big,
 | |
| 	invalid_count,
 | |
| 	invalid_index,
 | |
| 	invalid_ip_address,
 | |
| 	invalid_port,
 | |
| 	invalid_type_conversion,
 | |
| 	invalid_work,
 | |
| 	insufficient_balance,
 | |
| 	is_not_state_block,
 | |
| 	numeric_conversion,
 | |
| 	tracking_not_enabled,
 | |
| 	wallet_lmdb_max_dbs,
 | |
| 	wallet_locked,
 | |
| 	wallet_not_found
 | |
| };
 | |
| 
 | |
| /** Block related errors */
 | |
| enum class error_blocks
 | |
| {
 | |
| 	generic = 1,
 | |
| 	bad_hash_number,
 | |
| 	invalid_block,
 | |
| 	invalid_block_hash,
 | |
| 	invalid_type,
 | |
| 	not_found,
 | |
| 	work_low
 | |
| };
 | |
| 
 | |
| /** RPC related errors */
 | |
| enum class error_rpc
 | |
| {
 | |
| 	generic = 1,
 | |
| 	empty_response,
 | |
| 	bad_destination,
 | |
| 	bad_difficulty_format,
 | |
| 	bad_key,
 | |
| 	bad_link,
 | |
| 	bad_multiplier_format,
 | |
| 	bad_previous,
 | |
| 	bad_representative_number,
 | |
| 	bad_source,
 | |
| 	bad_timeout,
 | |
| 	bad_work_version,
 | |
| 	block_create_balance_mismatch,
 | |
| 	block_create_key_required,
 | |
| 	block_create_public_key_mismatch,
 | |
| 	block_create_requirements_state,
 | |
| 	block_create_requirements_open,
 | |
| 	block_create_requirements_receive,
 | |
| 	block_create_requirements_change,
 | |
| 	block_create_requirements_send,
 | |
| 	block_root_mismatch,
 | |
| 	block_work_enough,
 | |
| 	block_work_version_mismatch,
 | |
| 	confirmation_height_not_processing,
 | |
| 	confirmation_not_found,
 | |
| 	difficulty_limit,
 | |
| 	disabled_bootstrap_lazy,
 | |
| 	disabled_bootstrap_legacy,
 | |
| 	invalid_balance,
 | |
| 	invalid_destinations,
 | |
| 	invalid_epoch,
 | |
| 	invalid_epoch_signer,
 | |
| 	invalid_offset,
 | |
| 	invalid_missing_type,
 | |
| 	invalid_root,
 | |
| 	invalid_sources,
 | |
| 	invalid_subtype,
 | |
| 	invalid_subtype_balance,
 | |
| 	invalid_subtype_epoch_link,
 | |
| 	invalid_subtype_previous,
 | |
| 	invalid_timestamp,
 | |
| 	invalid_threads_count,
 | |
| 	peer_not_found,
 | |
| 	pruning_disabled,
 | |
| 	requires_port_and_address,
 | |
| 	rpc_control_disabled,
 | |
| 	sign_hash_disabled,
 | |
| 	source_not_found
 | |
| };
 | |
| 
 | |
| /** process_result related errors */
 | |
| enum class error_process
 | |
| {
 | |
| 	generic = 1,
 | |
| 	bad_signature, // Signature was bad, forged or transmission error
 | |
| 	old, // Already seen and was valid
 | |
| 	negative_spend, // Malicious attempt to spend a negative amount
 | |
| 	fork, // Malicious fork based on previous
 | |
| 	unreceivable, // Source block doesn't exist or has already been received
 | |
| 	gap_previous, // Block marked as previous is unknown
 | |
| 	gap_source, // Block marked as source is unknown
 | |
| 	gap_epoch_open_pending, // Block marked as pending blocks required for epoch open block are unknown
 | |
| 	opened_burn_account, // The impossible happened, someone found the private key associated with the public key '0'.
 | |
| 	balance_mismatch, // Balance and amount delta don't match
 | |
| 	block_position, // This block cannot follow the previous block
 | |
| 	insufficient_work, // Insufficient work for this block, even though it passed the minimal validation
 | |
| 	other
 | |
| };
 | |
| 
 | |
| /** config.json deserialization related errors */
 | |
| enum class error_config
 | |
| {
 | |
| 	generic = 1,
 | |
| 	invalid_value,
 | |
| 	missing_value
 | |
| };
 | |
| } // nano namespace
 | |
| 
 | |
| // Convenience macro to implement the standard boilerplate for using std::error_code with enums
 | |
| // Use this at the end of any header defining one or more error code enums.
 | |
| #define REGISTER_ERROR_CODES(namespace_name, enum_type)                                                        \
 | |
| 	namespace namespace_name                                                                                   \
 | |
| 	{                                                                                                          \
 | |
| 		static_assert (static_cast<int> (enum_type::generic) > 0, "The first error enum must be generic = 1"); \
 | |
| 		class enum_type##_messages : public std::error_category                                                \
 | |
| 		{                                                                                                      \
 | |
| 		public:                                                                                                \
 | |
| 			const char * name () const noexcept override                                                       \
 | |
| 			{                                                                                                  \
 | |
| 				return #enum_type;                                                                             \
 | |
| 			}                                                                                                  \
 | |
|                                                                                                                \
 | |
| 			std::string message (int ev) const override;                                                       \
 | |
| 		};                                                                                                     \
 | |
|                                                                                                                \
 | |
| 		inline const std::error_category & enum_type##_category ()                                             \
 | |
| 		{                                                                                                      \
 | |
| 			static enum_type##_messages instance;                                                              \
 | |
| 			return instance;                                                                                   \
 | |
| 		}                                                                                                      \
 | |
|                                                                                                                \
 | |
| 		inline std::error_code make_error_code (::namespace_name::enum_type err)                               \
 | |
| 		{                                                                                                      \
 | |
| 			return { static_cast<int> (err), enum_type##_category () };                                        \
 | |
| 		}                                                                                                      \
 | |
| 	}                                                                                                          \
 | |
| 	namespace std                                                                                              \
 | |
| 	{                                                                                                          \
 | |
| 		template <>                                                                                            \
 | |
| 		struct is_error_code_enum<::namespace_name::enum_type> : std::true_type                                \
 | |
| 		{                                                                                                      \
 | |
| 		};                                                                                                     \
 | |
| 	}
 | |
| 
 | |
| REGISTER_ERROR_CODES (nano, error_common);
 | |
| REGISTER_ERROR_CODES (nano, error_blocks);
 | |
| REGISTER_ERROR_CODES (nano, error_rpc);
 | |
| REGISTER_ERROR_CODES (nano, error_process);
 | |
| REGISTER_ERROR_CODES (nano, error_config);
 | |
| 
 | |
| /* boost->std error_code bridge */
 | |
| namespace nano
 | |
| {
 | |
| namespace error_conversion
 | |
| {
 | |
| 	const std::error_category & generic_category ();
 | |
| }
 | |
| }
 | |
| 
 | |
| namespace std
 | |
| {
 | |
| template <>
 | |
| struct is_error_code_enum<boost::system::errc::errc_t>
 | |
| 	: public std::true_type
 | |
| {
 | |
| };
 | |
| 
 | |
| std::error_code make_error_code (boost::system::errc::errc_t const & e);
 | |
| }
 | |
| namespace nano
 | |
| {
 | |
| namespace error_conversion
 | |
| {
 | |
| 	namespace detail
 | |
| 	{
 | |
| 		class generic_category : public std::error_category
 | |
| 		{
 | |
| 		public:
 | |
| 			const char * name () const noexcept override;
 | |
| 			std::string message (int value) const override;
 | |
| 		};
 | |
| 	}
 | |
| 	const std::error_category & generic_category ();
 | |
| 	std::error_code convert (const boost::system::error_code & error);
 | |
| }
 | |
| }
 | |
| 
 | |
| namespace nano
 | |
| {
 | |
| /** Adapter for std/boost::error_code, std::exception and bool flags to facilitate unified error handling */
 | |
| class error
 | |
| {
 | |
| public:
 | |
| 	error () = default;
 | |
| 	error (nano::error const & error_a) = default;
 | |
| 	error (nano::error && error_a) = default;
 | |
| 
 | |
| 	error (std::error_code code_a);
 | |
| 	error (boost::system::error_code const & code_a);
 | |
| 	error (std::string message_a);
 | |
| 	error (std::exception const & exception_a);
 | |
| 	error & operator= (nano::error const & err_a);
 | |
| 	error & operator= (nano::error && err_a);
 | |
| 	error & operator= (const std::error_code code_a);
 | |
| 	error & operator= (const boost::system::error_code & code_a);
 | |
| 	error & operator= (const boost::system::errc::errc_t & code_a);
 | |
| 	error & operator= (const std::string message_a);
 | |
| 	error & operator= (std::exception const & exception_a);
 | |
| 	bool operator== (const std::error_code code_a) const;
 | |
| 	bool operator== (const boost::system::error_code code_a) const;
 | |
| 	error & then (std::function<nano::error &()> next);
 | |
| 	template <typename... ErrorCode>
 | |
| 	error & accept (ErrorCode... err)
 | |
| 	{
 | |
| 		// Convert variadic arguments to std::error_code
 | |
| 		auto codes = { std::error_code (err)... };
 | |
| 		if (std::any_of (codes.begin (), codes.end (), [this, &codes] (auto & code_a) { return code == code_a; }))
 | |
| 		{
 | |
| 			code.clear ();
 | |
| 		}
 | |
| 
 | |
| 		return *this;
 | |
| 	}
 | |
| 
 | |
| 	explicit operator std::error_code () const;
 | |
| 	explicit operator bool () const;
 | |
| 	explicit operator std::string () const;
 | |
| 	std::string get_message () const;
 | |
| 	/**
 | |
| 	 * The error code as an integer. Note that some error codes have platform dependent values.
 | |
| 	 * A return value of 0 signifies there is no error.
 | |
| 	 */
 | |
| 	int error_code_as_int () const;
 | |
| 	error & on_error (std::string message_a);
 | |
| 	error & on_error (std::error_code code_a, std::string message_a);
 | |
| 	error & set (std::string message_a, std::error_code code_a = nano::error_common::generic);
 | |
| 	error & set_message (std::string message_a);
 | |
| 	error & clear ();
 | |
| 
 | |
| private:
 | |
| 	std::error_code code;
 | |
| 	std::string message;
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * A type that manages a nano::error.
 | |
|  * The default return type is nano::error&, though shared_ptr<nano::error> is a good option in cases
 | |
|  * where shared error state is desirable.
 | |
|  */
 | |
| template <typename RET_TYPE = nano::error &>
 | |
| class error_aware
 | |
| {
 | |
| 	static_assert (std::is_same<RET_TYPE, nano::error &>::value || std::is_same<RET_TYPE, std::shared_ptr<nano::error>>::value, "Must be nano::error& or shared_ptr<nano::error>");
 | |
| 
 | |
| public:
 | |
| 	/** Returns the error object managed by this object */
 | |
| 	virtual RET_TYPE get_error () = 0;
 | |
| };
 | |
| }
 | 
