diff --git a/builds/gnu/Makefile.am b/builds/gnu/Makefile.am index 659e6cd2..716b796f 100644 --- a/builds/gnu/Makefile.am +++ b/builds/gnu/Makefile.am @@ -48,21 +48,24 @@ src_libbitcoin_server_la_LIBADD = \ src_libbitcoin_server_la_SOURCES = \ ${srcdir}/../../src/configuration.cpp \ - ${srcdir}/../../src/error.cpp \ ${srcdir}/../../src/parser.cpp \ ${srcdir}/../../src/server_node.cpp \ ${srcdir}/../../src/settings.cpp \ + ${srcdir}/../../src/error/bitcoind_error_t.cpp \ + ${srcdir}/../../src/error/btcd_error_t.cpp \ + ${srcdir}/../../src/error/electrum_error_t.cpp \ + ${srcdir}/../../src/error/error_t.cpp \ ${srcdir}/../../src/parsers/admin_query.cpp \ ${srcdir}/../../src/parsers/admin_target.cpp \ + ${srcdir}/../../src/parsers/bitcoind_block_stats.cpp \ + ${srcdir}/../../src/parsers/bitcoind_descriptor.cpp \ + ${srcdir}/../../src/parsers/bitcoind_merkle.cpp \ ${srcdir}/../../src/parsers/bitcoind_script.cpp \ ${srcdir}/../../src/parsers/bitcoind_target.cpp \ - ${srcdir}/../../src/parsers/block_stats.cpp \ ${srcdir}/../../src/parsers/btcd_filter.cpp \ - ${srcdir}/../../src/parsers/descriptor.cpp \ ${srcdir}/../../src/parsers/electrum_version.cpp \ ${srcdir}/../../src/parsers/native_query.cpp \ ${srcdir}/../../src/parsers/native_target.cpp \ - ${srcdir}/../../src/parsers/partial_merkle.cpp \ ${srcdir}/../../src/protocols/protocol_html.cpp \ ${srcdir}/../../src/protocols/protocol_http.cpp \ ${srcdir}/../../src/protocols/admin/protocol_admin.cpp \ @@ -115,7 +118,6 @@ include_bitcoin_serverdir = \ include_bitcoin_server_HEADERS = \ ${srcdir}/../../include/bitcoin/server/configuration.hpp \ ${srcdir}/../../include/bitcoin/server/define.hpp \ - ${srcdir}/../../include/bitcoin/server/error.hpp \ ${srcdir}/../../include/bitcoin/server/parser.hpp \ ${srcdir}/../../include/bitcoin/server/server_node.hpp \ ${srcdir}/../../include/bitcoin/server/settings.hpp \ @@ -132,6 +134,16 @@ include_bitcoin_server_channels_HEADERS = \ ${srcdir}/../../include/bitcoin/server/channels/channel_stratum_v2.hpp \ ${srcdir}/../../include/bitcoin/server/channels/channels.hpp +include_bitcoin_server_errordir = \ + ${includedir}/bitcoin/server/error + +include_bitcoin_server_error_HEADERS = \ + ${srcdir}/../../include/bitcoin/server/error/bitcoind_error_t.hpp \ + ${srcdir}/../../include/bitcoin/server/error/btcd_error_t.hpp \ + ${srcdir}/../../include/bitcoin/server/error/electrum_error_t.hpp \ + ${srcdir}/../../include/bitcoin/server/error/error.hpp \ + ${srcdir}/../../include/bitcoin/server/error/error_t.hpp + include_bitcoin_server_impl_protocolsdir = \ ${includedir}/bitcoin/server/impl/protocols @@ -167,16 +179,16 @@ include_bitcoin_server_parsersdir = \ include_bitcoin_server_parsers_HEADERS = \ ${srcdir}/../../include/bitcoin/server/parsers/admin_query.hpp \ ${srcdir}/../../include/bitcoin/server/parsers/admin_target.hpp \ + ${srcdir}/../../include/bitcoin/server/parsers/bitcoind_block_stats.hpp \ + ${srcdir}/../../include/bitcoin/server/parsers/bitcoind_descriptor.hpp \ + ${srcdir}/../../include/bitcoin/server/parsers/bitcoind_merkle.hpp \ ${srcdir}/../../include/bitcoin/server/parsers/bitcoind_script.hpp \ ${srcdir}/../../include/bitcoin/server/parsers/bitcoind_target.hpp \ - ${srcdir}/../../include/bitcoin/server/parsers/block_stats.hpp \ ${srcdir}/../../include/bitcoin/server/parsers/btcd_filter.hpp \ - ${srcdir}/../../include/bitcoin/server/parsers/descriptor.hpp \ ${srcdir}/../../include/bitcoin/server/parsers/electrum_version.hpp \ ${srcdir}/../../include/bitcoin/server/parsers/native_query.hpp \ ${srcdir}/../../include/bitcoin/server/parsers/native_target.hpp \ - ${srcdir}/../../include/bitcoin/server/parsers/parsers.hpp \ - ${srcdir}/../../include/bitcoin/server/parsers/partial_merkle.hpp + ${srcdir}/../../include/bitcoin/server/parsers/parsers.hpp include_bitcoin_server_protocolsdir = \ ${includedir}/bitcoin/server/protocols @@ -251,13 +263,13 @@ test_libbitcoin_server_test_SOURCES = \ ${srcdir}/../../test/mocks/blocks.cpp \ ${srcdir}/../../test/parsers/admin_query.cpp \ ${srcdir}/../../test/parsers/admin_target.cpp \ + ${srcdir}/../../test/parsers/bitcoind_block_stats.cpp \ + ${srcdir}/../../test/parsers/bitcoind_descriptor.cpp \ + ${srcdir}/../../test/parsers/bitcoind_merkle.cpp \ ${srcdir}/../../test/parsers/bitcoind_target.cpp \ - ${srcdir}/../../test/parsers/block_stats.cpp \ - ${srcdir}/../../test/parsers/descriptor.cpp \ ${srcdir}/../../test/parsers/electrum_version.cpp \ ${srcdir}/../../test/parsers/native_query.cpp \ ${srcdir}/../../test/parsers/native_target.cpp \ - ${srcdir}/../../test/parsers/partial_merkle.cpp \ ${srcdir}/../../test/protocols/admin/admin_diagnostics.cpp \ ${srcdir}/../../test/protocols/admin/admin_setup_fixture.cpp \ ${srcdir}/../../test/protocols/bitcoind/bitcoind_json.cpp \ diff --git a/builds/msvc/vs2022/libbitcoin-server-test/libbitcoin-server-test.vcxproj b/builds/msvc/vs2022/libbitcoin-server-test/libbitcoin-server-test.vcxproj index 121a64e6..827b5562 100644 --- a/builds/msvc/vs2022/libbitcoin-server-test/libbitcoin-server-test.vcxproj +++ b/builds/msvc/vs2022/libbitcoin-server-test/libbitcoin-server-test.vcxproj @@ -126,15 +126,15 @@ + + + - - $(IntDir)test_parsers_electrum_version.obj - diff --git a/builds/msvc/vs2022/libbitcoin-server-test/libbitcoin-server-test.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-server-test/libbitcoin-server-test.vcxproj.filters index d8c24b2d..ca0576ff 100644 --- a/builds/msvc/vs2022/libbitcoin-server-test/libbitcoin-server-test.vcxproj.filters +++ b/builds/msvc/vs2022/libbitcoin-server-test/libbitcoin-server-test.vcxproj.filters @@ -63,13 +63,16 @@ src\parsers - + + src\parsers + + src\parsers - + src\parsers - + src\parsers @@ -81,9 +84,6 @@ src\parsers - - src\parsers - src\protocols\admin diff --git a/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj b/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj index db05e8f9..0bb09d0d 100644 --- a/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj +++ b/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj @@ -122,19 +122,22 @@ - + + + + + + + - - - @@ -188,7 +191,11 @@ - + + + + + @@ -210,16 +217,16 @@ + + + - - - diff --git a/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj.filters index 7eab2f40..6c9dae31 100644 --- a/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj.filters +++ b/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj.filters @@ -19,61 +19,76 @@ {73CE0AC2-ECB2-4E8D-0000-000000000003} - + {73CE0AC2-ECB2-4E8D-0000-000000000004} - + {73CE0AC2-ECB2-4E8D-0000-000000000005} - + {73CE0AC2-ECB2-4E8D-0000-000000000006} - + {73CE0AC2-ECB2-4E8D-0000-000000000007} - + {73CE0AC2-ECB2-4E8D-0000-000000000008} - + {73CE0AC2-ECB2-4E8D-0000-000000000009} - + {73CE0AC2-ECB2-4E8D-0000-00000000000A} - + {73CE0AC2-ECB2-4E8D-0000-00000000000B} - + {73CE0AC2-ECB2-4E8D-0000-00000000000C} - + {73CE0AC2-ECB2-4E8D-0000-00000000000D} - + {73CE0AC2-ECB2-4E8D-0000-00000000000E} - + {73CE0AC2-ECB2-4E8D-0000-00000000000F} - + {73CE0AC2-ECB2-4E8D-0000-000000000001} - + {73CE0AC2-ECB2-4E8D-0000-000000000002} - + {73CE0AC2-ECB2-4E8D-0000-000000000003} - + {73CE0AC2-ECB2-4E8D-0000-000000000004} + + {73CE0AC2-ECB2-4E8D-0000-000000000005} + + + {73CE0AC2-ECB2-4E8D-0000-000000000006} + src - - src + + src\error + + + src\error + + + src\error + + + src\error src @@ -84,19 +99,22 @@ src\parsers - + src\parsers - + src\parsers - + src\parsers - + + src\parsers + + src\parsers - + src\parsers @@ -108,9 +126,6 @@ src\parsers - - src\parsers - src\protocols\admin @@ -266,8 +281,20 @@ include\bitcoin\server - - include\bitcoin\server + + include\bitcoin\server\error + + + include\bitcoin\server\error + + + include\bitcoin\server\error + + + include\bitcoin\server\error + + + include\bitcoin\server\error include\bitcoin\server\interfaces @@ -332,19 +359,22 @@ include\bitcoin\server\parsers - + include\bitcoin\server\parsers - + include\bitcoin\server\parsers - + include\bitcoin\server\parsers - + + include\bitcoin\server\parsers + + include\bitcoin\server\parsers - + include\bitcoin\server\parsers @@ -359,9 +389,6 @@ include\bitcoin\server\parsers - - include\bitcoin\server\parsers - include\bitcoin\server\protocols diff --git a/builds/msvc/vs2026/libbitcoin-server-test/libbitcoin-server-test.vcxproj b/builds/msvc/vs2026/libbitcoin-server-test/libbitcoin-server-test.vcxproj index 010a810a..2083eddb 100644 --- a/builds/msvc/vs2026/libbitcoin-server-test/libbitcoin-server-test.vcxproj +++ b/builds/msvc/vs2026/libbitcoin-server-test/libbitcoin-server-test.vcxproj @@ -126,15 +126,15 @@ + + + - - $(IntDir)test_parsers_electrum_version.obj - diff --git a/builds/msvc/vs2026/libbitcoin-server-test/libbitcoin-server-test.vcxproj.filters b/builds/msvc/vs2026/libbitcoin-server-test/libbitcoin-server-test.vcxproj.filters index d8c24b2d..ca0576ff 100644 --- a/builds/msvc/vs2026/libbitcoin-server-test/libbitcoin-server-test.vcxproj.filters +++ b/builds/msvc/vs2026/libbitcoin-server-test/libbitcoin-server-test.vcxproj.filters @@ -63,13 +63,16 @@ src\parsers - + + src\parsers + + src\parsers - + src\parsers - + src\parsers @@ -81,9 +84,6 @@ src\parsers - - src\parsers - src\protocols\admin diff --git a/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj b/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj index c1d26b50..e90a146d 100644 --- a/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj +++ b/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj @@ -122,19 +122,22 @@ - + + + + + + + - - - @@ -188,7 +191,11 @@ - + + + + + @@ -210,16 +217,16 @@ + + + - - - diff --git a/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj.filters b/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj.filters index 7eab2f40..6c9dae31 100644 --- a/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj.filters +++ b/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj.filters @@ -19,61 +19,76 @@ {73CE0AC2-ECB2-4E8D-0000-000000000003} - + {73CE0AC2-ECB2-4E8D-0000-000000000004} - + {73CE0AC2-ECB2-4E8D-0000-000000000005} - + {73CE0AC2-ECB2-4E8D-0000-000000000006} - + {73CE0AC2-ECB2-4E8D-0000-000000000007} - + {73CE0AC2-ECB2-4E8D-0000-000000000008} - + {73CE0AC2-ECB2-4E8D-0000-000000000009} - + {73CE0AC2-ECB2-4E8D-0000-00000000000A} - + {73CE0AC2-ECB2-4E8D-0000-00000000000B} - + {73CE0AC2-ECB2-4E8D-0000-00000000000C} - + {73CE0AC2-ECB2-4E8D-0000-00000000000D} - + {73CE0AC2-ECB2-4E8D-0000-00000000000E} - + {73CE0AC2-ECB2-4E8D-0000-00000000000F} - + {73CE0AC2-ECB2-4E8D-0000-000000000001} - + {73CE0AC2-ECB2-4E8D-0000-000000000002} - + {73CE0AC2-ECB2-4E8D-0000-000000000003} - + {73CE0AC2-ECB2-4E8D-0000-000000000004} + + {73CE0AC2-ECB2-4E8D-0000-000000000005} + + + {73CE0AC2-ECB2-4E8D-0000-000000000006} + src - - src + + src\error + + + src\error + + + src\error + + + src\error src @@ -84,19 +99,22 @@ src\parsers - + src\parsers - + src\parsers - + src\parsers - + + src\parsers + + src\parsers - + src\parsers @@ -108,9 +126,6 @@ src\parsers - - src\parsers - src\protocols\admin @@ -266,8 +281,20 @@ include\bitcoin\server - - include\bitcoin\server + + include\bitcoin\server\error + + + include\bitcoin\server\error + + + include\bitcoin\server\error + + + include\bitcoin\server\error + + + include\bitcoin\server\error include\bitcoin\server\interfaces @@ -332,19 +359,22 @@ include\bitcoin\server\parsers - + include\bitcoin\server\parsers - + include\bitcoin\server\parsers - + include\bitcoin\server\parsers - + + include\bitcoin\server\parsers + + include\bitcoin\server\parsers - + include\bitcoin\server\parsers @@ -359,9 +389,6 @@ include\bitcoin\server\parsers - - include\bitcoin\server\parsers - include\bitcoin\server\protocols diff --git a/include/bitcoin/server.hpp b/include/bitcoin/server.hpp index 2be1321c..187668f3 100644 --- a/include/bitcoin/server.hpp +++ b/include/bitcoin/server.hpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -28,6 +27,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include @@ -48,16 +52,16 @@ #include #include #include +#include +#include +#include #include #include -#include #include -#include #include #include #include #include -#include #include #include #include diff --git a/include/bitcoin/server/define.hpp b/include/bitcoin/server/define.hpp index 26c35454..4ad36222 100644 --- a/include/bitcoin/server/define.hpp +++ b/include/bitcoin/server/define.hpp @@ -20,7 +20,7 @@ #define LIBBITCOIN_SERVER_DEFINE_HPP #include -#include +#include /// Now we use the generic helper definitions above to define BCS_API /// and BCS_INTERNAL. BCS_API is used for the public API symbols. It either DLL diff --git a/include/bitcoin/server/error/bitcoind_error_t.hpp b/include/bitcoin/server/error/bitcoind_error_t.hpp new file mode 100644 index 00000000..d0d4d05b --- /dev/null +++ b/include/bitcoin/server/error/bitcoind_error_t.hpp @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2011-2026 libbitcoin developers + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_SERVER_ERROR_BITCOIND_ERROR_T_HPP +#define LIBBITCOIN_SERVER_ERROR_BITCOIND_ERROR_T_HPP + +#include +#include + +namespace libbitcoin { +namespace server { +namespace error { +namespace bitcoind { + +/// Values are bitcoind wire codes, published as the json-rpc error code. +enum error_t : int32_t +{ + /// general + success = 0, + + /// json-rpc + invalid_request = -32600, + method_not_found = -32601, + invalid_params = -32602, + internal_error = -32603, + parse_error = -32700, + + /// application + misc_error = -1, + forbidden_by_safe_mode = -2, + type_error = -3, + invalid_address_or_key = -5, + out_of_memory = -7, + invalid_parameter = -8, + database_error = -20, + deserialization_error = -22, + verify_error = -25, + verify_rejected = -26, + verify_already_in_utxo_set = -27, + in_warmup = -28, + method_deprecated = -32, + limit_exceeded = -37, + + /// peer-to-peer client + client_not_connected = -9, + client_in_initial_download = -10, + client_node_already_added = -23, + client_node_not_added = -24, + client_node_not_connected = -29, + client_invalid_ip_or_subnet = -30, + client_p2p_disabled = -31, + client_node_capacity_reached = -34, + + /// chain + client_mempool_disabled = -33, + + /// wallet + wallet_error = -4, + wallet_insufficient_funds = -6, + wallet_invalid_label_name = -11, + wallet_keypool_ran_out = -12, + wallet_unlock_needed = -13, + wallet_passphrase_incorrect = -14, + wallet_wrong_enc_state = -15, + wallet_encryption_failed = -16, + wallet_already_unlocked = -17, + wallet_not_found = -18, + wallet_not_specified = -19, + wallet_already_loaded = -35, + wallet_already_exists = -36 +}; + +// No current need for error_code equivalence mapping. +DECLARE_ERROR_T_CODE_CATEGORY(error); + +/// Map a foreign category code to the bitcoind code space, where a store +/// fault is internal and any other failure is reported as the given code. +/// A code of this category passes through unchanged. +BC_API code translate(const code& ec, error_t failure) NOEXCEPT; + +/// The bitcoind (bip22) reject token for a validation code, message otherwise. +BC_API std::string reject(const code& ec) NOEXCEPT; + +} // namespace bitcoind +} // namespace error +} // namespace server +} // namespace libbitcoin + +DECLARE_STD_ERROR_REGISTRATION(bc::server::error::bitcoind::error) + +#endif diff --git a/include/bitcoin/server/error/btcd_error_t.hpp b/include/bitcoin/server/error/btcd_error_t.hpp new file mode 100644 index 00000000..4014490f --- /dev/null +++ b/include/bitcoin/server/error/btcd_error_t.hpp @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2011-2026 libbitcoin developers + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_SERVER_ERROR_BTCD_ERROR_T_HPP +#define LIBBITCOIN_SERVER_ERROR_BTCD_ERROR_T_HPP + +#include +#include + +namespace libbitcoin { +namespace server { +namespace error { +namespace btcd { + +/// Values are btcjson wire codes, published as the json-rpc error code. +/// unimplemented aliases misc_error, as btcd reports both as -1. +enum error_t : int32_t +{ + /// general + success = 0, + + /// json-rpc + invalid_request = -32600, + method_not_found = -32601, + invalid_params = -32602, + internal_error = -32603, + parse_error = -32700, + + /// application + misc_error = -1, + unimplemented = -1, + forbidden_by_safe_mode = -2, + type_error = -3, + wallet_error = -4, + invalid_address_or_key = -5, + wallet_insufficient_funds = -6, + out_of_memory = -7, + invalid_parameter = -8, + client_not_connected = -9, + client_in_initial_download = -10, + wallet_invalid_account_name = -11, + wallet_keypool_ran_out = -12, + wallet_unlock_needed = -13, + wallet_passphrase_incorrect = -14, + wallet_wrong_enc_state = -15, + wallet_encryption_failed = -16, + wallet_already_unlocked = -17, + wallet_not_found = -18, + wallet_not_specified = -19, + database_error = -20, + deserialization_error = -22, + client_node_already_added = -23, + client_node_not_added = -24, + verify_error = -25, + verify_rejected = -26, + verify_already_in_chain = -27, + in_warmup = -28, + client_node_not_connected = -29, + client_invalid_ip_or_subnet = -30, + method_deprecated = -32, + client_mempool_disabled = -33 +}; + +// No current need for error_code equivalence mapping. +DECLARE_ERROR_T_CODE_CATEGORY(error); + +/// Map a foreign category code to the btcd code space, where a store fault +/// is internal and any other failure is reported as the given code. +/// A code of this category passes through unchanged. +BC_API code translate(const code& ec, error_t failure) NOEXCEPT; + +} // namespace btcd +} // namespace error +} // namespace server +} // namespace libbitcoin + +DECLARE_STD_ERROR_REGISTRATION(bc::server::error::btcd::error) + +#endif diff --git a/include/bitcoin/server/error/electrum_error_t.hpp b/include/bitcoin/server/error/electrum_error_t.hpp new file mode 100644 index 00000000..33b53337 --- /dev/null +++ b/include/bitcoin/server/error/electrum_error_t.hpp @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2011-2026 libbitcoin developers + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_SERVER_ERROR_ELECTRUM_ERROR_T_HPP +#define LIBBITCOIN_SERVER_ERROR_ELECTRUM_ERROR_T_HPP + +#include +#include + +namespace libbitcoin { +namespace server { +namespace error { +namespace electrum { + +/// Values are electrumx/aiorpcx wire codes, published as the json-rpc error +/// code. The electrum client disconnects on method_not_found, internal_error, +/// excessive_resource_usage and server_busy. +enum error_t : int32_t +{ + /// general + success = 0, + + /// application (electrumx) + bad_request = 1, + daemon_error = 2, + excessive_history = 10'001, + + /// json-rpc (aiorpcx) + invalid_request = -32600, + method_not_found = -32601, + invalid_args = -32602, + internal_error = -32603, + parse_error = -32700, + + /// resource (aiorpcx) + unavailable = -100, + excessive_resource_usage = -101, + server_busy = -102 +}; + +// No current need for error_code equivalence mapping. +DECLARE_ERROR_T_CODE_CATEGORY(error); + +/// Map a foreign category code to the electrum code space, where a depth +/// limit is excessive history, any other store fault is a daemon error, and +/// any other failure is reported as the given code. A code of this category +/// passes through unchanged. +BC_API code translate(const code& ec, error_t failure) NOEXCEPT; + +} // namespace electrum +} // namespace error +} // namespace server +} // namespace libbitcoin + +DECLARE_STD_ERROR_REGISTRATION(bc::server::error::electrum::error) + +#endif diff --git a/include/bitcoin/server/error/error.hpp b/include/bitcoin/server/error/error.hpp new file mode 100644 index 00000000..614d124d --- /dev/null +++ b/include/bitcoin/server/error/error.hpp @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2011-2026 libbitcoin developers + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_SERVER_ERROR_ERROR_HPP +#define LIBBITCOIN_SERVER_ERROR_ERROR_HPP + +#include +#include +#include +#include + +#endif diff --git a/include/bitcoin/server/error.hpp b/include/bitcoin/server/error/error_t.hpp similarity index 94% rename from include/bitcoin/server/error.hpp rename to include/bitcoin/server/error/error_t.hpp index 3160cf4c..5d5ba7cf 100644 --- a/include/bitcoin/server/error.hpp +++ b/include/bitcoin/server/error/error_t.hpp @@ -16,8 +16,8 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#ifndef LIBBITCOIN_SERVER_ERROR_HPP -#define LIBBITCOIN_SERVER_ERROR_HPP +#ifndef LIBBITCOIN_SERVER_ERROR_ERROR_T_HPP +#define LIBBITCOIN_SERVER_ERROR_ERROR_T_HPP #include #include @@ -68,8 +68,7 @@ enum error_t : uint8_t target_overflow, maximum_depth, wrong_version, - server_error, - method_unauthorized + server_error }; // No current need for error_code equivalence mapping. diff --git a/include/bitcoin/server/parsers/block_stats.hpp b/include/bitcoin/server/parsers/bitcoind_block_stats.hpp similarity index 90% rename from include/bitcoin/server/parsers/block_stats.hpp rename to include/bitcoin/server/parsers/bitcoind_block_stats.hpp index 4137540a..4cd542c1 100644 --- a/include/bitcoin/server/parsers/block_stats.hpp +++ b/include/bitcoin/server/parsers/bitcoind_block_stats.hpp @@ -16,8 +16,8 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#ifndef LIBBITCOIN_SERVER_PARSERS_BLOCK_STATS_HPP -#define LIBBITCOIN_SERVER_PARSERS_BLOCK_STATS_HPP +#ifndef LIBBITCOIN_SERVER_PARSERS_BITCOIND_BLOCK_STATS_HPP +#define LIBBITCOIN_SERVER_PARSERS_BITCOIND_BLOCK_STATS_HPP #include diff --git a/include/bitcoin/server/parsers/descriptor.hpp b/include/bitcoin/server/parsers/bitcoind_descriptor.hpp similarity index 83% rename from include/bitcoin/server/parsers/descriptor.hpp rename to include/bitcoin/server/parsers/bitcoind_descriptor.hpp index 5bee7dc9..0b819c07 100644 --- a/include/bitcoin/server/parsers/descriptor.hpp +++ b/include/bitcoin/server/parsers/bitcoind_descriptor.hpp @@ -16,8 +16,8 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#ifndef LIBBITCOIN_SERVER_PARSERS_DESCRIPTOR_HPP -#define LIBBITCOIN_SERVER_PARSERS_DESCRIPTOR_HPP +#ifndef LIBBITCOIN_SERVER_PARSERS_BITCOIND_DESCRIPTOR_HPP +#define LIBBITCOIN_SERVER_PARSERS_BITCOIND_DESCRIPTOR_HPP #include @@ -25,8 +25,7 @@ namespace libbitcoin { namespace server { /// The bip380 output descriptor checksum, empty on invalid characters. -BCS_API std::string descriptor_checksum( - const std::string& descriptor) NOEXCEPT; +BCS_API std::string descriptor_checksum(const std::string& descriptor) NOEXCEPT; } // namespace server } // namespace libbitcoin diff --git a/include/bitcoin/server/parsers/partial_merkle.hpp b/include/bitcoin/server/parsers/bitcoind_merkle.hpp similarity index 94% rename from include/bitcoin/server/parsers/partial_merkle.hpp rename to include/bitcoin/server/parsers/bitcoind_merkle.hpp index 0495bad1..a5281c2b 100644 --- a/include/bitcoin/server/parsers/partial_merkle.hpp +++ b/include/bitcoin/server/parsers/bitcoind_merkle.hpp @@ -16,8 +16,8 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#ifndef LIBBITCOIN_SERVER_PARSERS_PARTIAL_MERKLE_HPP -#define LIBBITCOIN_SERVER_PARSERS_PARTIAL_MERKLE_HPP +#ifndef LIBBITCOIN_SERVER_PARSERS_BITCOIND_MERKLE_HPP +#define LIBBITCOIN_SERVER_PARSERS_BITCOIND_MERKLE_HPP #include diff --git a/include/bitcoin/server/parsers/parsers.hpp b/include/bitcoin/server/parsers/parsers.hpp index 526a1655..917c93ac 100644 --- a/include/bitcoin/server/parsers/parsers.hpp +++ b/include/bitcoin/server/parsers/parsers.hpp @@ -21,14 +21,14 @@ #include #include +#include +#include +#include #include #include -#include #include -#include #include #include #include -#include #endif diff --git a/src/error/bitcoind_error_t.cpp b/src/error/bitcoind_error_t.cpp new file mode 100644 index 00000000..d4b74b45 --- /dev/null +++ b/src/error/bitcoind_error_t.cpp @@ -0,0 +1,187 @@ +/** + * Copyright (c) 2011-2026 libbitcoin developers + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include + +#include + +namespace libbitcoin { +namespace server { +namespace error { +namespace bitcoind { + +DEFINE_ERROR_T_MESSAGE_MAP(error) +{ + // general + { success, "success" }, + + // json-rpc + { invalid_request, "invalid_request" }, + { method_not_found, "method_not_found" }, + { invalid_params, "invalid_params" }, + { internal_error, "internal_error" }, + { parse_error, "parse_error" }, + + // application + { misc_error, "misc_error" }, + { forbidden_by_safe_mode, "forbidden_by_safe_mode" }, + { type_error, "type_error" }, + { invalid_address_or_key, "invalid_address_or_key" }, + { out_of_memory, "out_of_memory" }, + { invalid_parameter, "invalid_parameter" }, + { database_error, "database_error" }, + { deserialization_error, "deserialization_error" }, + { verify_error, "verify_error" }, + { verify_rejected, "verify_rejected" }, + { verify_already_in_utxo_set, "verify_already_in_utxo_set" }, + { in_warmup, "in_warmup" }, + { method_deprecated, "method_deprecated" }, + { limit_exceeded, "limit_exceeded" }, + + // peer-to-peer client + { client_not_connected, "client_not_connected" }, + { client_in_initial_download, "client_in_initial_download" }, + { client_node_already_added, "client_node_already_added" }, + { client_node_not_added, "client_node_not_added" }, + { client_node_not_connected, "client_node_not_connected" }, + { client_invalid_ip_or_subnet, "client_invalid_ip_or_subnet" }, + { client_p2p_disabled, "client_p2p_disabled" }, + { client_node_capacity_reached, "client_node_capacity_reached" }, + + // chain + { client_mempool_disabled, "client_mempool_disabled" }, + + // wallet + { wallet_error, "wallet_error" }, + { wallet_insufficient_funds, "wallet_insufficient_funds" }, + { wallet_invalid_label_name, "wallet_invalid_label_name" }, + { wallet_keypool_ran_out, "wallet_keypool_ran_out" }, + { wallet_unlock_needed, "wallet_unlock_needed" }, + { wallet_passphrase_incorrect, "wallet_passphrase_incorrect" }, + { wallet_wrong_enc_state, "wallet_wrong_enc_state" }, + { wallet_encryption_failed, "wallet_encryption_failed" }, + { wallet_already_unlocked, "wallet_already_unlocked" }, + { wallet_not_found, "wallet_not_found" }, + { wallet_not_specified, "wallet_not_specified" }, + { wallet_already_loaded, "wallet_already_loaded" }, + { wallet_already_exists, "wallet_already_exists" } +}; + +DEFINE_ERROR_T_CATEGORY(error, "bitcoind", "bitcoind code") + +code translate(const code& ec, error_t failure) NOEXCEPT +{ + if (!ec) + return success; + + if (error_category::contains(ec)) + return ec; + + if (database::error::error_category::contains(ec)) + return internal_error; + + return failure; +} + +// bitcoind reject tokens by transaction code (mempool vocabulary). +static const message_map +transaction_rejects +{ + { system::error::empty_transaction, "bad-txns-vin-empty" }, + { system::error::previous_output_null, "bad-txns-prevout-null" }, + { system::error::spend_overflow, "bad-txns-txouttotal-toolarge" }, + { system::error::invalid_coinbase_script_size, "bad-cb-length" }, + { system::error::coinbase_transaction, "coinbase" }, + { system::error::transaction_internal_double_spend, "bad-txns-inputs-duplicate" }, + { system::error::transaction_size_limit, "bad-txns-oversize" }, + { system::error::transaction_legacy_sigop_limit, "bad-txns-too-many-sigops" }, + { system::error::unspent_duplicate, "bad-txns-BIP30" }, + { system::error::missing_previous_output, "bad-txns-inputs-missingorspent" }, + { system::error::coinbase_maturity, "bad-txns-premature-spend-of-coinbase" }, + { system::error::spend_exceeds_value, "bad-txns-in-belowout" }, + { system::error::transaction_sigop_limit, "bad-txns-too-many-sigops" }, + { system::error::absolute_time_locked, "non-final" }, + { system::error::relative_time_locked, "non-BIP68-final" }, + { system::error::transaction_weight_limit, "tx-size" }, + { system::error::confirmed_double_spend, "bad-txns-inputs-missingorspent" } +}; + +// bitcoind reject tokens by block code (submission vocabulary). +static const message_map +block_rejects +{ + { system::error::invalid_proof_of_work, "high-hash" }, + { system::error::futuristic_timestamp, "time-too-new" }, + { system::error::insufficient_block_version, "bad-version" }, + { system::error::anachronistic_timestamp, "time-too-old" }, + { system::error::incorrect_proof_of_work, "bad-diffbits" }, + { system::error::early_timestamp, "time-too-old" }, + { system::error::orphan_block, "prev-blk-not-found" }, + { system::error::block_size_limit, "bad-blk-length" }, + { system::error::empty_block, "bad-blk-length" }, + { system::error::first_not_coinbase, "bad-cb-missing" }, + { system::error::extra_coinbases, "bad-cb-multiple" }, + { system::error::internal_duplicate, "bad-txns-duplicate" }, + { system::error::block_internal_double_spend, "bad-txns-inputs-missingorspent" }, + { system::error::forward_reference, "bad-txns-inputs-missingorspent" }, + { system::error::invalid_transaction_commitment, "bad-txnmrklroot" }, + { system::error::block_legacy_sigop_limit, "bad-blk-sigops" }, + { system::error::block_non_final, "bad-txns-nonfinal" }, + { system::error::coinbase_height_mismatch, "bad-cb-height" }, + { system::error::coinbase_value_limit, "bad-cb-amount" }, + { system::error::block_sigop_limit, "bad-blk-sigops" }, + { system::error::invalid_witness_commitment, "bad-witness-merkle-match" }, + { system::error::block_weight_limit, "bad-blk-weight" }, + { system::error::invalid_signature, "mandatory-script-verify-flag-failed" }, + { system::error::unspent_coinbase_collision, "bad-txns-BIP30" } +}; + +std::string reject(const code& ec) NOEXCEPT +{ + // The organizer reports an unassociated block as a node orphan. + if ((ec == node::error::orphan_block) || (ec == node::error::orphan_header)) + return "prev-blk-not-found"; + + if ((ec == node::error::duplicate_block) || + (ec == node::error::duplicate_header)) + return "duplicate"; + + using namespace system::error; + if (transaction_error_category::contains(ec)) + { + const auto token = transaction_rejects.find( + static_cast(ec.value())); + if (token != transaction_rejects.end()) + return token->second; + } + + if (block_error_category::contains(ec)) + { + const auto token = block_rejects.find( + static_cast(ec.value())); + if (token != block_rejects.end()) + return token->second; + } + + return ec.message(); +} + +} // namespace bitcoind +} // namespace error +} // namespace server +} // namespace libbitcoin diff --git a/src/error/btcd_error_t.cpp b/src/error/btcd_error_t.cpp new file mode 100644 index 00000000..a7dba399 --- /dev/null +++ b/src/error/btcd_error_t.cpp @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2011-2026 libbitcoin developers + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include + +#include + +namespace libbitcoin { +namespace server { +namespace error { +namespace btcd { + +DEFINE_ERROR_T_MESSAGE_MAP(error) +{ + // general + { success, "success" }, + + // json-rpc + { invalid_request, "invalid_request" }, + { method_not_found, "method_not_found" }, + { invalid_params, "invalid_params" }, + { internal_error, "internal_error" }, + { parse_error, "parse_error" }, + + // application + { misc_error, "misc_error" }, + { forbidden_by_safe_mode, "forbidden_by_safe_mode" }, + { type_error, "type_error" }, + { wallet_error, "wallet_error" }, + { invalid_address_or_key, "invalid_address_or_key" }, + { wallet_insufficient_funds, "wallet_insufficient_funds" }, + { out_of_memory, "out_of_memory" }, + { invalid_parameter, "invalid_parameter" }, + { client_not_connected, "client_not_connected" }, + { client_in_initial_download, "client_in_initial_download" }, + { wallet_invalid_account_name, "wallet_invalid_account_name" }, + { wallet_keypool_ran_out, "wallet_keypool_ran_out" }, + { wallet_unlock_needed, "wallet_unlock_needed" }, + { wallet_passphrase_incorrect, "wallet_passphrase_incorrect" }, + { wallet_wrong_enc_state, "wallet_wrong_enc_state" }, + { wallet_encryption_failed, "wallet_encryption_failed" }, + { wallet_already_unlocked, "wallet_already_unlocked" }, + { wallet_not_found, "wallet_not_found" }, + { wallet_not_specified, "wallet_not_specified" }, + { database_error, "database_error" }, + { deserialization_error, "deserialization_error" }, + { client_node_already_added, "client_node_already_added" }, + { client_node_not_added, "client_node_not_added" }, + { verify_error, "verify_error" }, + { verify_rejected, "verify_rejected" }, + { verify_already_in_chain, "verify_already_in_chain" }, + { in_warmup, "in_warmup" }, + { client_node_not_connected, "client_node_not_connected" }, + { client_invalid_ip_or_subnet, "client_invalid_ip_or_subnet" }, + { method_deprecated, "method_deprecated" }, + { client_mempool_disabled, "client_mempool_disabled" } +}; + +DEFINE_ERROR_T_CATEGORY(error, "btcd", "btcd code") + +code translate(const code& ec, error_t failure) NOEXCEPT +{ + if (!ec) + return success; + + if (error_category::contains(ec)) + return ec; + + if (database::error::error_category::contains(ec)) + return internal_error; + + return failure; +} + +} // namespace btcd +} // namespace error +} // namespace server +} // namespace libbitcoin diff --git a/src/error/electrum_error_t.cpp b/src/error/electrum_error_t.cpp new file mode 100644 index 00000000..50c83321 --- /dev/null +++ b/src/error/electrum_error_t.cpp @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2011-2026 libbitcoin developers + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include + +#include + +namespace libbitcoin { +namespace server { +namespace error { +namespace electrum { + +DEFINE_ERROR_T_MESSAGE_MAP(error) +{ + // general + { success, "success" }, + + // application + { bad_request, "bad_request" }, + { daemon_error, "daemon_error" }, + { excessive_history, "excessive_history" }, + + // json-rpc + { invalid_request, "invalid_request" }, + { method_not_found, "method_not_found" }, + { invalid_args, "invalid_args" }, + { internal_error, "internal_error" }, + { parse_error, "parse_error" }, + + // resource + { unavailable, "unavailable" }, + { excessive_resource_usage, "excessive_resource_usage" }, + { server_busy, "server_busy" } +}; + +DEFINE_ERROR_T_CATEGORY(error, "electrum", "electrum code") + +code translate(const code& ec, error_t failure) NOEXCEPT +{ + if (!ec) + return success; + + if (error_category::contains(ec)) + return ec; + + if (ec == database::error::depth_limited) + return excessive_history; + + if (database::error::error_category::contains(ec)) + return daemon_error; + + return failure; +} + +} // namespace electrum +} // namespace error +} // namespace server +} // namespace libbitcoin diff --git a/src/error.cpp b/src/error/error_t.cpp similarity index 94% rename from src/error.cpp rename to src/error/error_t.cpp index e38084cb..af3fabbe 100644 --- a/src/error.cpp +++ b/src/error/error_t.cpp @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#include +#include #include @@ -58,8 +58,7 @@ DEFINE_ERROR_T_MESSAGE_MAP(error) { target_overflow, "target_overflow" }, { maximum_depth, "maximum_depth" }, { wrong_version, "wrong_version" }, - { server_error, "server_error" }, - { method_unauthorized, "method_unauthorized" } + { server_error, "server_error" } }; DEFINE_ERROR_T_CATEGORY(error, "server", "server code") diff --git a/src/parsers/block_stats.cpp b/src/parsers/bitcoind_block_stats.cpp similarity index 99% rename from src/parsers/block_stats.cpp rename to src/parsers/bitcoind_block_stats.cpp index 1a5b5504..cc09df34 100644 --- a/src/parsers/block_stats.cpp +++ b/src/parsers/bitcoind_block_stats.cpp @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#include +#include #include #include diff --git a/src/parsers/descriptor.cpp b/src/parsers/bitcoind_descriptor.cpp similarity index 98% rename from src/parsers/descriptor.cpp rename to src/parsers/bitcoind_descriptor.cpp index 918f66d5..23b70ccb 100644 --- a/src/parsers/descriptor.cpp +++ b/src/parsers/bitcoind_descriptor.cpp @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#include +#include #include diff --git a/src/parsers/partial_merkle.cpp b/src/parsers/bitcoind_merkle.cpp similarity index 99% rename from src/parsers/partial_merkle.cpp rename to src/parsers/bitcoind_merkle.cpp index 5152dec5..cf98a45a 100644 --- a/src/parsers/partial_merkle.cpp +++ b/src/parsers/bitcoind_merkle.cpp @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#include +#include #include diff --git a/src/protocols/bitcoind/protocol_bitcoind.cpp b/src/protocols/bitcoind/protocol_bitcoind.cpp index 89f97616..2efb605d 100644 --- a/src/protocols/bitcoind/protocol_bitcoind.cpp +++ b/src/protocols/bitcoind/protocol_bitcoind.cpp @@ -132,12 +132,12 @@ void protocol_bitcoind::handle_receive_post(const code& ec, // The credential may be restricted to a subset of interface methods. if (!permitted(message.method)) { - send_error(error::method_unauthorized); + send_forbidden(*post); return; } // No subgroup interface defines the method. - send_error(network::error::unexpected_method); + send_error(error::bitcoind::method_not_found); } // The websocket transport of the interface: subgroup protocols handle claimed @@ -174,12 +174,12 @@ void protocol_bitcoind::dispatch_websocket( // The credential may be restricted to a subset of interface methods. if (!permitted(message.method)) { - send_error(error::method_unauthorized); + stop(network::error::unauthorized); return; } // No subgroup interface defines the method. - send_error(network::error::unexpected_method); + send_error(error::bitcoind::method_not_found); } // Help. diff --git a/src/protocols/bitcoind/protocol_bitcoind_blockchain.cpp b/src/protocols/bitcoind/protocol_bitcoind_blockchain.cpp index b7831b1a..8179518c 100644 --- a/src/protocols/bitcoind/protocol_bitcoind_blockchain.cpp +++ b/src/protocols/bitcoind/protocol_bitcoind_blockchain.cpp @@ -154,24 +154,28 @@ bool protocol_bitcoind_blockchain::handle_get_block(const code& ec, hash_digest hash{}; if (!decode_hash(hash, blockhash)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } - size_t level{}; - if (!to_integer(level, verbosity) || level > block_verbosity::prevouts) + int64_t requested{}; + if (!to_integer(requested, verbosity)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::misc_error); return true; } + // bitcoind clamps out of range verbosity. + const auto level = limit(requested, block_verbosity::prevouts); + constexpr auto witness = true; const auto& query = archive(); const auto link = query.to_header(hash); const auto block = query.get_block(link, witness); if (!block) { - send_error(error::not_found, blockhash, blockhash.size()); + send_error(error::bitcoind::invalid_address_or_key, blockhash, + blockhash.size()); return true; } @@ -219,7 +223,7 @@ bool protocol_bitcoind_blockchain::handle_get_block_chain_info(const code& ec, if (!chain_info(out, archive(), node_settings().limited_blocks, is_current_chain(true))) { - send_error(database::error::integrity); + send_error(error::bitcoind::internal_error); return true; } @@ -247,21 +251,21 @@ bool protocol_bitcoind_blockchain::handle_get_block_filter(const code& ec, if (filtertype != basic_filter) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_address_or_key); return true; } hash_digest hash{}; if (!decode_hash(hash, blockhash)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } const auto& query = archive(); if (!query.filter_enabled()) { - send_error(error::not_implemented); + send_error(error::bitcoind::misc_error); return true; } @@ -271,7 +275,8 @@ bool protocol_bitcoind_blockchain::handle_get_block_filter(const code& ec, if (!query.get_filter_body(filter, link) || !query.get_filter_head(filter_header, link)) { - send_error(error::not_found, blockhash, blockhash.size()); + send_error(error::bitcoind::invalid_address_or_key, blockhash, + blockhash.size()); return true; } @@ -292,7 +297,7 @@ bool protocol_bitcoind_blockchain::handle_get_block_hash(const code& ec, size_t block_height{}; if (!to_integer(block_height, height)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -300,7 +305,7 @@ bool protocol_bitcoind_blockchain::handle_get_block_hash(const code& ec, const auto link = query.to_confirmed(block_height); if (link.is_terminal()) { - send_error(error::not_found); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -318,7 +323,7 @@ bool protocol_bitcoind_blockchain::handle_get_block_header(const code& ec, hash_digest hash{}; if (!decode_hash(hash, blockhash)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -327,7 +332,8 @@ bool protocol_bitcoind_blockchain::handle_get_block_header(const code& ec, const auto header = query.get_header(link); if (!header) { - send_error(error::not_found, blockhash, blockhash.size()); + send_error(error::bitcoind::invalid_address_or_key, blockhash, + blockhash.size()); return true; } @@ -358,7 +364,7 @@ bool protocol_bitcoind_blockchain::handle_get_block_stats(const code& ec, hash_digest hash{}; if (!decode_hash(hash, std::get(hash_or_height.value()))) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -369,7 +375,7 @@ bool protocol_bitcoind_blockchain::handle_get_block_stats(const code& ec, size_t height{}; if (!to_integer(height, std::get(hash_or_height.value()))) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -377,14 +383,14 @@ bool protocol_bitcoind_blockchain::handle_get_block_stats(const code& ec, } else { - send_error(error::invalid_argument); + send_error(error::bitcoind::type_error); return true; } size_t height{}; if (!query.get_height(height, link) || query.to_confirmed(height) != link) { - send_error(error::not_found); + send_error(error::bitcoind::invalid_address_or_key); return true; } @@ -392,7 +398,7 @@ bool protocol_bitcoind_blockchain::handle_get_block_stats(const code& ec, const auto block = query.get_block(link, true); if (!block || !query.populate_without_metadata(*block)) { - send_error(database::error::integrity); + send_error(error::bitcoind::misc_error); return true; } @@ -416,7 +422,7 @@ bool protocol_bitcoind_blockchain::handle_get_block_stats(const code& ec, { if (!std::holds_alternative(stat.value())) { - send_error(error::invalid_argument); + send_error(error::bitcoind::type_error); return true; } @@ -424,7 +430,7 @@ bool protocol_bitcoind_blockchain::handle_get_block_stats(const code& ec, const auto it = result.find(name); if (it == result.end()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -453,7 +459,7 @@ bool protocol_bitcoind_blockchain::handle_get_chain_tx_stats(const code& ec, hash_digest hash{}; if (!decode_hash(hash, blockhash)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -463,7 +469,8 @@ bool protocol_bitcoind_blockchain::handle_get_chain_tx_stats(const code& ec, size_t height{}; if (!query.get_height(height, link) || query.to_confirmed(height) != link) { - send_error(error::not_found, blockhash, blockhash.size()); + send_error(error::bitcoind::invalid_address_or_key, blockhash, + blockhash.size()); return true; } @@ -480,7 +487,7 @@ bool protocol_bitcoind_blockchain::handle_get_chain_tx_stats(const code& ec, if (!to_integer(window, nblocks) || (is_nonzero(window) && window >= height)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } } @@ -488,7 +495,7 @@ bool protocol_bitcoind_blockchain::handle_get_chain_tx_stats(const code& ec, const auto header = query.get_header(link); if (!header) { - send_error(database::error::integrity); + send_error(error::bitcoind::internal_error); return true; } @@ -534,7 +541,7 @@ bool protocol_bitcoind_blockchain::handle_get_tx_out(const code& ec, hash_digest hash{}; if (!decode_hash(hash, txid) || !to_integer(index, n)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -561,7 +568,7 @@ bool protocol_bitcoind_blockchain::handle_get_tx_out(const code& ec, const auto tx_link = query.to_tx(hash); if (tx_link.is_terminal()) { - send_error(error::server_error); + send_error(error::bitcoind::internal_error); return true; } @@ -626,7 +633,7 @@ bool protocol_bitcoind_blockchain::handle_get_tx_out_set_info(const code& ec, type = set_hash::none; else { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -637,7 +644,7 @@ bool protocol_bitcoind_blockchain::handle_get_tx_out_set_info(const code& ec, // bitcoind restricts specific block queries (coinstatsindex bounds). if ((type == set_hash::serialized) || !use_index) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -647,7 +654,7 @@ bool protocol_bitcoind_blockchain::handle_get_tx_out_set_info(const code& ec, hash_digest hash{}; if (!decode_hash(hash, std::get(hash_or_height.value()))) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -658,7 +665,7 @@ bool protocol_bitcoind_blockchain::handle_get_tx_out_set_info(const code& ec, if (!to_integer(height, std::get(hash_or_height.value()))) { - send_error(error::invalid_argument); + send_error(error::bitcoind::misc_error); return true; } @@ -666,14 +673,14 @@ bool protocol_bitcoind_blockchain::handle_get_tx_out_set_info(const code& ec, } else { - send_error(error::invalid_argument); + send_error(error::bitcoind::type_error); return true; } if (!query.get_height(height, link) || query.to_confirmed(height) != link) { - send_error(error::not_found); + send_error(error::bitcoind::invalid_address_or_key); return true; } } @@ -696,7 +703,7 @@ void protocol_bitcoind_blockchain::do_get_tx_out_set_info(set_hash type, database::header_links branch{}; if (!query.get_ancestry(branch, link, height)) { - POST(complete_scan, database::error::integrity, std::move(result), + POST(complete_scan, error::bitcoind::internal_error, std::move(result), zero); return; } @@ -740,7 +747,7 @@ void protocol_bitcoind_blockchain::do_get_tx_out_set_info(set_hash type, if (ec) { - POST(complete_scan, ec, + POST(complete_scan, error::bitcoind::internal_error, std::move(result), zero); return; } @@ -748,7 +755,8 @@ void protocol_bitcoind_blockchain::do_get_tx_out_set_info(set_hash type, // A reorganization across the pinned top voids the scan. if (!query.is_confirmed_block(link)) { - POST(complete_scan, error::server_error, std::move(result), zero); + POST(complete_scan, error::bitcoind::internal_error, std::move(result), + zero); return; } @@ -782,7 +790,7 @@ bool protocol_bitcoind_blockchain::handle_prune_block_chain(const code& ec, rpc_interface::prune_block_chain, double) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::misc_error); return true; } @@ -790,7 +798,7 @@ bool protocol_bitcoind_blockchain::handle_save_mempool(const code& ec, rpc_interface::save_mempool) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::client_mempool_disabled); return true; } @@ -819,7 +827,7 @@ bool protocol_bitcoind_blockchain::handle_scan_tx_out_set(const code& ec, if (action != "start") { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -839,8 +847,8 @@ void protocol_bitcoind_blockchain::do_scan_tx_out_set( { if (!expand_scan_object(scripts, item)) { - POST(complete_scan, error::invalid_argument, std::move(result), - zero); + POST(complete_scan, error::bitcoind::invalid_address_or_key, + std::move(result), zero); return; } } @@ -930,7 +938,7 @@ void protocol_bitcoind_blockchain::do_scan_tx_out_set( if (ec) { - POST(complete_scan, ec, + POST(complete_scan, error::bitcoind::internal_error, std::move(result), zero); return; } @@ -938,7 +946,8 @@ void protocol_bitcoind_blockchain::do_scan_tx_out_set( // A reorganization across the pinned top voids the scan. if (!query.is_confirmed_block(link)) { - POST(complete_scan, error::server_error, std::move(result), zero); + POST(complete_scan, error::bitcoind::internal_error, + std::move(result), zero); return; } @@ -1021,7 +1030,7 @@ bool protocol_bitcoind_blockchain::handle_dump_tx_out_set(const code& ec, rpc_interface::dump_tx_out_set) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -1029,7 +1038,7 @@ bool protocol_bitcoind_blockchain::handle_load_tx_out_set(const code& ec, rpc_interface::load_tx_out_set) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -1047,7 +1056,7 @@ bool protocol_bitcoind_blockchain::handle_get_tx_out_proof(const code& ec, if (txids.empty()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -1059,7 +1068,7 @@ bool protocol_bitcoind_blockchain::handle_get_tx_out_proof(const code& ec, !decode_hash(hash, std::get(item.value())) || !targets.insert(hash).second) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } } @@ -1073,7 +1082,7 @@ bool protocol_bitcoind_blockchain::handle_get_tx_out_proof(const code& ec, hash_digest hash{}; if (!decode_hash(hash, blockhash)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -1082,7 +1091,7 @@ bool protocol_bitcoind_blockchain::handle_get_tx_out_proof(const code& ec, if (!query.is_associated(link)) { - send_error(error::not_found); + send_error(error::bitcoind::invalid_address_or_key); return true; } @@ -1090,7 +1099,7 @@ bool protocol_bitcoind_blockchain::handle_get_tx_out_proof(const code& ec, const auto keys = query.get_tx_keys(link); if (keys.empty()) { - send_error(database::error::integrity); + send_error(error::bitcoind::internal_error); return true; } @@ -1107,14 +1116,14 @@ bool protocol_bitcoind_blockchain::handle_get_tx_out_proof(const code& ec, if (to_unsigned(std::count(match.begin(), match.end(), true)) != targets.size()) { - send_error(error::not_found); + send_error(error::bitcoind::invalid_address_or_key); return true; } const auto header = query.get_header(link); if (!header) { - send_error(database::error::integrity); + send_error(error::bitcoind::internal_error); return true; } @@ -1142,7 +1151,7 @@ bool protocol_bitcoind_blockchain::handle_verify_tx_out_proof(const code& ec, data_chunk data{}; if (!decode_base16(data, proof)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -1150,7 +1159,7 @@ bool protocol_bitcoind_blockchain::handle_verify_tx_out_proof(const code& ec, const auto merkle = merkle_block::deserialize(version, data); if (!merkle) { - send_error(error::invalid_argument); + send_error(error::bitcoind::misc_error); return true; } @@ -1174,7 +1183,7 @@ bool protocol_bitcoind_blockchain::handle_verify_tx_out_proof(const code& ec, if (!query.is_confirmed_block(link) || query.get_tx_count(link) != merkle->transactions) { - send_error(error::not_found); + send_error(error::bitcoind::invalid_address_or_key); return true; } @@ -1190,7 +1199,7 @@ bool protocol_bitcoind_blockchain::handle_get_block_from_peer(const code& ec, rpc_interface::get_block_from_peer) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -1207,7 +1216,7 @@ bool protocol_bitcoind_blockchain::handle_get_chain_states(const code& ec, auto entry = chain_states_entry(query, link, 1.0, true); if (entry.empty()) { - send_error(database::error::integrity); + send_error(error::bitcoind::internal_error); return true; } @@ -1228,7 +1237,7 @@ bool protocol_bitcoind_blockchain::handle_get_chain_states(const code& ec, entry = chain_states_entry(query, link, validated, false); if (entry.empty()) { - send_error(database::error::integrity); + send_error(error::bitcoind::internal_error); return true; } @@ -1335,7 +1344,7 @@ bool protocol_bitcoind_blockchain::handle_get_deployment_info(const code& ec, hash_digest hash{}; if (!decode_hash(hash, blockhash)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -1345,7 +1354,8 @@ bool protocol_bitcoind_blockchain::handle_get_deployment_info(const code& ec, size_t height{}; if (!query.get_height(height, link)) { - send_error(error::not_found, blockhash, blockhash.size()); + send_error(error::bitcoind::invalid_address_or_key, blockhash, + blockhash.size()); return true; } @@ -1385,7 +1395,7 @@ bool protocol_bitcoind_blockchain::handle_get_descriptor_activity( { if (!expand_scan_object(derived, item)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_address_or_key); return true; } } @@ -1402,7 +1412,7 @@ bool protocol_bitcoind_blockchain::handle_get_descriptor_activity( if (!std::holds_alternative(item.value()) || !decode_hash(hash, std::get(item.value()))) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -1412,7 +1422,7 @@ bool protocol_bitcoind_blockchain::handle_get_descriptor_activity( size_t height{}; if (!block || !query.get_height(height, link)) { - send_error(error::not_found); + send_error(error::bitcoind::invalid_address_or_key); return true; } @@ -1494,7 +1504,7 @@ bool protocol_bitcoind_blockchain::handle_get_difficulty(const code& ec, const auto header = query.get_header(query.to_confirmed(top)); if (!header) { - send_error(database::error::integrity); + send_error(error::bitcoind::internal_error); return true; } @@ -1506,7 +1516,7 @@ bool protocol_bitcoind_blockchain::handle_precious_block(const code& ec, rpc_interface::precious_block) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -1598,17 +1608,28 @@ bool protocol_bitcoind_blockchain::handle_scan_blocks(const code& ec, if (stopped(ec)) return false; - if (action != "start" || filtertype != basic_filter || - scanobjects.empty()) + if (action != "start") + { + send_error(error::bitcoind::invalid_parameter); + return true; + } + + if (filtertype != basic_filter) + { + send_error(error::bitcoind::invalid_address_or_key); + return true; + } + + if (scanobjects.empty()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::misc_error); return true; } const auto& query = archive(); if (!query.filter_enabled()) { - send_error(error::not_implemented); + send_error(error::bitcoind::misc_error); return true; } @@ -1618,14 +1639,14 @@ bool protocol_bitcoind_blockchain::handle_scan_blocks(const code& ec, if (!to_integer(from, start_height) || (stop_height >= 0 && !to_integer(to, stop_height))) { - send_error(error::invalid_argument); + send_error(error::bitcoind::misc_error); return true; } to = std::min(to, top); if (from > to) { - send_error(error::invalid_argument); + send_error(error::bitcoind::misc_error); return true; } @@ -1634,7 +1655,7 @@ bool protocol_bitcoind_blockchain::handle_scan_blocks(const code& ec, { if (!expand_scan_object(scripts, item)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_address_or_key); return true; } } @@ -1647,7 +1668,7 @@ bool protocol_bitcoind_blockchain::handle_scan_blocks(const code& ec, neutrino::block_filter filter{ hash, {} }; if (!query.get_filter_body(filter.filter, link)) { - send_error(database::error::integrity); + send_error(error::bitcoind::internal_error); return true; } @@ -1676,7 +1697,7 @@ bool protocol_bitcoind_blockchain::handle_wait_for_block(const code& ec, if (!decode_hash(wait_hash_, blockhash)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -1694,7 +1715,7 @@ bool protocol_bitcoind_blockchain::handle_wait_for_block_height(const code& ec, if (!to_integer(wait_height_, height)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -1761,7 +1782,7 @@ void protocol_bitcoind_blockchain::arm_wait(double timeout) NOEXCEPT if (!to_integer(span, timeout)) { wait_ = wait::none; - send_error(error::invalid_argument); + send_error(error::bitcoind::misc_error); return; } @@ -1821,7 +1842,7 @@ bool protocol_bitcoind_blockchain::handle_get_mempool_ancestors(const code& ec, rpc_interface::get_mempool_ancestors) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::client_mempool_disabled); return true; } @@ -1829,7 +1850,7 @@ bool protocol_bitcoind_blockchain::handle_get_mempool_cluster(const code& ec, rpc_interface::get_mempool_cluster) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::client_mempool_disabled); return true; } @@ -1837,7 +1858,7 @@ bool protocol_bitcoind_blockchain::handle_get_mempool_descendants(const code& ec rpc_interface::get_mempool_descendants) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::client_mempool_disabled); return true; } @@ -1845,7 +1866,7 @@ bool protocol_bitcoind_blockchain::handle_get_mempool_entry(const code& ec, rpc_interface::get_mempool_entry) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::client_mempool_disabled); return true; } @@ -1853,7 +1874,7 @@ bool protocol_bitcoind_blockchain::handle_get_mempool_info(const code& ec, rpc_interface::get_mempool_info) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::client_mempool_disabled); return true; } @@ -1861,7 +1882,7 @@ bool protocol_bitcoind_blockchain::handle_get_raw_mempool(const code& ec, rpc_interface::get_raw_mempool) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::client_mempool_disabled); return true; } @@ -1869,7 +1890,7 @@ bool protocol_bitcoind_blockchain::handle_get_tx_spending_prevout(const code& ec rpc_interface::get_tx_spending_prevout) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::client_mempool_disabled); return true; } @@ -1877,7 +1898,7 @@ bool protocol_bitcoind_blockchain::handle_import_mempool(const code& ec, rpc_interface::import_mempool) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::client_mempool_disabled); return true; } diff --git a/src/protocols/bitcoind/protocol_bitcoind_control.cpp b/src/protocols/bitcoind/protocol_bitcoind_control.cpp index f2e05238..89b7e3fa 100644 --- a/src/protocols/bitcoind/protocol_bitcoind_control.cpp +++ b/src/protocols/bitcoind/protocol_bitcoind_control.cpp @@ -133,7 +133,7 @@ bool protocol_bitcoind_control::handle_stop(const code& ec, rpc_interface::stop) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -148,7 +148,7 @@ bool protocol_bitcoind_control::handle_get_memory_info(const code& ec, // mallocinfo is a glibc-specific malloc dump. if (mode != "stats") { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -264,7 +264,7 @@ bool protocol_bitcoind_control::handle_logging(const code& ec, if (!include.empty() || !exclude.empty()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } diff --git a/src/protocols/bitcoind/protocol_bitcoind_dispatch.cpp b/src/protocols/bitcoind/protocol_bitcoind_dispatch.cpp index 393c45b9..dd9421c6 100644 --- a/src/protocols/bitcoind/protocol_bitcoind_dispatch.cpp +++ b/src/protocols/bitcoind/protocol_bitcoind_dispatch.cpp @@ -97,7 +97,7 @@ void CLASS::handle_receive_post(const code& ec, // The credential may be restricted to a subset of interface methods. if (!permitted(message.method)) { - send_error(error::method_unauthorized); + send_forbidden(*post); return; } @@ -140,7 +140,7 @@ void CLASS::dispatch_websocket( // The credential may be restricted to a subset of interface methods. if (!permitted(message.method)) { - send_error(error::method_unauthorized); + stop(network::error::unauthorized); return; } diff --git a/src/protocols/bitcoind/protocol_bitcoind_mining.cpp b/src/protocols/bitcoind/protocol_bitcoind_mining.cpp index 688db09d..c8e1d71f 100644 --- a/src/protocols/bitcoind/protocol_bitcoind_mining.cpp +++ b/src/protocols/bitcoind/protocol_bitcoind_mining.cpp @@ -84,7 +84,7 @@ bool protocol_bitcoind_mining::handle_get_network_hash_ps(const code& ec, } else if (!to_integer(target, height)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } else @@ -100,7 +100,7 @@ bool protocol_bitcoind_mining::handle_get_network_hash_ps(const code& ec, } else if (!to_integer(window, nblocks)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -120,7 +120,7 @@ bool protocol_bitcoind_mining::handle_get_network_hash_ps(const code& ec, const auto header = query.get_header(query.to_confirmed(index)); if (!header) { - send_error(database::error::integrity); + send_error(error::bitcoind::internal_error); return true; } @@ -139,7 +139,7 @@ bool protocol_bitcoind_mining::handle_get_network_hash_ps(const code& ec, if (!query.get_branch_work(start_work, query.to_confirmed(first)) || !query.get_branch_work(end_work, query.to_confirmed(target))) { - send_error(database::error::integrity); + send_error(error::bitcoind::internal_error); return true; } @@ -166,7 +166,7 @@ bool protocol_bitcoind_mining::handle_get_mining_info(const code& ec, const auto top = query.get_header(link); if (!top) { - send_error(database::error::integrity); + send_error(error::bitcoind::internal_error); return true; } @@ -176,7 +176,7 @@ bool protocol_bitcoind_mining::handle_get_mining_info(const code& ec, const auto state = query.get_chain_state(bitcoin, key); if (!state) { - send_error(database::error::integrity); + send_error(error::bitcoind::internal_error); return true; } @@ -223,7 +223,7 @@ bool protocol_bitcoind_mining::handle_submit_block(const code& ec, data_chunk data{}; if (!decode_base16(data, hexdata)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -231,7 +231,7 @@ bool protocol_bitcoind_mining::handle_submit_block(const code& ec, const auto block = to_shared(data, witness); if (!block->is_valid()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -255,14 +255,14 @@ bool protocol_bitcoind_mining::handle_submit_header(const code& ec, data_chunk data{}; if (!decode_base16(data, hexdata)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } const auto header = to_shared(data); if (!header->is_valid()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -294,12 +294,12 @@ void protocol_bitcoind_mining::handle_organize_header(const code& ec, POST(do_submit_header, ec); } -// bitcoind returns null on acceptance and a reason string on rejection. +// bitcoind returns null on acceptance and a reject token on rejection. void protocol_bitcoind_mining::do_submit_block(const code& ec) NOEXCEPT { BC_ASSERT(stranded()); if (ec) - send_result(ec.message(), 64); + send_result(error::bitcoind::reject(ec), 64); else send_result(null_t{}, 8); } @@ -307,8 +307,9 @@ void protocol_bitcoind_mining::do_submit_block(const code& ec) NOEXCEPT void protocol_bitcoind_mining::do_submit_header(const code& ec) NOEXCEPT { BC_ASSERT(stranded()); + using namespace error::bitcoind; if (ec) - send_error(ec); + send_error(translate(ec, verify_error)); else send_result(null_t{}, 8); } @@ -317,7 +318,7 @@ bool protocol_bitcoind_mining::handle_get_block_template(const code& ec, rpc_interface::get_block_template) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::client_mempool_disabled); return true; } @@ -325,7 +326,7 @@ bool protocol_bitcoind_mining::handle_get_prioritised_transactions(const code& e rpc_interface::get_prioritised_transactions) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::client_mempool_disabled); return true; } @@ -333,7 +334,7 @@ bool protocol_bitcoind_mining::handle_prioritise_transaction(const code& ec, rpc_interface::prioritise_transaction) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::client_mempool_disabled); return true; } diff --git a/src/protocols/bitcoind/protocol_bitcoind_network.cpp b/src/protocols/bitcoind/protocol_bitcoind_network.cpp index f83779ee..38c5a4cf 100644 --- a/src/protocols/bitcoind/protocol_bitcoind_network.cpp +++ b/src/protocols/bitcoind/protocol_bitcoind_network.cpp @@ -220,7 +220,7 @@ bool protocol_bitcoind_network::handle_get_node_addresses(const code& ec, if (!to_integer(node_count_, count) || (!network.empty() && network != "ipv4" && network != "ipv6")) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -310,7 +310,7 @@ bool protocol_bitcoind_network::handle_clear_banned(const code& ec, rpc_interface::clear_banned) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::database_error); return true; } @@ -318,7 +318,7 @@ bool protocol_bitcoind_network::handle_list_banned(const code& ec, rpc_interface::list_banned) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::database_error); return true; } @@ -326,7 +326,7 @@ bool protocol_bitcoind_network::handle_set_ban(const code& ec, rpc_interface::set_ban) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::database_error); return true; } @@ -341,8 +341,8 @@ bool protocol_bitcoind_network::handle_add_node(const code& ec, if (command != "add" && command != "onetry") { - send_error(command == "remove" ? error::not_implemented : - error::invalid_argument); + send_error(command == "remove" ? error::bitcoind::client_node_not_added : + error::bitcoind::misc_error); return true; } @@ -353,7 +353,7 @@ bool protocol_bitcoind_network::handle_add_node(const code& ec, } catch (const std::exception&) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -365,7 +365,7 @@ bool protocol_bitcoind_network::handle_disconnect_node(const code& ec, rpc_interface::disconnect_node) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -373,7 +373,7 @@ bool protocol_bitcoind_network::handle_export_asmap(const code& ec, rpc_interface::export_asmap) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -381,7 +381,7 @@ bool protocol_bitcoind_network::handle_get_added_node_info(const code& ec, rpc_interface::get_added_node_info) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::client_node_not_added); return true; } @@ -428,7 +428,7 @@ bool protocol_bitcoind_network::handle_get_peer_info(const code& ec, rpc_interface::get_peer_info) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } diff --git a/src/protocols/bitcoind/protocol_bitcoind_test.cpp b/src/protocols/bitcoind/protocol_bitcoind_test.cpp index 43d0d79a..b77eb436 100644 --- a/src/protocols/bitcoind/protocol_bitcoind_test.cpp +++ b/src/protocols/bitcoind/protocol_bitcoind_test.cpp @@ -82,7 +82,7 @@ bool protocol_bitcoind_test::handle_add_connection(const code& ec, rpc_interface::add_connection) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -90,7 +90,7 @@ bool protocol_bitcoind_test::handle_add_peer_address(const code& ec, rpc_interface::add_peer_address) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -98,7 +98,7 @@ bool protocol_bitcoind_test::handle_echo(const code& ec, rpc_interface::echo) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -106,7 +106,7 @@ bool protocol_bitcoind_test::handle_echo_ipc(const code& ec, rpc_interface::echo_ipc) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -114,7 +114,7 @@ bool protocol_bitcoind_test::handle_echo_json(const code& ec, rpc_interface::echo_json) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -122,7 +122,7 @@ bool protocol_bitcoind_test::handle_estimate_raw_fee(const code& ec, rpc_interface::estimate_raw_fee) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -130,7 +130,7 @@ bool protocol_bitcoind_test::handle_generate(const code& ec, rpc_interface::generate) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -138,7 +138,7 @@ bool protocol_bitcoind_test::handle_generate_block(const code& ec, rpc_interface::generate_block) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -146,7 +146,7 @@ bool protocol_bitcoind_test::handle_generate_to_address(const code& ec, rpc_interface::generate_to_address) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -154,7 +154,7 @@ bool protocol_bitcoind_test::handle_generate_to_descriptor(const code& ec, rpc_interface::generate_to_descriptor) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -162,7 +162,7 @@ bool protocol_bitcoind_test::handle_get_mempool_fee_rate_diagram(const code& ec, rpc_interface::get_mempool_fee_rate_diagram) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -170,7 +170,7 @@ bool protocol_bitcoind_test::handle_get_orphan_txs(const code& ec, rpc_interface::get_orphan_txs) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -178,7 +178,7 @@ bool protocol_bitcoind_test::handle_get_raw_addrman(const code& ec, rpc_interface::get_raw_addrman) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -186,7 +186,7 @@ bool protocol_bitcoind_test::handle_invalidate_block(const code& ec, rpc_interface::invalidate_block) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -194,7 +194,7 @@ bool protocol_bitcoind_test::handle_mock_scheduler(const code& ec, rpc_interface::mock_scheduler) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -202,7 +202,7 @@ bool protocol_bitcoind_test::handle_reconsider_block(const code& ec, rpc_interface::reconsider_block) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -210,7 +210,7 @@ bool protocol_bitcoind_test::handle_send_msg_to_peer(const code& ec, rpc_interface::send_msg_to_peer) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -218,7 +218,7 @@ bool protocol_bitcoind_test::handle_set_mock_time(const code& ec, rpc_interface::set_mock_time) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -226,7 +226,7 @@ bool protocol_bitcoind_test::handle_sync_with_validation_interface_queue(const c rpc_interface::sync_with_validation_interface_queue) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } diff --git a/src/protocols/bitcoind/protocol_bitcoind_transaction.cpp b/src/protocols/bitcoind/protocol_bitcoind_transaction.cpp index 866541ad..465cc44d 100644 --- a/src/protocols/bitcoind/protocol_bitcoind_transaction.cpp +++ b/src/protocols/bitcoind/protocol_bitcoind_transaction.cpp @@ -88,7 +88,7 @@ bool protocol_bitcoind_transaction::handle_get_raw_transaction(const code& ec, hash_digest hash{}; if (!decode_hash(hash, txid)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -98,7 +98,7 @@ bool protocol_bitcoind_transaction::handle_get_raw_transaction(const code& ec, const auto tx = query.get_transaction(link, witness); if (!tx) { - send_error(error::not_found, txid, txid.size()); + send_error(error::bitcoind::invalid_address_or_key, txid, txid.size()); return true; } @@ -109,13 +109,16 @@ bool protocol_bitcoind_transaction::handle_get_raw_transaction(const code& ec, json_verbose = 2 }; - size_t level{}; - if (!to_integer(level, verbose) || level > verbosity::json_verbose) + int64_t requested{}; + if (!to_integer(requested, verbose)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::misc_error); return true; } + // bitcoind clamps out of range verbosity. + const auto level = limit(requested, verbosity::json_verbose); + if (level == verbosity::hexadecimal) { send_text(to_text(*tx, tx->serialized_size(witness), witness)); @@ -146,20 +149,45 @@ bool protocol_bitcoind_transaction::handle_send_raw_transaction(const code& ec, data_chunk data{}; if (!decode_base16(data, hexstring)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } const auto tx = to_shared(data, true); if (!tx->is_valid()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } + // A confirmed tx with any unspent output is reported without validating. + const auto& query = archive(); + const auto link = query.to_tx(tx->hash(false)); + if (!link.is_terminal() && query.is_confirmed_tx(link)) + { + const auto outs = query.to_outputs(link); + const auto unspent = [&query](const auto& out) NOEXCEPT + { + return !query.is_confirmed_spent(out); + }; + + if (std::any_of(outs.begin(), outs.end(), unspent)) + { + send_error(error::bitcoind::verify_already_in_utxo_set); + return true; + } + } + if (const auto fault = broadcast_tx(tx); fault) { - send_error(fault); + using namespace error::bitcoind; + + // Absent and confirmed-spent inputs are missing coins (as bitcoind). + const auto missing = + (fault == system::error::missing_previous_output) || + (fault == system::error::confirmed_double_spend); + + send_error(translate(fault, missing ? verify_error : verify_rejected)); return true; } @@ -176,7 +204,7 @@ bool protocol_bitcoind_transaction::handle_test_mempool_accept(const code& ec, if (rawtxs.empty()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -186,7 +214,7 @@ bool protocol_bitcoind_transaction::handle_test_mempool_accept(const code& ec, { if (!std::holds_alternative(item.value())) { - send_error(error::invalid_argument); + send_error(error::bitcoind::type_error); return true; } @@ -194,7 +222,7 @@ bool protocol_bitcoind_transaction::handle_test_mempool_accept(const code& ec, const chain::transaction tx{ hexer, true }; if (!tx.is_valid() || !hexer.is_exhausted()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -207,7 +235,7 @@ bool protocol_bitcoind_transaction::handle_test_mempool_accept(const code& ec, }; if (fault) - result.emplace("reject-reason", fault.message()); + result.emplace("reject-reason", error::bitcoind::reject(fault)); results.emplace_back(std::move(result)); } @@ -224,7 +252,7 @@ code protocol_bitcoind_transaction::build_transaction(chain::transaction& out, { uint32_t lock_time{}; if (!to_integer(lock_time, locktime)) - return error::invalid_argument; + return error::bitcoind::invalid_parameter; using namespace chain; const auto sequence = replaceable ? messages::peer::bip125_sequence : @@ -238,7 +266,7 @@ code protocol_bitcoind_transaction::build_transaction(chain::transaction& out, for (const auto& item: inputs) { if (!std::holds_alternative(item.value())) - return error::invalid_argument; + return error::bitcoind::type_error; const auto& fields = std::get(item.value()); const auto txid_it = fields.find("txid"); @@ -246,11 +274,11 @@ code protocol_bitcoind_transaction::build_transaction(chain::transaction& out, if (txid_it == fields.end() || vout_it == fields.end() || !std::holds_alternative(txid_it->second.value()) || !std::holds_alternative(vout_it->second.value())) - return error::invalid_argument; + return error::bitcoind::invalid_parameter; if (!decode_hash(hash, std::get(txid_it->second.value())) || !to_integer(vout, std::get(vout_it->second.value()))) - return error::invalid_argument; + return error::bitcoind::invalid_parameter; ins->push_back(to_shared(point{ hash, vout }, script{}, sequence)); } @@ -268,7 +296,7 @@ code protocol_bitcoind_transaction::build_transaction(chain::transaction& out, if (!std::holds_alternative(pair.second.value()) || !decode_base16(data, std::get(pair.second.value())) || data.size() > max_null_data_size) - return error::invalid_argument; + return error::bitcoind::invalid_parameter; outs->push_back(to_shared(zero, chain::script{ script::to_pay_null_data_pattern(data) })); @@ -276,21 +304,20 @@ code protocol_bitcoind_transaction::build_transaction(chain::transaction& out, } if (!std::holds_alternative(pair.second.value())) - return error::invalid_argument; + return error::bitcoind::type_error; - if (const auto fault = output_script(script, pair.first, p2kh_, p2sh_, - witness_)) - return fault; + if (output_script(script, pair.first, p2kh_, p2sh_, witness_)) + return error::bitcoind::invalid_address_or_key; const auto btc = std::get(pair.second.value()); if (!to_integer(satoshi, btc * satoshi_per_bitcoin, false)) - return error::invalid_argument; + return error::bitcoind::type_error; outs->push_back(to_shared(satoshi, std::move(script))); } out = { 1, ins, outs, lock_time }; - return error::success; + return error::bitcoind::success; } bool protocol_bitcoind_transaction::handle_create_raw_transaction( @@ -324,7 +351,7 @@ bool protocol_bitcoind_transaction::handle_decode_raw_transaction(const code& ec data_chunk data{}; if (!decode_base16(data, hexstring)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -336,7 +363,7 @@ bool protocol_bitcoind_transaction::handle_decode_raw_transaction(const code& ec if (!tx.is_valid()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -522,7 +549,7 @@ bool protocol_bitcoind_transaction::handle_decode_psbt(const code& ec, const psbt_tx doc(psbt); if (!doc) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -594,7 +621,7 @@ bool protocol_bitcoind_transaction::handle_analyze_psbt(const code& ec, const psbt_tx doc(psbt); if (!doc) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -678,14 +705,20 @@ bool protocol_bitcoind_transaction::handle_combine_psbt(const code& ec, { if (!std::holds_alternative(item.value())) { - send_error(error::invalid_argument); + send_error(error::bitcoind::type_error); return true; } psbt_tx doc(std::get(item.value())); - if (!doc || (combined && !combined.combine(doc))) + if (!doc) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); + return true; + } + + if (combined && !combined.combine(doc)) + { + send_error(error::bitcoind::invalid_parameter); return true; } @@ -695,7 +728,7 @@ bool protocol_bitcoind_transaction::handle_combine_psbt(const code& ec, if (!combined) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -713,7 +746,7 @@ bool protocol_bitcoind_transaction::handle_convert_to_psbt(const code& ec, data_chunk data{}; if (!decode_base16(data, hexstring)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -724,7 +757,7 @@ bool protocol_bitcoind_transaction::handle_convert_to_psbt(const code& ec, if (!tx.is_valid()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -738,7 +771,7 @@ bool protocol_bitcoind_transaction::handle_convert_to_psbt(const code& ec, { if (!permitsigdata) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -755,7 +788,7 @@ bool protocol_bitcoind_transaction::handle_convert_to_psbt(const code& ec, const psbt_tx doc(tx); if (!doc) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -781,7 +814,7 @@ bool protocol_bitcoind_transaction::handle_create_psbt(const code& ec, const psbt_tx doc(tx); if (!doc) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -799,7 +832,7 @@ bool protocol_bitcoind_transaction::handle_finalize_psbt(const code& ec, psbt_tx doc(psbt); if (!doc) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -829,7 +862,7 @@ bool protocol_bitcoind_transaction::handle_join_psbts(const code& ec, if (txs.size() < 2u) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -838,14 +871,20 @@ bool protocol_bitcoind_transaction::handle_join_psbts(const code& ec, { if (!std::holds_alternative(item.value())) { - send_error(error::invalid_argument); + send_error(error::bitcoind::type_error); return true; } psbt_tx doc(std::get(item.value())); - if (!doc || (joined && !joined.join(doc))) + if (!doc) + { + send_error(error::bitcoind::deserialization_error); + return true; + } + + if (joined && !joined.join(doc)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -861,7 +900,7 @@ bool protocol_bitcoind_transaction::handle_descriptor_process_psbt(const code& e rpc_interface::descriptor_process_psbt) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -875,14 +914,14 @@ bool protocol_bitcoind_transaction::handle_utxo_update_psbt(const code& ec, // Descriptor expansion requires the descriptor engine (pending). if (!descriptors.empty()) { - send_error(error::not_implemented); + send_error(error::bitcoind::invalid_parameter); return true; } psbt_tx doc(psbt); if (!doc) { - send_error(error::invalid_argument); + send_error(error::bitcoind::deserialization_error); return true; } @@ -918,7 +957,7 @@ bool protocol_bitcoind_transaction::handle_abort_private_broadcast(const code& e rpc_interface::abort_private_broadcast) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -926,7 +965,7 @@ bool protocol_bitcoind_transaction::handle_get_private_broadcast_info(const code rpc_interface::get_private_broadcast_info) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -934,7 +973,7 @@ bool protocol_bitcoind_transaction::handle_submit_package(const code& ec, rpc_interface::submit_package) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::client_mempool_disabled); return true; } diff --git a/src/protocols/bitcoind/protocol_bitcoind_utility.cpp b/src/protocols/bitcoind/protocol_bitcoind_utility.cpp index 2391e34a..82b878c4 100644 --- a/src/protocols/bitcoind/protocol_bitcoind_utility.cpp +++ b/src/protocols/bitcoind/protocol_bitcoind_utility.cpp @@ -102,18 +102,13 @@ bool protocol_bitcoind_utility::handle_decode_script(const code& ec, data_chunk data{}; if (!decode_base16(data, hex)) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } using namespace chain; constexpr auto prefix = false; const script script{ data, prefix }; - if (!script.is_valid()) - { - send_error(error::invalid_argument); - return true; - } using namespace wallet; const auto pattern = script.output_pattern(); @@ -124,6 +119,15 @@ bool protocol_bitcoind_utility::handle_decode_script(const code& ec, { "type", to_script_type(pattern) } }; + // An undecodable script is rendered, not rejected (as bitcoind). + if (!script.is_valid() || script.is_underflow()) + { + const auto body = "raw(" + encode_base16(data) + ")"; + result["desc"] = body + "#" + descriptor_checksum(body); + send_result(std::move(result), 512); + return true; + } + if (pattern == script_pattern::pay_key_hash || pattern == script_pattern::pay_script_hash) { @@ -215,7 +219,7 @@ bool protocol_bitcoind_utility::handle_create_multisig(const code& ec, if (!to_integer(required, nrequired) || is_zero(required) || required > keys.size()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -223,14 +227,16 @@ bool protocol_bitcoind_utility::handle_create_multisig(const code& ec, address_type != "p2sh-segwit" && address_type != "bech32") { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_address_or_key); return true; } + // An invalid key (bitcoind -5) and an oversized script (-8) are not + // distinguished by the helper. auto result = create_multisig(required, keys, address_type); if (result.empty()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_address_or_key); return true; } @@ -246,9 +252,15 @@ bool protocol_bitcoind_utility::handle_derive_addresses(const code& ec, return false; const wallet::descriptor parsed{ expression }; - if (!parsed || parsed.ranged() != range.has_value()) + if (!parsed) + { + send_error(error::bitcoind::invalid_address_or_key); + return true; + } + + if (parsed.ranged() != range.has_value()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -262,7 +274,7 @@ bool protocol_bitcoind_utility::handle_derive_addresses(const code& ec, { if (!to_integer(end, std::get(value))) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } } @@ -276,13 +288,13 @@ bool protocol_bitcoind_utility::handle_derive_addresses(const code& ec, !to_integer(end, std::get(pair.back().value())) || end < begin) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } } else { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } } @@ -291,7 +303,7 @@ bool protocol_bitcoind_utility::handle_derive_addresses(const code& ec, constexpr uint32_t maximum_range = 10'000; if (floored_subtract(end, begin) >= maximum_range) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_parameter); return true; } @@ -305,7 +317,7 @@ bool protocol_bitcoind_utility::handle_derive_addresses(const code& ec, if (address.empty()) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_address_or_key); return true; } @@ -327,7 +339,7 @@ bool protocol_bitcoind_utility::handle_get_descriptor_info(const code& ec, const wallet::descriptor parsed{ expression }; if (!parsed) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_address_or_key); return true; } @@ -353,7 +365,7 @@ bool protocol_bitcoind_utility::handle_verify_message(const code& ec, const payment_address payment(address); if (!payment) { - send_error(error::invalid_argument); + send_error(error::bitcoind::invalid_address_or_key); return true; } @@ -361,7 +373,7 @@ bool protocol_bitcoind_utility::handle_verify_message(const code& ec, if (!decode_base64(decoded, signature) || decoded.size() != message_signature_size) { - send_error(error::invalid_argument); + send_error(error::bitcoind::type_error); return true; } @@ -407,7 +419,7 @@ bool protocol_bitcoind_utility::handle_estimate_smart_fee(const code& ec, rpc_interface::estimate_smart_fee) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::internal_error); return true; } diff --git a/src/protocols/bitcoind/protocol_bitcoind_wallet.cpp b/src/protocols/bitcoind/protocol_bitcoind_wallet.cpp index c8fd8533..12a98b2f 100644 --- a/src/protocols/bitcoind/protocol_bitcoind_wallet.cpp +++ b/src/protocols/bitcoind/protocol_bitcoind_wallet.cpp @@ -121,7 +121,7 @@ bool protocol_bitcoind_wallet::handle_abandon_transaction(const code& ec, rpc_interface::abandon_transaction) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -129,7 +129,7 @@ bool protocol_bitcoind_wallet::handle_abort_rescan(const code& ec, rpc_interface::abort_rescan) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -137,7 +137,7 @@ bool protocol_bitcoind_wallet::handle_add_hd_key(const code& ec, rpc_interface::add_hd_key) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -145,7 +145,7 @@ bool protocol_bitcoind_wallet::handle_backup_wallet(const code& ec, rpc_interface::backup_wallet) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -153,7 +153,7 @@ bool protocol_bitcoind_wallet::handle_bump_fee(const code& ec, rpc_interface::bump_fee) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -161,7 +161,7 @@ bool protocol_bitcoind_wallet::handle_create_wallet(const code& ec, rpc_interface::create_wallet) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -169,7 +169,7 @@ bool protocol_bitcoind_wallet::handle_create_wallet_descriptor(const code& ec, rpc_interface::create_wallet_descriptor) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -177,7 +177,7 @@ bool protocol_bitcoind_wallet::handle_encrypt_wallet(const code& ec, rpc_interface::encrypt_wallet) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -185,7 +185,7 @@ bool protocol_bitcoind_wallet::handle_export_watchonly_wallet(const code& ec, rpc_interface::export_watchonly_wallet) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -193,7 +193,7 @@ bool protocol_bitcoind_wallet::handle_get_addresses_by_label(const code& ec, rpc_interface::get_addresses_by_label) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -201,7 +201,7 @@ bool protocol_bitcoind_wallet::handle_get_address_info(const code& ec, rpc_interface::get_address_info) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -209,7 +209,7 @@ bool protocol_bitcoind_wallet::handle_get_balance(const code& ec, rpc_interface::get_balance) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -217,7 +217,7 @@ bool protocol_bitcoind_wallet::handle_get_balances(const code& ec, rpc_interface::get_balances) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -225,7 +225,7 @@ bool protocol_bitcoind_wallet::handle_get_hd_keys(const code& ec, rpc_interface::get_hd_keys) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -233,7 +233,7 @@ bool protocol_bitcoind_wallet::handle_get_new_address(const code& ec, rpc_interface::get_new_address) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -241,7 +241,7 @@ bool protocol_bitcoind_wallet::handle_get_raw_change_address(const code& ec, rpc_interface::get_raw_change_address) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -249,7 +249,7 @@ bool protocol_bitcoind_wallet::handle_get_received_by_address(const code& ec, rpc_interface::get_received_by_address) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -257,7 +257,7 @@ bool protocol_bitcoind_wallet::handle_get_received_by_label(const code& ec, rpc_interface::get_received_by_label) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -265,7 +265,7 @@ bool protocol_bitcoind_wallet::handle_get_transaction(const code& ec, rpc_interface::get_transaction) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -273,7 +273,7 @@ bool protocol_bitcoind_wallet::handle_get_wallet_info(const code& ec, rpc_interface::get_wallet_info) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -281,7 +281,7 @@ bool protocol_bitcoind_wallet::handle_import_descriptors(const code& ec, rpc_interface::import_descriptors) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -289,7 +289,7 @@ bool protocol_bitcoind_wallet::handle_import_pruned_funds(const code& ec, rpc_interface::import_pruned_funds) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -297,7 +297,7 @@ bool protocol_bitcoind_wallet::handle_keypool_refill(const code& ec, rpc_interface::keypool_refill) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -305,7 +305,7 @@ bool protocol_bitcoind_wallet::handle_list_address_groupings(const code& ec, rpc_interface::list_address_groupings) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -313,7 +313,7 @@ bool protocol_bitcoind_wallet::handle_list_descriptors(const code& ec, rpc_interface::list_descriptors) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -321,7 +321,7 @@ bool protocol_bitcoind_wallet::handle_list_labels(const code& ec, rpc_interface::list_labels) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -329,7 +329,7 @@ bool protocol_bitcoind_wallet::handle_list_lock_unspent(const code& ec, rpc_interface::list_lock_unspent) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -337,7 +337,7 @@ bool protocol_bitcoind_wallet::handle_list_received_by_address(const code& ec, rpc_interface::list_received_by_address) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -345,7 +345,7 @@ bool protocol_bitcoind_wallet::handle_list_received_by_label(const code& ec, rpc_interface::list_received_by_label) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -353,7 +353,7 @@ bool protocol_bitcoind_wallet::handle_list_since_block(const code& ec, rpc_interface::list_since_block) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -361,7 +361,7 @@ bool protocol_bitcoind_wallet::handle_list_transactions(const code& ec, rpc_interface::list_transactions) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -369,7 +369,7 @@ bool protocol_bitcoind_wallet::handle_list_unspent(const code& ec, rpc_interface::list_unspent) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -377,7 +377,7 @@ bool protocol_bitcoind_wallet::handle_list_wallet_dir(const code& ec, rpc_interface::list_wallet_dir) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -385,7 +385,7 @@ bool protocol_bitcoind_wallet::handle_list_wallets(const code& ec, rpc_interface::list_wallets) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -393,7 +393,7 @@ bool protocol_bitcoind_wallet::handle_load_wallet(const code& ec, rpc_interface::load_wallet) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -401,7 +401,7 @@ bool protocol_bitcoind_wallet::handle_lock_unspent(const code& ec, rpc_interface::lock_unspent) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -409,7 +409,7 @@ bool protocol_bitcoind_wallet::handle_migrate_wallet(const code& ec, rpc_interface::migrate_wallet) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -417,7 +417,7 @@ bool protocol_bitcoind_wallet::handle_psbt_bump_fee(const code& ec, rpc_interface::psbt_bump_fee) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -425,7 +425,7 @@ bool protocol_bitcoind_wallet::handle_remove_pruned_funds(const code& ec, rpc_interface::remove_pruned_funds) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -433,7 +433,7 @@ bool protocol_bitcoind_wallet::handle_rescan_block_chain(const code& ec, rpc_interface::rescan_block_chain) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -441,7 +441,7 @@ bool protocol_bitcoind_wallet::handle_restore_wallet(const code& ec, rpc_interface::restore_wallet) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -449,7 +449,7 @@ bool protocol_bitcoind_wallet::handle_wallet_send(const code& ec, rpc_interface::send) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -457,7 +457,7 @@ bool protocol_bitcoind_wallet::handle_send_all(const code& ec, rpc_interface::send_all) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -465,7 +465,7 @@ bool protocol_bitcoind_wallet::handle_send_many(const code& ec, rpc_interface::send_many) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -473,7 +473,7 @@ bool protocol_bitcoind_wallet::handle_send_to_address(const code& ec, rpc_interface::send_to_address) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -481,7 +481,7 @@ bool protocol_bitcoind_wallet::handle_set_label(const code& ec, rpc_interface::set_label) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -489,7 +489,7 @@ bool protocol_bitcoind_wallet::handle_set_wallet_flag(const code& ec, rpc_interface::set_wallet_flag) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -497,7 +497,7 @@ bool protocol_bitcoind_wallet::handle_sign_message(const code& ec, rpc_interface::sign_message) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -505,7 +505,7 @@ bool protocol_bitcoind_wallet::handle_sign_raw_transaction_with_wallet(const cod rpc_interface::sign_raw_transaction_with_wallet) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -513,7 +513,7 @@ bool protocol_bitcoind_wallet::handle_simulate_raw_transaction(const code& ec, rpc_interface::simulate_raw_transaction) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -521,7 +521,7 @@ bool protocol_bitcoind_wallet::handle_unload_wallet(const code& ec, rpc_interface::unload_wallet) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -529,7 +529,7 @@ bool protocol_bitcoind_wallet::handle_wallet_create_funded_psbt(const code& ec, rpc_interface::wallet_create_funded_psbt) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -537,7 +537,7 @@ bool protocol_bitcoind_wallet::handle_wallet_display_address(const code& ec, rpc_interface::wallet_display_address) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -545,7 +545,7 @@ bool protocol_bitcoind_wallet::handle_wallet_lock(const code& ec, rpc_interface::wallet_lock) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -553,7 +553,7 @@ bool protocol_bitcoind_wallet::handle_wallet_passphrase(const code& ec, rpc_interface::wallet_passphrase) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -561,7 +561,7 @@ bool protocol_bitcoind_wallet::handle_wallet_passphrase_change(const code& ec, rpc_interface::wallet_passphrase_change) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -569,7 +569,7 @@ bool protocol_bitcoind_wallet::handle_wallet_process_psbt(const code& ec, rpc_interface::wallet_process_psbt) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } @@ -577,7 +577,7 @@ bool protocol_bitcoind_wallet::handle_enumerate_signers(const code& ec, rpc_interface::enumerate_signers) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::bitcoind::method_not_found); return true; } diff --git a/src/protocols/btcd/protocol_btcd.cpp b/src/protocols/btcd/protocol_btcd.cpp index a2a2c9a6..22c5fafa 100644 --- a/src/protocols/btcd/protocol_btcd.cpp +++ b/src/protocols/btcd/protocol_btcd.cpp @@ -136,7 +136,7 @@ void protocol_btcd::handle_receive_post(const code& ec, // The credential may be restricted to a subset of interface methods. if (!permitted(message.method)) { - send_error(error::method_unauthorized); + send_error(error::btcd::invalid_params); return; } @@ -180,7 +180,7 @@ void protocol_btcd::dispatch_websocket( // The credential may be restricted to a subset of interface methods. if (!authenticate && !permitted(message.method)) { - send_error(network::error::unauthorized); + send_error(error::btcd::invalid_params); return; } @@ -234,7 +234,7 @@ bool protocol_btcd::handle_stop(const code& ec, return false; // The server/node cannot stop itself. - send_error(error::not_implemented); + send_error(error::btcd::unimplemented); return true; } @@ -267,7 +267,7 @@ bool protocol_btcd::handle_notify_new_transactions(const code& ec, btcd_interface::notify_new_transactions, bool) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::btcd::unimplemented); return true; } @@ -275,7 +275,7 @@ bool protocol_btcd::handle_stop_notify_new_transactions(const code& ec, btcd_interface::stop_notify_new_transactions) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::btcd::unimplemented); return true; } @@ -286,7 +286,7 @@ bool protocol_btcd::handle_notify_received(const code& ec, btcd_interface::notify_received, const value_t&) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::btcd::unimplemented); return true; } @@ -294,7 +294,7 @@ bool protocol_btcd::handle_stop_notify_received(const code& ec, btcd_interface::stop_notify_received, const value_t&) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::btcd::unimplemented); return true; } @@ -302,7 +302,7 @@ bool protocol_btcd::handle_notify_spent(const code& ec, btcd_interface::notify_spent, const value_t&) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::btcd::unimplemented); return true; } @@ -310,7 +310,7 @@ bool protocol_btcd::handle_stop_notify_spent(const code& ec, btcd_interface::stop_notify_spent, const value_t&) NOEXCEPT { if (stopped(ec)) return false; - send_error(error::not_implemented); + send_error(error::btcd::unimplemented); return true; } @@ -326,14 +326,14 @@ bool protocol_btcd::handle_rescan(const code& ec, hash_digest begin_hash{}; if (!decode_hash(begin_hash, beginblock)) { - send_error(error::not_found, two * beginblock.size()); + send_error(error::btcd::invalid_address_or_key, two * beginblock.size()); return true; } const auto& query = archive(); if (query.to_header(begin_hash).is_terminal()) { - send_error(error::not_found, two * beginblock.size()); + send_error(error::btcd::invalid_address_or_key, two * beginblock.size()); return true; } @@ -344,7 +344,7 @@ bool protocol_btcd::handle_rescan(const code& ec, if (has_addresses || has_outpoints) { - send_error(error::not_implemented); + send_error(error::btcd::unimplemented); return true; } @@ -353,7 +353,7 @@ bool protocol_btcd::handle_rescan(const code& ec, const auto header = query.get_header(confirmed); if (!header) { - send_error(error::not_found); + send_error(error::btcd::internal_error); return true; } diff --git a/src/protocols/btcd/protocol_btcd_filter.cpp b/src/protocols/btcd/protocol_btcd_filter.cpp index 9051721e..8664df07 100644 --- a/src/protocols/btcd/protocol_btcd_filter.cpp +++ b/src/protocols/btcd/protocol_btcd_filter.cpp @@ -54,23 +54,22 @@ bool protocol_btcd::handle_load_tx_filter(const code& ec, return false; hashes keys{}; - if (const auto fault = btcd::filter_keys(keys, addresses, p2kh_, p2sh_, - witness_)) + if (btcd::filter_keys(keys, addresses, p2kh_, p2sh_, witness_)) { - send_error(fault); + send_error(error::btcd::invalid_parameter); return true; } chain::points points{}; - if (const auto fault = btcd::filter_points(points, outpoints)) + if (btcd::filter_points(points, outpoints)) { - send_error(fault); + send_error(error::btcd::invalid_parameter); return true; } if (!keys.empty() && !archive().address_enabled()) { - send_error(error::not_implemented); + send_error(error::btcd::unimplemented); return true; } @@ -104,7 +103,7 @@ void protocol_btcd::do_load_tx_filter(bool reload, const hashes& keys, if (ceilinged_add(address_watches_.size(), outpoint_watches_.size()) >= maximum) { - ec = error::subscription_limit; + ec = error::btcd::misc_error; break; } @@ -130,7 +129,7 @@ void protocol_btcd::do_load_tx_filter(bool reload, const hashes& keys, if (ceilinged_add(address_watches_.size(), outpoint_watches_.size()) >= maximum) { - ec = error::subscription_limit; + ec = error::btcd::misc_error; break; } @@ -157,7 +156,8 @@ void protocol_btcd::complete_load_tx_filter(const code& ec) NOEXCEPT if (ec) { - send_error(ec); + using namespace error::btcd; + send_error(translate(ec, internal_error)); return; } @@ -172,7 +172,7 @@ bool protocol_btcd::handle_rescan_blocks(const code& ec, if (!std::holds_alternative(blockhashes.value())) { - send_error(error::invalid_argument); + send_error(error::btcd::invalid_params); return true; } @@ -180,10 +180,11 @@ bool protocol_btcd::handle_rescan_blocks(const code& ec, hashes block_hashes{}; for (const auto& item: std::get(blockhashes.value())) { + // btcd wraps the hash parse failure as an internal error. if (!std::holds_alternative(item.value()) || !decode_hash(hash, std::get(item.value()))) { - send_error(error::invalid_argument); + send_error(error::btcd::internal_error); return true; } @@ -192,7 +193,7 @@ bool protocol_btcd::handle_rescan_blocks(const code& ec, if (!archive().address_enabled()) { - send_error(error::not_implemented); + send_error(error::btcd::unimplemented); return true; } @@ -239,7 +240,7 @@ void protocol_btcd::do_rescan_watches(const hashes_ptr& block_hashes, size_t height{}; if (!query.get_height(height, query.to_header(hash))) { - POST_BTCD(complete_rescan_blocks, error::not_found, + POST_BTCD(complete_rescan_blocks, error::btcd::invalid_address_or_key, to_shared()); return; } @@ -302,7 +303,8 @@ void protocol_btcd::complete_rescan_blocks(const code& ec, if (ec) { - send_error(ec); + using namespace error::btcd; + send_error(translate(ec, internal_error)); return; } diff --git a/src/protocols/btcd/protocol_btcd_utility.cpp b/src/protocols/btcd/protocol_btcd_utility.cpp index 2af9c2de..940c3f1c 100644 --- a/src/protocols/btcd/protocol_btcd_utility.cpp +++ b/src/protocols/btcd/protocol_btcd_utility.cpp @@ -68,7 +68,7 @@ bool protocol_btcd::handle_get_block_chain_info(const code& ec, if (!chain_info(out, archive(), node_settings().limited_blocks, is_current_chain(true))) { - send_error(database::error::integrity); + send_error(error::btcd::internal_error); return true; } @@ -114,7 +114,7 @@ bool protocol_btcd::handle_get_difficulty(const code& ec, const auto header = query.get_header(query.to_confirmed(top)); if (!header) { - send_error(database::error::integrity); + send_error(error::btcd::internal_error); return true; } @@ -133,7 +133,7 @@ bool protocol_btcd::handle_get_info(const code& ec, const auto header = query.get_header(query.to_confirmed(top)); if (!header) { - send_error(database::error::integrity); + send_error(error::btcd::internal_error); return true; } diff --git a/src/protocols/electrum/protocol_electrum_addresses.cpp b/src/protocols/electrum/protocol_electrum_addresses.cpp index 46b28246..b4557590 100644 --- a/src/protocols/electrum/protocol_electrum_addresses.cpp +++ b/src/protocols/electrum/protocol_electrum_addresses.cpp @@ -43,7 +43,7 @@ void protocol_electrum::handle_blockchain_address_get_balance(const code& ec, if (at_least(electrum::version::v1_3)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -59,7 +59,7 @@ void protocol_electrum::handle_blockchain_address_get_history(const code& ec, if (at_least(electrum::version::v1_3)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -75,7 +75,7 @@ void protocol_electrum::handle_blockchain_address_get_mempool(const code& ec, if (at_least(electrum::version::v1_3)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -91,7 +91,7 @@ void protocol_electrum::handle_blockchain_address_list_unspent(const code& ec, if (at_least(electrum::version::v1_3)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -107,14 +107,14 @@ void protocol_electrum::handle_blockchain_address_subscribe(const code& ec, if (at_least(electrum::version::v1_3)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } const auto hash = extract_scripthash(address); if (hash == null_hash) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } diff --git a/src/protocols/electrum/protocol_electrum_fees.cpp b/src/protocols/electrum/protocol_electrum_fees.cpp index 5920e99c..bffe9b33 100644 --- a/src/protocols/electrum/protocol_electrum_fees.cpp +++ b/src/protocols/electrum/protocol_electrum_fees.cpp @@ -53,27 +53,27 @@ void protocol_electrum::handle_blockchain_estimate_fee(const code& ec, if (!at_least(electrum::version::v1_0)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } size_t target{}; if (!to_integer(target, number)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } if (!mode.empty() && !at_least(electrum::version::v1_6)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } const auto mode_ = mode_from_string(mode); if (mode_ == mode_t::unknown) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -105,7 +105,7 @@ void protocol_electrum::complete_estimate_fee(const code& ec, if (!disabled && ec) { // node::error::estimates_failed, implies store fault. - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } @@ -129,7 +129,7 @@ void protocol_electrum::handle_blockchain_relay_fee(const code& ec, if (!at_least(electrum::version::v1_0) || at_least(electrum::version::v1_6)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } diff --git a/src/protocols/electrum/protocol_electrum_headers.cpp b/src/protocols/electrum/protocol_electrum_headers.cpp index d1a42fb7..665b7a2b 100644 --- a/src/protocols/electrum/protocol_electrum_headers.cpp +++ b/src/protocols/electrum/protocol_electrum_headers.cpp @@ -43,7 +43,7 @@ void protocol_electrum::handle_blockchain_number_of_blocks_subscribe( if (at_least(electrum::version::v1_1)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -60,14 +60,14 @@ void protocol_electrum::handle_blockchain_block_get_chunk(const code& ec, if (at_least(electrum::version::v1_4)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } size_t position{}; if (!to_integer(position, index)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -88,7 +88,7 @@ void protocol_electrum::handle_blockchain_block_get_chunk(const code& ec, { if (!query.get_wire_header(writer, link)) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } } @@ -104,14 +104,14 @@ void protocol_electrum::handle_blockchain_block_get_header(const code& ec, if (at_least(electrum::version::v1_4)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } size_t target{}; if (!to_integer(target, height)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -130,7 +130,7 @@ void protocol_electrum::handle_blockchain_block_get_header(const code& ec, write::base16::fast writer{ sink }; if (!query.get_wire_header(writer, link)) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } @@ -147,7 +147,7 @@ void protocol_electrum::handle_blockchain_block_header(const code& ec, if (!at_least(electrum::version::v1_3)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -156,7 +156,7 @@ void protocol_electrum::handle_blockchain_block_header(const code& ec, if (!to_integer(starting, height) || !to_integer(waypoint, cp_height)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -173,7 +173,7 @@ void protocol_electrum::handle_blockchain_block_headers(const code& ec, if (!at_least(electrum::version::v1_2)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -184,13 +184,13 @@ void protocol_electrum::handle_blockchain_block_headers(const code& ec, !to_integer(waypoint, cp_height) || !to_integer(starting, start_height)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } if (!is_zero(cp_height) && !at_least(electrum::version::v1_4)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -211,17 +211,17 @@ void protocol_electrum::blockchain_block_headers(size_t starting, // ambiguous at count = 0 so guard must be applied to both args and prover. if (is_add_overflow(starting, quantity)) { - send_code(error::argument_overflow); + send_code(error::electrum::bad_request); return; } else if ((starting > top) || (prove && waypoint > top)) { - send_code(error::not_found); + send_code(error::electrum::bad_request); return; } else if (prove && target > waypoint) { - send_code(error::target_overflow); + send_code(error::electrum::bad_request); return; } @@ -237,7 +237,7 @@ void protocol_electrum::blockchain_block_headers(size_t starting, if (single && !is_one(links.size())) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } @@ -248,7 +248,7 @@ void protocol_electrum::blockchain_block_headers(size_t starting, const auto header = query.get_wire_header(links.front()); if (header.empty()) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } @@ -268,7 +268,7 @@ void protocol_electrum::blockchain_block_headers(size_t starting, const auto header = query.get_wire_header(link); if (header.empty()) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } @@ -296,7 +296,7 @@ void protocol_electrum::blockchain_block_headers(size_t starting, { if (!query.get_wire_header(writer, link)) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } } @@ -323,7 +323,8 @@ void protocol_electrum::blockchain_block_headers(size_t starting, if (const auto code = query.get_merkle_root_and_proof(root, proof, target, waypoint)) { - send_code(code); + using namespace error::electrum; + send_code(translate(code, daemon_error)); return; } @@ -364,7 +365,7 @@ void protocol_electrum::handle_blockchain_headers_subscribe(const code& ec, (!at_least(electrum::version::v1_2) && raw_defined) || ( at_least(electrum::version::v1_4) && raw_defined)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -375,7 +376,7 @@ void protocol_electrum::handle_blockchain_headers_subscribe(const code& ec, // This is unlikely but possible due to a race condition during reorg. if (link.is_terminal()) { - send_code(error::not_found); + send_code(error::electrum::daemon_error); return; } @@ -386,7 +387,7 @@ void protocol_electrum::handle_blockchain_headers_subscribe(const code& ec, const auto header = query.get_wire_header(link); if (header.empty()) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } @@ -402,7 +403,7 @@ void protocol_electrum::handle_blockchain_headers_subscribe(const code& ec, const auto header = query.get_header(link); if (!header) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } @@ -410,7 +411,7 @@ void protocol_electrum::handle_blockchain_headers_subscribe(const code& ec, value = value_from(electrumx(*header)); if (!value.is_object()) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } diff --git a/src/protocols/electrum/protocol_electrum_mempool.cpp b/src/protocols/electrum/protocol_electrum_mempool.cpp index 9318f3bb..760a0e20 100644 --- a/src/protocols/electrum/protocol_electrum_mempool.cpp +++ b/src/protocols/electrum/protocol_electrum_mempool.cpp @@ -38,7 +38,7 @@ void protocol_electrum::handle_mempool_get_fee_histogram(const code& ec, if (!at_least(electrum::version::v1_2)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -56,7 +56,7 @@ void protocol_electrum::handle_mempool_get_info(const code& ec, // Not documented, but replaces blockchain.relayfee. if (!at_least(electrum::version::v1_6)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } diff --git a/src/protocols/electrum/protocol_electrum_outpoints.cpp b/src/protocols/electrum/protocol_electrum_outpoints.cpp index b61c2a6f..2807a986 100644 --- a/src/protocols/electrum/protocol_electrum_outpoints.cpp +++ b/src/protocols/electrum/protocol_electrum_outpoints.cpp @@ -48,7 +48,7 @@ void protocol_electrum::handle_blockchain_utxo_get_address(const code& ec, if (at_least(electrum::version::v1_1)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -56,7 +56,7 @@ void protocol_electrum::handle_blockchain_utxo_get_address(const code& ec, hash_digest hash{}; if (!to_integer(offset, index) || !decode_hash(hash, tx_hash)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -73,7 +73,7 @@ void protocol_electrum::handle_blockchain_utxo_get_address(const code& ec, const auto script = query.get_output_script(output); if (!script) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } @@ -98,7 +98,7 @@ void protocol_electrum::handle_blockchain_outpoint_get_status(const code& ec, if (!at_least(electrum::version::v1_7)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -107,7 +107,7 @@ void protocol_electrum::handle_blockchain_outpoint_get_status(const code& ec, if (!to_integer(index, txout_idx) || !decode_hash(hash, tx_hash) || !is_valid_hint(spk_hint)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -132,7 +132,7 @@ void protocol_electrum::handle_blockchain_outpoint_subscribe(const code& ec, if (!at_least(electrum::version::v1_7)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -141,7 +141,7 @@ void protocol_electrum::handle_blockchain_outpoint_subscribe(const code& ec, if (!to_integer(index, txout_idx) || !decode_hash(hash, tx_hash) || !is_valid_hint(spk_hint)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -155,7 +155,7 @@ void protocol_electrum::do_outpoint_subscribe(const point& prevout) NOEXCEPT BC_ASSERT(notification_strand_.running_in_this_thread()); outpoint_subscription sub{}; - code ec{ error::subscription_limit }; + code ec{ error::electrum::excessive_resource_usage }; if (outpoint_subscriptions_.size() < options().maximum_subscriptions) { ec = error::success; @@ -179,7 +179,8 @@ void protocol_electrum::complete_outpoint_subscribe(const code& ec, if (ec) { - send_code(ec); + using namespace error::electrum; + send_code(translate(ec, daemon_error)); return; } @@ -213,7 +214,7 @@ void protocol_electrum::handle_blockchain_outpoint_unsubscribe(const code& ec, if (!at_least(electrum::version::v1_7)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -221,7 +222,7 @@ void protocol_electrum::handle_blockchain_outpoint_unsubscribe(const code& ec, hash_digest hash{}; if (!to_integer(index, txout_idx) || !decode_hash(hash, tx_hash)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } diff --git a/src/protocols/electrum/protocol_electrum_scripthash.cpp b/src/protocols/electrum/protocol_electrum_scripthash.cpp index 987d90b0..9e9e5d27 100644 --- a/src/protocols/electrum/protocol_electrum_scripthash.cpp +++ b/src/protocols/electrum/protocol_electrum_scripthash.cpp @@ -45,7 +45,7 @@ void protocol_electrum::handle_blockchain_scripthash_get_balance(const code& ec, if (!at_least(electrum::version::v1_1)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -60,13 +60,13 @@ void protocol_electrum::get_balance(const hash_digest& hash) NOEXCEPT BC_ASSERT(stranded()); if (hash == null_hash) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } if (!archive().address_enabled()) { - send_code(error::not_implemented); + send_code(error::electrum::method_not_found); return; } @@ -93,7 +93,8 @@ void protocol_electrum::complete_get_balance(const code& ec, if (ec) { - send_code(ec); + using namespace error::electrum; + send_code(translate(ec, daemon_error)); return; } @@ -118,7 +119,7 @@ void protocol_electrum::handle_blockchain_scripthash_get_history(const code& ec, if (!at_least(electrum::version::v1_1)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -133,13 +134,13 @@ void protocol_electrum::get_history(const system::hash_digest& hash) NOEXCEPT BC_ASSERT(stranded()); if (hash == null_hash) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } if (!archive().address_enabled()) { - send_code(error::not_implemented); + send_code(error::electrum::method_not_found); return; } @@ -169,7 +170,8 @@ void protocol_electrum::complete_get_history(const code& ec, if (ec) { - send_code(ec); + using namespace error::electrum; + send_code(translate(ec, daemon_error)); return; } @@ -191,7 +193,7 @@ void protocol_electrum::handle_blockchain_scripthash_get_mempool(const code& ec, if (!at_least(electrum::version::v1_1)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -206,13 +208,13 @@ void protocol_electrum::get_mempool(const system::hash_digest& hash) NOEXCEPT BC_ASSERT(stranded()); if (hash == null_hash) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } if (!archive().address_enabled()) { - send_code(error::not_implemented); + send_code(error::electrum::method_not_found); return; } @@ -241,7 +243,8 @@ void protocol_electrum::complete_get_mempool(const code& ec, if (ec) { - send_code(ec); + using namespace error::electrum; + send_code(translate(ec, daemon_error)); return; } @@ -262,7 +265,7 @@ void protocol_electrum::handle_blockchain_scripthash_list_unspent(const code& ec if (!at_least(electrum::version::v1_1)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -277,13 +280,13 @@ void protocol_electrum::list_unspent(const system::hash_digest& hash) NOEXCEPT BC_ASSERT(stranded()); if (hash == null_hash) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } if (!archive().address_enabled()) { - send_code(error::not_implemented); + send_code(error::electrum::method_not_found); return; } @@ -310,7 +313,8 @@ void protocol_electrum::complete_list_unspent(const code& ec, if (ec) { - send_code(ec); + using namespace error::electrum; + send_code(translate(ec, daemon_error)); return; } diff --git a/src/protocols/electrum/protocol_electrum_scriptpubkey.cpp b/src/protocols/electrum/protocol_electrum_scriptpubkey.cpp index 170e34ab..c8987a4a 100644 --- a/src/protocols/electrum/protocol_electrum_scriptpubkey.cpp +++ b/src/protocols/electrum/protocol_electrum_scriptpubkey.cpp @@ -43,21 +43,21 @@ void protocol_electrum::handle_blockchain_scriptpubkey_get_balance( if (!at_least(electrum::version::v1_7)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } data_chunk bytes{}; if (!decode_base16(bytes, scriptpubkey)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } chain::script script{ std::move(bytes), false }; if (!script.is_valid()) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -73,21 +73,21 @@ void protocol_electrum::handle_blockchain_scriptpubkey_get_history( if (!at_least(electrum::version::v1_7)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } data_chunk bytes{}; if (!decode_base16(bytes, scriptpubkey)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } chain::script script{ std::move(bytes), false }; if (!script.is_valid()) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -103,21 +103,21 @@ void protocol_electrum::handle_blockchain_scriptpubkey_get_mempool( if (!at_least(electrum::version::v1_7)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } data_chunk bytes{}; if (!decode_base16(bytes, scriptpubkey)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } chain::script script{ std::move(bytes), false }; if (!script.is_valid()) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -133,21 +133,21 @@ void protocol_electrum::handle_blockchain_scriptpubkey_list_unspent( if (!at_least(electrum::version::v1_7)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } data_chunk bytes{}; if (!decode_base16(bytes, scriptpubkey)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } chain::script script{ std::move(bytes), false }; if (!script.is_valid()) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -163,21 +163,21 @@ void protocol_electrum::handle_blockchain_scriptpubkey_subscribe( if (!at_least(electrum::version::v1_7)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } data_chunk bytes{}; if (!decode_base16(bytes, scriptpubkey)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } chain::script script{ std::move(bytes), false }; if (!script.is_valid()) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -193,21 +193,21 @@ void protocol_electrum::handle_blockchain_scriptpubkey_unsubscribe( if (!at_least(electrum::version::v1_7)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } data_chunk bytes{}; if (!decode_base16(bytes, scriptpubkey)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } chain::script script{ std::move(bytes), false }; if (!script.is_valid()) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } diff --git a/src/protocols/electrum/protocol_electrum_server.cpp b/src/protocols/electrum/protocol_electrum_server.cpp index 016c5088..07834bbf 100644 --- a/src/protocols/electrum/protocol_electrum_server.cpp +++ b/src/protocols/electrum/protocol_electrum_server.cpp @@ -41,13 +41,13 @@ void protocol_electrum::handle_server_add_peer(const code& ec, if (!at_least(electrum::version::v1_1)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } // This is an unsafe feature and server outbound connections are a bad idea. // Instead we rely strictly on a configured list servers to advertise. - send_code(error::not_implemented); + send_code(error::electrum::method_not_found); } void protocol_electrum::handle_server_banner(const code& ec, @@ -58,7 +58,7 @@ void protocol_electrum::handle_server_banner(const code& ec, if (!at_least(electrum::version::v1_0)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -73,7 +73,7 @@ void protocol_electrum::handle_server_donation_address(const code& ec, if (!at_least(electrum::version::v1_0)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -89,7 +89,7 @@ void protocol_electrum::handle_server_features(const code& ec, if (!at_least(electrum::version::v1_0)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -97,14 +97,14 @@ void protocol_electrum::handle_server_features(const code& ec, const auto genesis = query.to_confirmed(zero); if (genesis.is_terminal()) { - send_code(error::not_found); + send_code(error::electrum::daemon_error); return; } const auto hash = query.get_header_key(genesis); if (hash == null_hash) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } @@ -150,7 +150,7 @@ void protocol_electrum::handle_server_peers_subscribe(const code& ec, if (!at_least(electrum::version::v1_0)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -168,7 +168,7 @@ void protocol_electrum::handle_server_ping(const code& ec, if (!at_least(electrum::version::v1_2)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -180,7 +180,7 @@ void protocol_electrum::handle_server_ping(const code& ec, { if (!data.empty() || is_nonzero(pong_len)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } } @@ -192,7 +192,7 @@ void protocol_electrum::handle_server_ping(const code& ec, if (!to_integer(size, pong_len) || (size != data.length()) || !decode_base16(unused, data)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } diff --git a/src/protocols/electrum/protocol_electrum_subscribe.cpp b/src/protocols/electrum/protocol_electrum_subscribe.cpp index fdd2f9ca..aa0afa72 100644 --- a/src/protocols/electrum/protocol_electrum_subscribe.cpp +++ b/src/protocols/electrum/protocol_electrum_subscribe.cpp @@ -51,14 +51,14 @@ void protocol_electrum::handle_blockchain_scripthash_subscribe(const code& ec, if (!at_least(electrum::version::v1_1)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } hash_digest hash{}; if (!decode_hash(hash, scripthash)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -73,7 +73,7 @@ void protocol_electrum::scripthash_subscribe(const hash_digest& hash, if (!archive().address_enabled()) { - send_code(error::not_implemented); + send_code(error::electrum::method_not_found); return; } @@ -87,7 +87,7 @@ void protocol_electrum::do_scripthash_subscribe(const hash_digest& hash, BC_ASSERT(notification_strand_.running_in_this_thread()); hash_digest status{}; - code ec{ error::subscription_limit }; + code ec{ error::electrum::excessive_resource_usage }; if (address_subscriptions_.size() < options().maximum_subscriptions) { const auto at = address_subscriptions_.try_emplace(hash, @@ -120,7 +120,8 @@ void protocol_electrum::complete_scripthash_subscribe(const code& ec, if (ec) { - send_code(ec); + using namespace error::electrum; + send_code(translate(ec, daemon_error)); return; } @@ -142,14 +143,14 @@ void protocol_electrum::handle_blockchain_scripthash_unsubscribe(const code& ec, if (!at_least(electrum::version::v1_4_2)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } hash_digest hash{}; if (!decode_hash(hash, scripthash)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -164,7 +165,7 @@ void protocol_electrum::scripthash_unsubscribe( if (!archive().address_enabled()) { - send_code(error::not_implemented); + send_code(error::electrum::method_not_found); return; } diff --git a/src/protocols/electrum/protocol_electrum_transactions.cpp b/src/protocols/electrum/protocol_electrum_transactions.cpp index 6262ec5f..ab7c200e 100644 --- a/src/protocols/electrum/protocol_electrum_transactions.cpp +++ b/src/protocols/electrum/protocol_electrum_transactions.cpp @@ -45,7 +45,7 @@ void protocol_electrum::handle_blockchain_transaction_broadcast(const code& ec, if (!at_least(electrum::version::v1_0)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -53,7 +53,7 @@ void protocol_electrum::handle_blockchain_transaction_broadcast(const code& ec, const auto tx = to_shared(hexer, true); if (!tx->is_valid() || !hexer.is_exhausted()) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -70,7 +70,8 @@ void protocol_electrum::handle_blockchain_transaction_broadcast(const code& ec, return; } - send_code(fault); + using namespace error::electrum; + send_code(translate(fault, daemon_error)); } void protocol_electrum::handle_blockchain_transaction_broadcast_package( @@ -82,7 +83,7 @@ void protocol_electrum::handle_blockchain_transaction_broadcast_package( if (!at_least(electrum::version::v1_6)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -91,20 +92,20 @@ void protocol_electrum::handle_blockchain_transaction_broadcast_package( // experimental and better-suited for debugging." - do not support this. if (verbose) { - send_code(error::unsupported_argument); + send_code(error::electrum::bad_request); return; } if (!std::holds_alternative(raw_txs.value())) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } const auto& txs_hex = std::get(raw_txs.value()); if (txs_hex.empty()) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -117,7 +118,7 @@ void protocol_electrum::handle_blockchain_transaction_broadcast_package( { if (!std::holds_alternative(tx_hex.value())) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -125,7 +126,7 @@ void protocol_electrum::handle_blockchain_transaction_broadcast_package( const auto tx = to_shared(hexer, true); if (!tx->is_valid() || !hexer.is_exhausted()) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -160,14 +161,14 @@ void protocol_electrum::handle_blockchain_transaction_get(const code& ec, if ((!at_least(electrum::version::v1_0)) || (!at_least(electrum::version::v1_2) && verbose)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } hash_digest hash{}; if (!decode_hash(hash, tx_hash)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -175,7 +176,8 @@ void protocol_electrum::handle_blockchain_transaction_get(const code& ec, const auto link = query.to_tx(hash); if (link.is_terminal()) { - send_code(error::not_found); + // electrumx passes tx lookup to its daemon, failing as daemon error. + send_code(error::electrum::daemon_error); return; } @@ -186,7 +188,7 @@ void protocol_electrum::handle_blockchain_transaction_get(const code& ec, const auto tx = query.get_wire_tx(link, true); if (tx.empty()) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } @@ -198,7 +200,7 @@ void protocol_electrum::handle_blockchain_transaction_get(const code& ec, const auto tx = query.get_transaction(link, true); if (!tx) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } @@ -206,7 +208,7 @@ void protocol_electrum::handle_blockchain_transaction_get(const code& ec, value = value_from(bitcoind(*tx)); if (!value.is_object()) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } @@ -222,7 +224,7 @@ void protocol_electrum::handle_blockchain_transaction_get(const code& ec, if (height.is_terminal() || (block_hash == null_hash) || !query.get_timestamp(timestamp, block)) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } @@ -251,7 +253,7 @@ void protocol_electrum::handle_blockchain_transaction_get_merkle( if (!at_least(electrum::version::v1_4)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -259,7 +261,7 @@ void protocol_electrum::handle_blockchain_transaction_get_merkle( size_t block_height{}; if (!to_integer(block_height, height) || !decode_hash(hash, tx_hash)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -267,21 +269,21 @@ void protocol_electrum::handle_blockchain_transaction_get_merkle( const auto block_link = query.to_confirmed(block_height); if (block_link.is_terminal()) { - send_code(error::not_found); + send_code(error::electrum::bad_request); return; } auto hashes = query.get_tx_keys(block_link); if (hashes.empty()) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } const auto index = find_position(hashes, hash); if (is_negative(index)) { - send_code(error::not_found); + send_code(error::electrum::bad_request); return; } @@ -310,7 +312,7 @@ void protocol_electrum::handle_blockchain_transaction_id_from_position( if (!at_least(electrum::version::v1_4)) { - send_code(error::wrong_version); + send_code(error::electrum::bad_request); return; } @@ -319,7 +321,7 @@ void protocol_electrum::handle_blockchain_transaction_id_from_position( if (!to_integer(block_height, height) || !to_integer(position, tx_pos)) { - send_code(error::invalid_argument); + send_code(error::electrum::bad_request); return; } @@ -328,7 +330,7 @@ void protocol_electrum::handle_blockchain_transaction_id_from_position( const auto tx_link = query.get_position_tx(block_link, position); if (tx_link.is_terminal()) { - send_code(error::not_found); + send_code(error::electrum::bad_request); return; } @@ -336,7 +338,7 @@ void protocol_electrum::handle_blockchain_transaction_id_from_position( const auto hash = query.get_tx_key(tx_link); if (hash == null_hash) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } @@ -349,13 +351,13 @@ void protocol_electrum::handle_blockchain_transaction_id_from_position( auto hashes = query.get_tx_keys(block_link); if (hashes.empty()) { - send_code(error::server_error); + send_code(error::electrum::daemon_error); return; } if (position >= hashes.size()) { - send_code(error::not_found); + send_code(error::electrum::bad_request); return; } diff --git a/src/protocols/electrum/protocol_electrum_version.cpp b/src/protocols/electrum/protocol_electrum_version.cpp index 79c78d70..1c6790ea 100644 --- a/src/protocols/electrum/protocol_electrum_version.cpp +++ b/src/protocols/electrum/protocol_electrum_version.cpp @@ -101,7 +101,7 @@ void protocol_electrum_version::handle_server_version(const code& ec, if ((channel_->version() == electrum::version::v0_0) && (!set_client(client_name) || !set_version(protocol_version))) { - const auto reason = error::invalid_argument; + const auto reason = error::electrum::bad_request; send_code(reason, BIND(finished, _1, reason)); } else diff --git a/test/parsers/block_stats.cpp b/test/parsers/bitcoind_block_stats.cpp similarity index 94% rename from test/parsers/block_stats.cpp rename to test/parsers/bitcoind_block_stats.cpp index e0432c85..d3f996aa 100644 --- a/test/parsers/block_stats.cpp +++ b/test/parsers/bitcoind_block_stats.cpp @@ -18,7 +18,7 @@ */ #include "../test.hpp" -BOOST_AUTO_TEST_SUITE(block_stats_tests) +BOOST_AUTO_TEST_SUITE(bitcoind_block_stats_tests) using namespace system; using namespace system::chain; @@ -46,7 +46,7 @@ static block make_block(transactions&& txs) NOEXCEPT std::move(txs) }; } -BOOST_AUTO_TEST_CASE(block_stats__coinbase_only__no_fees) +BOOST_AUTO_TEST_CASE(bitcoind_block_stats__coinbase_only__no_fees) { const auto block = make_block({ make_coinbase() }); const auto stats = server::block_stats(block, 1, 40, test_subsidy); @@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(block_stats__coinbase_only__no_fees) BOOST_REQUIRE_EQUAL(std::get(stats.at("utxo_increase_actual").value()), 1); } -BOOST_AUTO_TEST_CASE(block_stats__two_paying__fee_statistics) +BOOST_AUTO_TEST_CASE(bitcoind_block_stats__two_paying__fee_statistics) { const auto block = make_block({ make_coinbase(), make_paying(100'000, 90'000), make_paying(50'000, 48'000) }); @@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(block_stats__two_paying__fee_statistics) } // Unspendable outputs are excluded from the actual utxo statistics. -BOOST_AUTO_TEST_CASE(block_stats__unspendable_output__excluded_from_actual) +BOOST_AUTO_TEST_CASE(bitcoind_block_stats__unspendable_output__excluded_from_actual) { const script unspendable{ operations{ operation{ opcode::op_return } } }; const auto block = make_block({ make_coinbase(unspendable) }); diff --git a/test/parsers/descriptor.cpp b/test/parsers/bitcoind_descriptor.cpp similarity index 84% rename from test/parsers/descriptor.cpp rename to test/parsers/bitcoind_descriptor.cpp index f6eef911..4b87b3b8 100644 --- a/test/parsers/descriptor.cpp +++ b/test/parsers/bitcoind_descriptor.cpp @@ -18,27 +18,27 @@ */ #include "../test.hpp" -BOOST_AUTO_TEST_SUITE(descriptor_tests) +BOOST_AUTO_TEST_SUITE(bitcoind_descriptor_tests) // Vectors from bitcoind (rpc example and descriptor tests). -BOOST_AUTO_TEST_CASE(descriptor__checksum__wpkh__expected) +BOOST_AUTO_TEST_CASE(bitcoind_descriptor__checksum__wpkh__expected) { BOOST_REQUIRE_EQUAL(server::descriptor_checksum("wpkh([d34db33f/84h/0h/0h]xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8PhqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKEu3oaqMSzhSrHMxyyoEAmUHQbY/0/*)"), "cjjspncu"); } -BOOST_AUTO_TEST_CASE(descriptor__checksum__sh_multi_2__expected) +BOOST_AUTO_TEST_CASE(bitcoind_descriptor__checksum__sh_multi_2__expected) { BOOST_REQUIRE_EQUAL(server::descriptor_checksum("sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))"), "tjg09x5t"); } -BOOST_AUTO_TEST_CASE(descriptor__checksum__sh_multi_3__expected) +BOOST_AUTO_TEST_CASE(bitcoind_descriptor__checksum__sh_multi_3__expected) { BOOST_REQUIRE_EQUAL(server::descriptor_checksum("sh(multi(3,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))"), "d4x0uxyv"); } // A character outside the descriptor character set has no checksum. -BOOST_AUTO_TEST_CASE(descriptor__checksum__invalid_character__empty) +BOOST_AUTO_TEST_CASE(bitcoind_descriptor__checksum__invalid_character__empty) { BOOST_REQUIRE(server::descriptor_checksum("raw(\x01)").empty()); } diff --git a/test/parsers/partial_merkle.cpp b/test/parsers/bitcoind_merkle.cpp similarity index 87% rename from test/parsers/partial_merkle.cpp rename to test/parsers/bitcoind_merkle.cpp index a1d46f48..f5874ff5 100644 --- a/test/parsers/partial_merkle.cpp +++ b/test/parsers/bitcoind_merkle.cpp @@ -70,33 +70,33 @@ static void verify_round_trip(size_t count, // round trip // ---------------------------------------------------------------------------- -BOOST_AUTO_TEST_CASE(partial_merkle__single_tx__matched__root) +BOOST_AUTO_TEST_CASE(bitcoind_merkle__single_tx__matched__root) { verify_round_trip(1, { 0 }); } -BOOST_AUTO_TEST_CASE(partial_merkle__seven_tx__two_matched__root_and_positions) +BOOST_AUTO_TEST_CASE(bitcoind_merkle__seven_tx__two_matched__root_and_positions) { verify_round_trip(7, { 1, 4 }); } -BOOST_AUTO_TEST_CASE(partial_merkle__eight_tx__interior_matched__root) +BOOST_AUTO_TEST_CASE(bitcoind_merkle__eight_tx__interior_matched__root) { verify_round_trip(8, { 0, 3, 7 }); } -BOOST_AUTO_TEST_CASE(partial_merkle__odd_tx__last_matched__root) +BOOST_AUTO_TEST_CASE(bitcoind_merkle__odd_tx__last_matched__root) { verify_round_trip(5, { 4 }); } -BOOST_AUTO_TEST_CASE(partial_merkle__large__scattered__root) +BOOST_AUTO_TEST_CASE(bitcoind_merkle__large__scattered__root) { verify_round_trip(100, { 0, 1, 50, 98, 99 }); } // A branch smaller than a single-tx tree extracts the leaf as the root. -BOOST_AUTO_TEST_CASE(partial_merkle__single_tx__is_leaf_root) +BOOST_AUTO_TEST_CASE(bitcoind_merkle__single_tx__is_leaf_root) { const auto txids = make_txids(1); data_chunk flags{}; @@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE(partial_merkle__single_tx__is_leaf_root) // malformed // ---------------------------------------------------------------------------- -BOOST_AUTO_TEST_CASE(partial_merkle__zero_tx__false) +BOOST_AUTO_TEST_CASE(bitcoind_merkle__zero_tx__false) { hash_digest root{}; hashes matched{}; @@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(partial_merkle__zero_tx__false) } // More branch hashes than transactions is malformed. -BOOST_AUTO_TEST_CASE(partial_merkle__excess_hashes__false) +BOOST_AUTO_TEST_CASE(bitcoind_merkle__excess_hashes__false) { hash_digest root{}; hashes matched{}; diff --git a/test/protocols/bitcoind/bitcoind_rpc.cpp b/test/protocols/bitcoind/bitcoind_rpc.cpp index dab7d78f..018cfb08 100644 --- a/test/protocols/bitcoind/bitcoind_rpc.cpp +++ b/test/protocols/bitcoind/bitcoind_rpc.cpp @@ -45,30 +45,33 @@ bool has_error(const boost::json::value& response) NOEXCEPT !response.at("error").is_null(); } -bool is_not_implemented(const boost::json::value& response) NOEXCEPT +// Codes are the bitcoind wire values, not our enumeration. +bool has_code(const boost::json::value& response, int64_t code) NOEXCEPT { return has_error(response) && - response.at("error").at("message").as_string() == "not_implemented"; + response.at("error").at("code").as_int64() == code; } -const std::vector rejected_methods +using method_code = std::pair; + +const std::vector rejected_methods { - "dumptxoutset", - "loadtxoutset", - "clearbanned", - "listbanned", - "setban", - "stop", - "descriptorprocesspsbt" + { "dumptxoutset", -32601 }, + { "loadtxoutset", -32601 }, + { "clearbanned", -20 }, + { "listbanned", -20 }, + { "setban", -20 }, + { "stop", -32601 }, + { "descriptorprocesspsbt", -32601 } }; -const std::vector wip_methods +const std::vector wip_methods { - "getblockfrompeer", - "preciousblock", - "disconnectnode", - "exportasmap", - "getaddednodeinfo", + { "getblockfrompeer", -32601 }, + { "preciousblock", -32601 }, + { "disconnectnode", -32601 }, + { "exportasmap", -32601 }, + { "getaddednodeinfo", -24 } }; std::string as_text(const boost::json::value& value) NOEXCEPT @@ -157,23 +160,23 @@ const std::vector scope_methods "enumeratesigners" }; -const std::vector pending_methods -{ - "getmempoolancestors", - "getmempoolcluster", - "getmempooldescendants", - "getmempoolentry", - "getmempoolinfo", - "getrawmempool", - "gettxspendingprevout", - "importmempool", - "abortprivatebroadcast", - "getprivatebroadcastinfo", - "submitpackage", - "getblocktemplate", - "getprioritisedtransactions", - "prioritisetransaction", - "estimatesmartfee" +const std::vector pending_methods +{ + { "getmempoolancestors", -33 }, + { "getmempoolcluster", -33 }, + { "getmempooldescendants", -33 }, + { "getmempoolentry", -33 }, + { "getmempoolinfo", -33 }, + { "getrawmempool", -33 }, + { "gettxspendingprevout", -33 }, + { "importmempool", -33 }, + { "abortprivatebroadcast", -32601 }, + { "getprivatebroadcastinfo", -32601 }, + { "submitpackage", -33 }, + { "getblocktemplate", -33 }, + { "getprioritisedtransactions", -33 }, + { "prioritisetransaction", -33 }, + { "estimatesmartfee", -32603 } }; } // namespace @@ -247,10 +250,16 @@ BOOST_AUTO_TEST_CASE(bitcoind_rpc__getblock__block9_verbosity3__tx_objects) BOOST_REQUIRE(!tx.at(0).as_object().contains("fee")); } -BOOST_AUTO_TEST_CASE(bitcoind_rpc__getblock__verbosity4__invalid) +BOOST_AUTO_TEST_CASE(bitcoind_rpc__getblock__verbosity4__clamped_tx_objects) { const auto response = rpc("getblock", hash_param(test::block9_hash, "4")); - REQUIRE_NO_THROW_TRUE(response.as_object().contains("error")); + REQUIRE_NO_THROW_TRUE(response.at("result").at("tx").at(0).is_object()); +} + +BOOST_AUTO_TEST_CASE(bitcoind_rpc__getblock__negative_verbosity__clamped_hex) +{ + const auto response = rpc("getblock", hash_param(test::block9_hash, "-1")); + REQUIRE_NO_THROW_TRUE(response.at("result").is_string()); } BOOST_AUTO_TEST_CASE(bitcoind_rpc__getblockchaininfo__ten_block_store__expected) @@ -335,11 +344,18 @@ BOOST_AUTO_TEST_CASE(bitcoind_rpc__getrawtransaction__coinbase_verbosity_two__no BOOST_REQUIRE(!result.as_object().contains("fee")); } -BOOST_AUTO_TEST_CASE(bitcoind_rpc__getrawtransaction__excess_verbosity__error) +BOOST_AUTO_TEST_CASE(bitcoind_rpc__getrawtransaction__excess_verbosity__clamped_verbose) { const auto txid = test::block1.transactions_ptr()->front()->hash(false); const auto response = rpc("getrawtransaction", hash_param(txid, "3")); - BOOST_REQUIRE(has_error(response)); + REQUIRE_NO_THROW_TRUE(response.at("result").at("vin").is_array()); +} + +BOOST_AUTO_TEST_CASE(bitcoind_rpc__getrawtransaction__negative_verbosity__clamped_hex) +{ + const auto txid = test::block1.transactions_ptr()->front()->hash(false); + const auto response = rpc("getrawtransaction", hash_param(txid, "-1")); + REQUIRE_NO_THROW_TRUE(response.at("result").is_string()); } BOOST_AUTO_TEST_CASE(bitcoind_rpc__getrawtransaction__unknown_txid__error) @@ -360,6 +376,23 @@ BOOST_AUTO_TEST_CASE(bitcoind_rpc__sendrawtransaction__malformed__error) BOOST_REQUIRE(has_error(response)); } +BOOST_AUTO_TEST_CASE(bitcoind_rpc__sendrawtransaction__confirmed_unspent__verify_already_in_utxo_set) +{ + const auto tx0 = encode_base16(test::genesis.transactions_ptr()->front()->to_data(true)); + const auto response = rpc("sendrawtransaction", "[\"" + tx0 + "\"]"); + BOOST_REQUIRE_MESSAGE(has_code(response, -27), response); +} + +BOOST_AUTO_TEST_CASE(bitcoind_rpc__sendrawtransaction__unknown_inputs__verify_error) +{ + const chain::input input{ chain::point{ one_hash, 0 }, {}, 0xffffffff }; + const chain::output output{ 1, chain::script{ chain::script::to_pay_key_hash_pattern({ 0x42 }) } }; + const chain::transaction missing{ 1, { input }, { output }, 0 }; + const auto hex = encode_base16(missing.to_data(true)); + const auto response = rpc("sendrawtransaction", "[\"" + hex + "\"]"); + BOOST_REQUIRE_MESSAGE(has_code(response, -25), response); +} + // control, mining, rawtransactions, util (moved from btcd) // ---------------------------------------------------------------------------- @@ -476,6 +509,16 @@ BOOST_AUTO_TEST_CASE(bitcoind_rpc__decodescript__p2kh__descriptor_and_segwit) BOOST_REQUIRE(segwit.as_object().contains("p2sh-segwit")); } +BOOST_AUTO_TEST_CASE(bitcoind_rpc__decodescript__undecodable__nonstandard) +{ + const auto response = rpc("decodescript", "[\"01\"]"); + const auto& result = response.at("result"); + BOOST_REQUIRE_EQUAL(result.at("type").as_string(), "nonstandard"); + BOOST_REQUIRE_EQUAL(result.at("desc").as_string().subview(0, 8), "raw(01)#"); + BOOST_REQUIRE(!result.as_object().contains("p2sh")); + BOOST_REQUIRE(!result.as_object().contains("segwit")); +} + BOOST_AUTO_TEST_CASE(bitcoind_rpc__decodescript__witness_program__no_segwit) { const auto response = rpc("decodescript", "[\"0014751e76e8199196d454941c45d1b3a323f1433bd6\"]"); @@ -577,6 +620,23 @@ BOOST_AUTO_TEST_CASE(bitcoind_rpc__testmempoolaccept__empty__error) BOOST_REQUIRE(has_error(response)); } +BOOST_AUTO_TEST_CASE(bitcoind_rpc__testmempoolaccept__coinbase__coinbase_token) +{ + const auto tx0 = encode_base16(test::genesis.transactions_ptr()->front()->to_data(true)); + const auto response = rpc("testmempoolaccept", "[[\"" + tx0 + "\"]]"); + BOOST_REQUIRE_EQUAL(response.at("result").at(0).at("reject-reason").as_string(), "coinbase"); +} + +BOOST_AUTO_TEST_CASE(bitcoind_rpc__testmempoolaccept__unknown_inputs__missingorspent_token) +{ + const chain::input input{ chain::point{ one_hash, 0 }, {}, 0xffffffff }; + const chain::output output{ 1, chain::script{ chain::script::to_pay_key_hash_pattern({ 0x42 }) } }; + const chain::transaction missing{ 1, { input }, { output }, 0 }; + const auto hex = encode_base16(missing.to_data(true)); + const auto response = rpc("testmempoolaccept", "[[\"" + hex + "\"]]"); + BOOST_REQUIRE_EQUAL(response.at("result").at(0).at("reject-reason").as_string(), "bad-txns-inputs-missingorspent"); +} + // network // ---------------------------------------------------------------------------- @@ -609,35 +669,35 @@ BOOST_AUTO_TEST_CASE(bitcoind_rpc__not_implemented__error) BOOST_REQUIRE_MESSAGE(has_error(rpc(method, params)), method); } -BOOST_AUTO_TEST_CASE(bitcoind_rpc__rejected__not_implemented) +BOOST_AUTO_TEST_CASE(bitcoind_rpc__rejected__expected_code) { - for (const auto& method: rejected_methods) + for (const auto& [method, code]: rejected_methods) { - BOOST_REQUIRE_MESSAGE(is_not_implemented(rpc(method, "[]")), method); + BOOST_REQUIRE_MESSAGE(has_code(rpc(method, "[]"), code), method); } } -BOOST_AUTO_TEST_CASE(bitcoind_rpc__wip__not_implemented) +BOOST_AUTO_TEST_CASE(bitcoind_rpc__wip__expected_code) { - for (const auto& method: wip_methods) + for (const auto& [method, code]: wip_methods) { - BOOST_REQUIRE_MESSAGE(is_not_implemented(rpc(method, "[]")), method); + BOOST_REQUIRE_MESSAGE(has_code(rpc(method, "[]"), code), method); } } -BOOST_AUTO_TEST_CASE(bitcoind_rpc__scope__not_implemented) +BOOST_AUTO_TEST_CASE(bitcoind_rpc__scope__method_not_found) { for (const auto& method: scope_methods) { - BOOST_REQUIRE_MESSAGE(is_not_implemented(rpc(method, "[]")), method); + BOOST_REQUIRE_MESSAGE(has_code(rpc(method, "[]"), -32601), method); } } -BOOST_AUTO_TEST_CASE(bitcoind_rpc__pending__not_implemented) +BOOST_AUTO_TEST_CASE(bitcoind_rpc__pending__expected_code) { - for (const auto& method: pending_methods) + for (const auto& [method, code]: pending_methods) { - BOOST_REQUIRE_MESSAGE(is_not_implemented(rpc(method, "[]")), method); + BOOST_REQUIRE_MESSAGE(has_code(rpc(method, "[]"), code), method); } } @@ -1442,6 +1502,14 @@ BOOST_AUTO_TEST_CASE(bitcoind_rpc__submitblock__existing_block__duplicate) BOOST_REQUIRE_EQUAL(as_text(response.at("result")), "duplicate"); } +BOOST_AUTO_TEST_CASE(bitcoind_rpc__submitblock__unknown_header__prev_blk_not_found_token) +{ + auto data = test::block1.to_data(true); + data[76]++; + const auto response = rpc("submitblock", "[\"" + encode_base16(data) + "\"]"); + BOOST_REQUIRE_EQUAL(response.at("result").as_string(), "prev-blk-not-found"); +} + BOOST_AUTO_TEST_CASE(bitcoind_rpc__submitblock__garbage__invalid) { const auto response = rpc("submitblock", "[\"deadbeef\"]"); @@ -1635,6 +1703,48 @@ BOOST_AUTO_TEST_CASE(bitcoind_rpc__websocket__wrong_username_upgrade__refused) BOOST_AUTO_TEST_SUITE_END() +// scoped credential +// ---------------------------------------------------------------------------- + +BOOST_FIXTURE_TEST_SUITE(bitcoind_scoped_credential_tests, + bitcoind_scoped_credential_setup_fixture) + +BOOST_AUTO_TEST_CASE(bitcoind_scoped_credential__post_listed_method__ok) +{ + const auto result = rpc_status(BITCOIND_TEST_SCOPED_METHOD, BITCOIND_TEST_USERNAME, BITCOIND_TEST_PASSWORD); + BOOST_REQUIRE_EQUAL(result, status::ok); +} + +BOOST_AUTO_TEST_CASE(bitcoind_scoped_credential__post_unlisted_method__forbidden) +{ + const auto result = rpc_status("getbestblockhash", BITCOIND_TEST_USERNAME, BITCOIND_TEST_PASSWORD); + BOOST_REQUIRE_EQUAL(result, status::forbidden); +} + +BOOST_AUTO_TEST_CASE(bitcoind_scoped_credential__post_unknown_method__forbidden) +{ + const auto result = rpc_status("nosuchmethod", BITCOIND_TEST_USERNAME, BITCOIND_TEST_PASSWORD); + BOOST_REQUIRE_EQUAL(result, status::forbidden); +} + +BOOST_AUTO_TEST_CASE(bitcoind_scoped_credential__websocket_listed_method__result) +{ + BOOST_REQUIRE(!ws_upgrade(BITCOIND_TEST_USERNAME, BITCOIND_TEST_PASSWORD)); + + const auto response = ws_rpc(BITCOIND_TEST_SCOPED_METHOD); + BOOST_REQUIRE_EQUAL(response.at("result").as_int64(), 9); +} + +BOOST_AUTO_TEST_CASE(bitcoind_scoped_credential__websocket_unlisted_method__dropped) +{ + BOOST_REQUIRE(!ws_upgrade(BITCOIND_TEST_USERNAME, BITCOIND_TEST_PASSWORD)); + + const auto response = ws_rpc_dropped("getbestblockhash"); + REQUIRE_NO_THROW_TRUE(response.at("dropped").as_bool()); +} + +BOOST_AUTO_TEST_SUITE_END() + // witness // ---------------------------------------------------------------------------- diff --git a/test/protocols/bitcoind/bitcoind_setup_fixture.cpp b/test/protocols/bitcoind/bitcoind_setup_fixture.cpp index 3baf856a..5208d5d9 100644 --- a/test/protocols/bitcoind/bitcoind_setup_fixture.cpp +++ b/test/protocols/bitcoind/bitcoind_setup_fixture.cpp @@ -162,6 +162,27 @@ boost::json::value bitcoind_setup_fixture::rpc_body(std::string_view body) test::parse_json(response.body()); } +bitcoind_setup_fixture::status +bitcoind_setup_fixture::rpc_status(std::string_view method, + const std::string& username, const std::string& password) +{ + std::ostringstream body{}; + body << R"({"jsonrpc":"2.0","id":0,"method":")" << method << R"(","params":[]})"; + + const std::string plain{ username + ":" + password }; + const auto credential = "Basic " + system::encode_base64(plain); + auto request = create_post("/", body.str()); + request.set(http::field::authorization, credential); + http::write(socket_, request); + + flat_buffer buffer{}; + network::boost_code ec{}; + http::response response{}; + http::read(socket_, buffer, response, ec); + BOOST_CHECK_MESSAGE(!ec, ec.message()); + return response.result(); +} + network::boost_code bitcoind_setup_fixture::ws_upgrade() { network::boost_code ec{}; @@ -222,6 +243,24 @@ boost::json::value bitcoind_setup_fixture::ws_rpc(std::string_view method, return test::parse_json(buffers_to_string(buffer.data())); } +boost::json::value bitcoind_setup_fixture::ws_rpc_dropped( + std::string_view method, std::string_view params) +{ + std::ostringstream body{}; + body << R"({"jsonrpc":"2.0","id":0,"method":")" << method << R"(","params":)" << params << "}"; + + const auto frame = body.str(); + network::boost_code ec{}; + BOOST_CHECK(websocket_.has_value()); + websocket_.value().write(net::buffer(frame), ec); + BOOST_CHECK_MESSAGE(!ec, ec.message()); + + flat_buffer buffer{}; + websocket_.value().read(buffer, ec); + return ec ? boost::json::parse(R"({"dropped":true})") : + test::parse_json(buffers_to_string(buffer.data())); +} + bitcoind_setup_fixture::status bitcoind_setup_fixture::rest_status(std::string_view target) { diff --git a/test/protocols/bitcoind/bitcoind_setup_fixture.hpp b/test/protocols/bitcoind/bitcoind_setup_fixture.hpp index 6dbacb0d..891bc927 100644 --- a/test/protocols/bitcoind/bitcoind_setup_fixture.hpp +++ b/test/protocols/bitcoind/bitcoind_setup_fixture.hpp @@ -25,6 +25,7 @@ #define BITCOIND_ENDPOINT "127.0.0.1:65003" #define BITCOIND_TEST_USERNAME "user" #define BITCOIND_TEST_PASSWORD "pass" +#define BITCOIND_TEST_SCOPED_METHOD "getblockcount" struct bitcoind_setup_fixture { @@ -45,6 +46,10 @@ struct bitcoind_setup_fixture // the parsed json response, or {"dropped":true} if the channel dropped. boost::json::value rpc_body(std::string_view body); + // As rpc(), with basic authorization, returning only the http status. + status rpc_status(std::string_view method, const std::string& username, + const std::string& password); + // Upgrade the connection to websocket (no further http requests). network::boost_code ws_upgrade(); @@ -56,6 +61,10 @@ struct bitcoind_setup_fixture boost::json::value ws_rpc(std::string_view method, std::string_view params="[]"); + // As ws_rpc(), returning {"dropped":true} if the channel dropped. + boost::json::value ws_rpc_dropped(std::string_view method, + std::string_view params="[]"); + // bitcoind REST over HTTP GET (target under "/rest/..."). status rest_status(std::string_view target); @@ -117,6 +126,27 @@ struct bitcoind_credentialed_setup_fixture } }; +// Configured with a credential scoped to a single method -- for tests that +// verify permitted() refuses at the transport (post 403, websocket stop). +struct bitcoind_scoped_credential_setup_fixture + : bitcoind_setup_fixture +{ + inline bitcoind_scoped_credential_setup_fixture() + : bitcoind_setup_fixture([](test::query_t& query) + { + return test::setup_ten_block_store(query); + }, [](configuration& config) + { + config.server.bitcoind.credentials = + { + { BITCOIND_TEST_USERNAME ":" BITCOIND_TEST_PASSWORD ":" + BITCOIND_TEST_SCOPED_METHOD } + }; + }) + { + } +}; + // Configured with no currency window -- for tests of state that requires the // confirmed top to be current (the test store is historical). struct bitcoind_current_setup_fixture diff --git a/test/protocols/btcd/btcd_rpc.cpp b/test/protocols/btcd/btcd_rpc.cpp index 7b2e5c4f..94e1160e 100644 --- a/test/protocols/btcd/btcd_rpc.cpp +++ b/test/protocols/btcd/btcd_rpc.cpp @@ -27,6 +27,17 @@ static const code subscription_limit{ server::error::subscription_limit }; static const code unauthorized{ network::error::unauthorized }; static const code unexpected_method{ network::error::unexpected_method }; +// Inherited bitcoind paths send bitcoind codes (btcjson uses the same values). +static const code method_not_found{ server::error::bitcoind::method_not_found }; +static const code deserialization{ server::error::bitcoind::deserialization_error }; + +// btcd reports unimplemented and misc alike as -1. +static const code unimplemented{ server::error::btcd::unimplemented }; +static const code misc_error{ server::error::btcd::misc_error }; +static const code invalid_parameter{ server::error::btcd::invalid_parameter }; +static const code invalid_params{ server::error::btcd::invalid_params }; +static const code block_not_found{ server::error::btcd::invalid_address_or_key }; + // mock_block10 chains onto block9 and pays found_address from its second // transaction only (its other outputs pay distinct key/script hashes), so a // filter watching found_address matches exactly one of its transactions. @@ -63,12 +74,12 @@ BOOST_AUTO_TEST_CASE(btcd_rpc__authenticate__no_credential_configured__unauthori BOOST_REQUIRE_EQUAL(result, unauthorized.value()); } -BOOST_AUTO_TEST_CASE(btcd_rpc__authenticate__http_post__unexpected_method) +BOOST_AUTO_TEST_CASE(btcd_rpc__authenticate__http_post__method_not_found) { // authenticate is websocket-only (as btcd): not part of the post surface. const auto response = http_rpc("authenticate", R"(["user","pass"])"); REQUIRE_NO_THROW_TRUE(response.at("error").is_object()); - BOOST_REQUIRE_EQUAL(response.at("error").at("code").as_int64(), unexpected_method.value()); + BOOST_REQUIRE_EQUAL(response.at("error").at("code").as_int64(), method_not_found.value()); } BOOST_AUTO_TEST_CASE(btcd_rpc__help__default__method_list) @@ -87,7 +98,7 @@ BOOST_AUTO_TEST_CASE(btcd_rpc__session__default__returns_id) BOOST_AUTO_TEST_CASE(btcd_rpc__stop__default__not_implemented) { - BOOST_REQUIRE_EQUAL(rpc_error("stop"), not_implemented.value()); + BOOST_REQUIRE_EQUAL(rpc_error("stop"), unimplemented.value()); } // getters @@ -178,10 +189,10 @@ BOOST_AUTO_TEST_CASE(btcd_rpc__decoderawtransaction__block1_coinbase__expected_t BOOST_REQUIRE_EQUAL(as_text(response.at("result").at("txid")), encode_hash(coinbase.hash(false))); } -BOOST_AUTO_TEST_CASE(btcd_rpc__decoderawtransaction__malformed_hex__invalid_argument) +BOOST_AUTO_TEST_CASE(btcd_rpc__decoderawtransaction__malformed_hex__deserialization) { const auto result = rpc_error("decoderawtransaction", R"(["not-hex"])"); - BOOST_REQUIRE_EQUAL(result, invalid_argument.value()); + BOOST_REQUIRE_EQUAL(result, deserialization.value()); } BOOST_AUTO_TEST_CASE(btcd_rpc__decodescript__pay_public_key__pubkey) @@ -239,12 +250,12 @@ BOOST_AUTO_TEST_CASE(btcd_rpc__stopnotifyblocks__subscribed__null_result) BOOST_AUTO_TEST_CASE(btcd_rpc__notifynewtransactions__default__not_implemented) { - BOOST_REQUIRE_EQUAL(rpc_error("notifynewtransactions", "[false]"), not_implemented.value()); + BOOST_REQUIRE_EQUAL(rpc_error("notifynewtransactions", "[false]"), unimplemented.value()); } BOOST_AUTO_TEST_CASE(btcd_rpc__stopnotifynewtransactions__default__not_implemented) { - BOOST_REQUIRE_EQUAL(rpc_error("stopnotifynewtransactions"), not_implemented.value()); + BOOST_REQUIRE_EQUAL(rpc_error("stopnotifynewtransactions"), unimplemented.value()); } // filters @@ -261,7 +272,7 @@ BOOST_AUTO_TEST_CASE(btcd_rpc__loadtxfilter__valid_address__null_result) BOOST_AUTO_TEST_CASE(btcd_rpc__loadtxfilter__invalid_address__invalid_argument) { const auto result = rpc_error("loadtxfilter", (boost_format(R"([true,["%1%"],[]])") % bogus_address).str()); - BOOST_REQUIRE_EQUAL(result, invalid_argument.value()); + BOOST_REQUIRE_EQUAL(result, invalid_parameter.value()); } BOOST_AUTO_TEST_CASE(btcd_rpc__loadtxfilter__valid_outpoint__null_result) @@ -274,7 +285,7 @@ BOOST_AUTO_TEST_CASE(btcd_rpc__loadtxfilter__valid_outpoint__null_result) BOOST_AUTO_TEST_CASE(btcd_rpc__loadtxfilter__malformed_outpoint__invalid_argument) { const auto result = rpc_error("loadtxfilter", R"([true,[],[{"hash":"00"}]])"); - BOOST_REQUIRE_EQUAL(result, invalid_argument.value()); + BOOST_REQUIRE_EQUAL(result, invalid_parameter.value()); } BOOST_AUTO_TEST_CASE(btcd_rpc__rescanblocks__unknown_hash__not_found) @@ -282,7 +293,7 @@ BOOST_AUTO_TEST_CASE(btcd_rpc__rescanblocks__unknown_hash__not_found) // 'blockhashes' is one positional arg that is itself an array, so the // wire params need double-wrapping: [[...]], not [...]. const auto result = rpc_error("rescanblocks", (boost_format(R"([["%1%"]])") % encode_hash(null_hash)).str()); - BOOST_REQUIRE_EQUAL(result, not_found.value()); + BOOST_REQUIRE_EQUAL(result, block_not_found.value()); } BOOST_AUTO_TEST_CASE(btcd_rpc__rescanblocks__no_filter_match__empty_result) @@ -337,28 +348,28 @@ BOOST_AUTO_TEST_CASE(btcd_rpc__filteredblockconnected__address_match__delivered) BOOST_AUTO_TEST_CASE(btcd_rpc__notifyreceived__default__not_implemented) { - BOOST_REQUIRE_EQUAL(rpc_error("notifyreceived", "[[]]"), not_implemented.value()); + BOOST_REQUIRE_EQUAL(rpc_error("notifyreceived", "[[]]"), unimplemented.value()); } BOOST_AUTO_TEST_CASE(btcd_rpc__stopnotifyreceived__default__not_implemented) { - BOOST_REQUIRE_EQUAL(rpc_error("stopnotifyreceived", "[[]]"), not_implemented.value()); + BOOST_REQUIRE_EQUAL(rpc_error("stopnotifyreceived", "[[]]"), unimplemented.value()); } BOOST_AUTO_TEST_CASE(btcd_rpc__notifyspent__default__not_implemented) { - BOOST_REQUIRE_EQUAL(rpc_error("notifyspent", "[[]]"), not_implemented.value()); + BOOST_REQUIRE_EQUAL(rpc_error("notifyspent", "[[]]"), unimplemented.value()); } BOOST_AUTO_TEST_CASE(btcd_rpc__stopnotifyspent__default__not_implemented) { - BOOST_REQUIRE_EQUAL(rpc_error("stopnotifyspent", "[[]]"), not_implemented.value()); + BOOST_REQUIRE_EQUAL(rpc_error("stopnotifyspent", "[[]]"), unimplemented.value()); } BOOST_AUTO_TEST_CASE(btcd_rpc__rescan__unknown_beginblock__not_found) { const auto result = rpc_error("rescan", (boost_format(R"(["%1%",[],[],""])") % encode_hash(null_hash)).str()); - BOOST_REQUIRE_EQUAL(result, not_found.value()); + BOOST_REQUIRE_EQUAL(result, block_not_found.value()); } BOOST_AUTO_TEST_CASE(btcd_rpc__rescan__no_addresses_or_outpoints__rescan_finished) @@ -379,7 +390,7 @@ BOOST_AUTO_TEST_CASE(btcd_rpc__rescan__with_addresses__not_implemented) { const auto request = R"(["%1%",["%2%"],[],""])"; const auto result = rpc_error("rescan", (boost_format(request) % block9 % found_address).str()); - BOOST_REQUIRE_EQUAL(result, not_implemented.value()); + BOOST_REQUIRE_EQUAL(result, unimplemented.value()); } // bitcoind interface methods (bridged into the ws dispatcher) @@ -403,9 +414,9 @@ BOOST_AUTO_TEST_CASE(btcd_rpc__response__sequential_requests__id_matches_request BOOST_REQUIRE_EQUAL(r1.at("id").as_int64(), 1); } -BOOST_AUTO_TEST_CASE(btcd_rpc__unknown_method__default__unexpected_method) +BOOST_AUTO_TEST_CASE(btcd_rpc__unknown_method__default__method_not_found) { - BOOST_REQUIRE_EQUAL(rpc_error("nosuchmethod"), unexpected_method.value()); + BOOST_REQUIRE_EQUAL(rpc_error("nosuchmethod"), method_not_found.value()); // The connection survives an unknown method (as btcd). const auto follow_up = rpc("session"); @@ -463,7 +474,7 @@ BOOST_AUTO_TEST_CASE(btcd_limited_filter__loadtxfilter__over_limit__subscription // The fixture allows one watch; the second address exceeds it. const auto request = R"([true,["%1%","%2%"],[]])"; const auto result = rpc_error("loadtxfilter", (boost_format(request) % found_address % other_address).str()); - BOOST_REQUIRE_EQUAL(result, subscription_limit.value()); + BOOST_REQUIRE_EQUAL(result, misc_error.value()); } BOOST_AUTO_TEST_SUITE_END() @@ -478,7 +489,7 @@ BOOST_AUTO_TEST_CASE(btcd_no_index__loadtxfilter__address__not_implemented) { const auto request = R"([true,["%1%"],[]])"; const auto result = rpc_error("loadtxfilter", (boost_format(request) % found_address).str()); - BOOST_REQUIRE_EQUAL(result, not_implemented.value()); + BOOST_REQUIRE_EQUAL(result, unimplemented.value()); } BOOST_AUTO_TEST_CASE(btcd_no_index__loadtxfilter__outpoint_only__null_result) @@ -493,7 +504,7 @@ BOOST_AUTO_TEST_CASE(btcd_no_index__rescanblocks__any__not_implemented) { const auto request = R"([["%1%"]])"; const auto result = rpc_error("rescanblocks", (boost_format(request) % encode_hash(test::block1_hash)).str()); - BOOST_REQUIRE_EQUAL(result, not_implemented.value()); + BOOST_REQUIRE_EQUAL(result, unimplemented.value()); } BOOST_AUTO_TEST_SUITE_END() @@ -514,12 +525,12 @@ BOOST_AUTO_TEST_CASE(btcd_scoped_credential__session__listed_method__permitted) REQUIRE_NO_THROW_TRUE(session.at("result").is_object()); } -BOOST_AUTO_TEST_CASE(btcd_scoped_credential__notifyblocks__unlisted_method__unauthorized) +BOOST_AUTO_TEST_CASE(btcd_scoped_credential__notifyblocks__unlisted_method__invalid_params) { BOOST_REQUIRE(authenticate()); // notifyblocks is implemented, so rejection is permitted()'s doing. - BOOST_REQUIRE_EQUAL(rpc_error("notifyblocks"), unauthorized.value()); + BOOST_REQUIRE_EQUAL(rpc_error("notifyblocks"), invalid_params.value()); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/protocols/electrum/electrum_addresses.cpp b/test/protocols/electrum/electrum_addresses.cpp index 79aac572..9c1fa96e 100644 --- a/test/protocols/electrum/electrum_addresses.cpp +++ b/test/protocols/electrum/electrum_addresses.cpp @@ -20,9 +20,9 @@ #include "electrum_setup_fixture.hpp" using namespace system; -static const code not_found{ server::error::not_found }; -static const code wrong_version{ server::error::wrong_version }; -static const code invalid_argument{ server::error::invalid_argument }; +static const code not_found{ server::error::electrum::bad_request }; +static const code wrong_version{ server::error::electrum::bad_request }; +static const code invalid_argument{ server::error::electrum::bad_request }; static const std::string bogus_address{ "1JqDybm2nWTENrHvMyafbSXXtTk5Uv5QAn" }; static const std::string found_address{ "1BaMPFdqMUQ46BV8iRcwbVfsam57oBLMM" }; diff --git a/test/protocols/electrum/electrum_disabled.cpp b/test/protocols/electrum/electrum_disabled.cpp index 6e73cc6f..80feefb5 100644 --- a/test/protocols/electrum/electrum_disabled.cpp +++ b/test/protocols/electrum/electrum_disabled.cpp @@ -20,8 +20,8 @@ #include "electrum_setup_fixture.hpp" using namespace system; -static const code not_implemented{ server::error::not_implemented }; -static const code invalid_argument{ server::error::invalid_argument }; +static const code not_implemented{ server::error::electrum::method_not_found }; +static const code invalid_argument{ server::error::electrum::bad_request }; static const std::string bogus_address{ "1JqDybm2nWTENrHvMyafbSXXtTk5Uv5QAn" }; static const std::string bogus_scripthash{ "9c2c84a6cf9809e08af19557e28d38257e6fee6981269760637a5f9dfb000b05" }; static const chain::script bogus{ chain::script::to_pay_key_hash_pattern({ 0x42 }) }; diff --git a/test/protocols/electrum/electrum_fees.cpp b/test/protocols/electrum/electrum_fees.cpp index dc57740e..30857652 100644 --- a/test/protocols/electrum/electrum_fees.cpp +++ b/test/protocols/electrum/electrum_fees.cpp @@ -22,9 +22,9 @@ BOOST_FIXTURE_TEST_SUITE(electrum_tests, electrum_ten_block_setup_fixture) using namespace system; -static const code wrong_version{ server::error::wrong_version }; -static const code not_implemented{ server::error::not_implemented }; -static const code invalid_argument{ server::error::invalid_argument }; +static const code wrong_version{ server::error::electrum::bad_request }; +static const code not_implemented{ server::error::electrum::method_not_found }; +static const code invalid_argument{ server::error::electrum::bad_request }; // blockchain.estimatefee diff --git a/test/protocols/electrum/electrum_headers.cpp b/test/protocols/electrum/electrum_headers.cpp index 82645478..57b50fa1 100644 --- a/test/protocols/electrum/electrum_headers.cpp +++ b/test/protocols/electrum/electrum_headers.cpp @@ -22,10 +22,10 @@ BOOST_FIXTURE_TEST_SUITE(electrum_tests, electrum_ten_block_setup_fixture) using namespace system; -static const code not_found{ server::error::not_found }; -static const code wrong_version{ server::error::wrong_version }; -static const code target_overflow{ server::error::target_overflow }; -static const code invalid_argument{ server::error::invalid_argument }; +static const code not_found{ server::error::electrum::bad_request }; +static const code wrong_version{ server::error::electrum::bad_request }; +static const code target_overflow{ server::error::electrum::bad_request }; +static const code invalid_argument{ server::error::electrum::bad_request }; // blockchain.numblocks.subscribe diff --git a/test/protocols/electrum/electrum_mempool.cpp b/test/protocols/electrum/electrum_mempool.cpp index 0bb683bd..247734dd 100644 --- a/test/protocols/electrum/electrum_mempool.cpp +++ b/test/protocols/electrum/electrum_mempool.cpp @@ -22,8 +22,8 @@ BOOST_FIXTURE_TEST_SUITE(electrum_tests, electrum_ten_block_setup_fixture) using namespace system; -static const code wrong_version{ server::error::wrong_version }; -static const code not_implemented{ server::error::not_implemented }; +static const code wrong_version{ server::error::electrum::bad_request }; +static const code not_implemented{ server::error::electrum::method_not_found }; // mempool.get_fee_histogram diff --git a/test/protocols/electrum/electrum_outpoints.cpp b/test/protocols/electrum/electrum_outpoints.cpp index 72e95ad0..e0f426b8 100644 --- a/test/protocols/electrum/electrum_outpoints.cpp +++ b/test/protocols/electrum/electrum_outpoints.cpp @@ -22,9 +22,9 @@ BOOST_FIXTURE_TEST_SUITE(electrum_tests, electrum_ten_block_setup_fixture) using namespace system; -static const code not_found{ server::error::not_found }; -static const code wrong_version{ server::error::wrong_version }; -static const code invalid_argument{ server::error::invalid_argument }; +static const code not_found{ server::error::electrum::bad_request }; +static const code wrong_version{ server::error::electrum::bad_request }; +static const code invalid_argument{ server::error::electrum::bad_request }; static const std::string found_address{ "1BaMPFdqMUQ46BV8iRcwbVfsam57oBLMM" }; static const std::string bogus_hash{ "4242424242424242424242424242424242424242424242424242424242424242" }; diff --git a/test/protocols/electrum/electrum_scripthash.cpp b/test/protocols/electrum/electrum_scripthash.cpp index c9b7c47a..ea5cd210 100644 --- a/test/protocols/electrum/electrum_scripthash.cpp +++ b/test/protocols/electrum/electrum_scripthash.cpp @@ -20,9 +20,9 @@ #include "electrum_setup_fixture.hpp" using namespace system; -static const code not_found{ server::error::not_found }; -static const code wrong_version{ server::error::wrong_version }; -static const code invalid_argument{ server::error::invalid_argument }; +static const code not_found{ server::error::electrum::bad_request }; +static const code wrong_version{ server::error::electrum::bad_request }; +static const code invalid_argument{ server::error::electrum::bad_request }; static const std::string bogus_scripthash{ "9c2c84a6cf9809e08af19557e28d38257e6fee6981269760637a5f9dfb000b05" }; static const std::string found_scripthash{ "bad83872c90886be19b98734fd16741611efcd9f5de699c14b712675eec682f5" }; static const chain::script bogus{ chain::script::to_pay_key_hash_pattern({ 0x42 }) }; diff --git a/test/protocols/electrum/electrum_scriptpubkey.cpp b/test/protocols/electrum/electrum_scriptpubkey.cpp index 8e57aaab..2ffb0ef2 100644 --- a/test/protocols/electrum/electrum_scriptpubkey.cpp +++ b/test/protocols/electrum/electrum_scriptpubkey.cpp @@ -20,9 +20,9 @@ #include "electrum_setup_fixture.hpp" using namespace system; -static const code not_found{ server::error::not_found }; -static const code wrong_version{ server::error::wrong_version }; -static const code invalid_argument{ server::error::invalid_argument }; +static const code not_found{ server::error::electrum::bad_request }; +static const code wrong_version{ server::error::electrum::bad_request }; +static const code invalid_argument{ server::error::electrum::bad_request }; static const chain::script bogus{ chain::script::to_pay_key_hash_pattern({ 0x42 }) }; static const chain::script found{ chain::script::to_pay_key_hash_pattern({ 0x02 }) }; static const auto bogus_script = encode_base16(bogus.to_data(false)); diff --git a/test/protocols/electrum/electrum_server.cpp b/test/protocols/electrum/electrum_server.cpp index 57932d55..a8528cdf 100644 --- a/test/protocols/electrum/electrum_server.cpp +++ b/test/protocols/electrum/electrum_server.cpp @@ -22,9 +22,9 @@ BOOST_FIXTURE_TEST_SUITE(electrum_tests, electrum_ten_block_setup_fixture) using namespace system; -static const code wrong_version{ server::error::wrong_version }; -static const code not_implemented{ server::error::not_implemented }; -static const code invalid_argument{ server::error::invalid_argument }; +static const code wrong_version{ server::error::electrum::bad_request }; +static const code not_implemented{ server::error::electrum::method_not_found }; +static const code invalid_argument{ server::error::electrum::bad_request }; // server.add_peer diff --git a/test/protocols/electrum/electrum_subscribe.cpp b/test/protocols/electrum/electrum_subscribe.cpp index 8cfbcbd0..3aaec710 100644 --- a/test/protocols/electrum/electrum_subscribe.cpp +++ b/test/protocols/electrum/electrum_subscribe.cpp @@ -20,9 +20,9 @@ #include "electrum_setup_fixture.hpp" using namespace system; -static const code not_found{ server::error::not_found }; -static const code wrong_version{ server::error::wrong_version }; -static const code invalid_argument{ server::error::invalid_argument }; +static const code not_found{ server::error::electrum::bad_request }; +static const code wrong_version{ server::error::electrum::bad_request }; +static const code invalid_argument{ server::error::electrum::bad_request }; static const std::string bogus_address{ "1JqDybm2nWTENrHvMyafbSXXtTk5Uv5QAn" }; static const std::string found_address{ "1BaMPFdqMUQ46BV8iRcwbVfsam57oBLMM" }; static const std::string bogus_scripthash{ "9c2c84a6cf9809e08af19557e28d38257e6fee6981269760637a5f9dfb000b05" }; diff --git a/test/protocols/electrum/electrum_transactions.cpp b/test/protocols/electrum/electrum_transactions.cpp index 757832a4..d786e941 100644 --- a/test/protocols/electrum/electrum_transactions.cpp +++ b/test/protocols/electrum/electrum_transactions.cpp @@ -24,12 +24,13 @@ BOOST_FIXTURE_TEST_SUITE(electrum_tests, electrum_ten_block_setup_fixture) // blockchain.transaction.broadcast using namespace system; -static const code not_found{ server::error::not_found }; -static const code wrong_version{ server::error::wrong_version }; -static const code not_implemented{ server::error::not_implemented }; -static const code invalid_argument{ server::error::invalid_argument }; -static const code unsupported_argument{ server::error::unsupported_argument }; -static const code unconfirmable_transaction{ server::error::unconfirmable_transaction }; +static const code not_found{ server::error::electrum::bad_request }; +static const code daemon_error{ server::error::electrum::daemon_error }; +static const code wrong_version{ server::error::electrum::bad_request }; +static const code not_implemented{ server::error::electrum::method_not_found }; +static const code invalid_argument{ server::error::electrum::bad_request }; +static const code unsupported_argument{ server::error::electrum::bad_request }; +static const code unconfirmable_transaction{ server::error::electrum::daemon_error }; static const code coinbase_transaction{ system::error::coinbase_transaction }; BOOST_AUTO_TEST_CASE(electrum__blockchain_transaction_broadcast__empty__invalid_argument) @@ -78,7 +79,7 @@ BOOST_AUTO_TEST_CASE(electrum__blockchain_transaction_broadcast__v1_6_genesis_co constexpr auto request = R"({"id":74,"method":"blockchain.transaction.broadcast","params":["%1%"]})" "\n"; const auto response = get((boost_format(request) % tx0_text).str()); REQUIRE_NO_THROW_TRUE(response.at("error").as_object().at("code").is_int64()); - BOOST_REQUIRE_EQUAL(response.at("error").as_object().at("code").as_int64(), coinbase_transaction.value()); + BOOST_REQUIRE_EQUAL(response.at("error").as_object().at("code").as_int64(), daemon_error.value()); } // blockchain.transaction.broadcast_package @@ -209,7 +210,7 @@ BOOST_AUTO_TEST_CASE(electrum__blockchain_transaction_get__nonexistent_tx__not_f const auto request = R"({"id":79,"method":"blockchain.transaction.get","params":["%1%",false]})" "\n"; const auto response = get((boost_format(request) % bogus).str()); REQUIRE_NO_THROW_TRUE(response.at("error").as_object().at("code").is_int64()); - BOOST_REQUIRE_EQUAL(response.at("error").as_object().at("code").as_int64(), not_found.value()); + BOOST_REQUIRE_EQUAL(response.at("error").as_object().at("code").as_int64(), daemon_error.value()); } BOOST_AUTO_TEST_CASE(electrum__blockchain_transaction_get__missing_verbose__defaults_false) diff --git a/test/protocols/electrum/electrum_version.cpp b/test/protocols/electrum/electrum_version.cpp index 1f40785a..b9300cbb 100644 --- a/test/protocols/electrum/electrum_version.cpp +++ b/test/protocols/electrum/electrum_version.cpp @@ -19,7 +19,7 @@ #include "../../test.hpp" #include "electrum_setup_fixture.hpp" -static const code invalid_argument{ error::invalid_argument }; +static const code invalid_argument{ error::electrum::bad_request }; BOOST_FIXTURE_TEST_SUITE(electrum_tests, electrum_ten_block_setup_fixture)