Skip to content

Commit

Permalink
merge bitcoin#17192: Add CHECK_NONFATAL and use it in src/rpc
Browse files Browse the repository at this point in the history
  • Loading branch information
kwvg committed Feb 25, 2022
1 parent 157b56a commit 7c71de1
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 10 deletions.
1 change: 1 addition & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ BITCOIN_CORE_H = \
unordered_lru_cache.h \
util/bip32.h \
util/bytevectorhash.h \
util/check.h \
util/error.h \
util/fees.h \
util/spanparsing.h \
Expand Down
5 changes: 2 additions & 3 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
#include <chain.h>
#include <chainparams.h>
#include <coins.h>
#include <node/coinstats.h>
#include <core_io.h>
#include <consensus/validation.h>
#include <index/blockfilterindex.h>
#include <key_io.h>
#include <index/txindex.h>
#include <key_io.h>
#include <node/coinstats.h>
#include <policy/feerate.h>
#include <policy/policy.h>
#include <primitives/transaction.h>
Expand All @@ -40,7 +40,6 @@
#include <llmq/chainlocks.h>
#include <llmq/instantsend.h>

#include <assert.h>
#include <stdint.h>

#include <univalue.h>
Expand Down
6 changes: 5 additions & 1 deletion src/rpc/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
#include <rpc/util.h>
#include <script/descriptor.h>
#include <txmempool.h>
#include <util/system.h>
#include <util/check.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <validation.h>
#include <util/validation.h>

Expand Down Expand Up @@ -1270,6 +1271,7 @@ static UniValue echo(const JSONRPCRequest& request)
throw std::runtime_error(
RPCHelpMan{"echo|echojson ...",
"\nSimply echo back the input arguments. This command is for testing.\n"
"\nIt will return an internal bug report when exactly 100 arguments are passed.\n"
"\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in "
"dash-cli and the GUI. There is no server-side difference.",
{},
Expand All @@ -1278,6 +1280,8 @@ static UniValue echo(const JSONRPCRequest& request)
}.ToString()
);

CHECK_NONFATAL(request.params.size() != 100);

return request.params;
}

Expand Down
13 changes: 7 additions & 6 deletions src/rpc/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
#define BITCOIN_RPC_UTIL_H

#include <node/transaction.h>
#include <pubkey.h>
#include <protocol.h>
#include <pubkey.h>
#include <rpc/protocol.h>
#include <rpc/request.h>
#include <script/standard.h>
#include <univalue.h>
#include <util/check.h>
#include <util/strencodings.h>

#include <string>
Expand Down Expand Up @@ -143,7 +144,7 @@ struct RPCArg {
m_oneline_description{oneline_description},
m_type_str{type_str}
{
assert(type != Type::ARR && type != Type::OBJ);
CHECK_NONFATAL(type != Type::ARR && type != Type::OBJ);
}

RPCArg(
Expand All @@ -162,7 +163,7 @@ struct RPCArg {
m_oneline_description{oneline_description},
m_type_str{type_str}
{
assert(type == Type::ARR || type == Type::OBJ);
CHECK_NONFATAL(type == Type::ARR || type == Type::OBJ);
}

bool IsOptional() const;
Expand Down Expand Up @@ -191,14 +192,14 @@ struct RPCResult {
explicit RPCResult(std::string result)
: m_cond{}, m_result{std::move(result)}
{
assert(!m_result.empty());
CHECK_NONFATAL(!m_result.empty());
}

RPCResult(std::string cond, std::string result)
: m_cond{std::move(cond)}, m_result{std::move(result)}
{
assert(!m_cond.empty());
assert(!m_result.empty());
CHECK_NONFATAL(!m_cond.empty());
CHECK_NONFATAL(!m_result.empty());
}
};

Expand Down
41 changes: 41 additions & 0 deletions src/util/check.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) 2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_UTIL_CHECK_H
#define BITCOIN_UTIL_CHECK_H

#include <tinyformat.h>

#include <stdexcept>

class NonFatalCheckError : public std::runtime_error
{
using std::runtime_error::runtime_error;
};

/**
* Throw a NonFatalCheckError when the condition evaluates to false
*
* This should only be used
* - where the condition is assumed to be true, not for error handling or validating user input
* - where a failure to fulfill the condition is recoverable and does not abort the program
*
* For example in RPC code, where it is undersirable to crash the whole program, this can be generally used to replace
* asserts or recoverable logic errors. A NonFatalCheckError in RPC code is caught and passed as a string to the RPC
* caller, which can then report the issue to the developers.
*/
#define CHECK_NONFATAL(condition) \
do { \
if (!(condition)) { \
throw NonFatalCheckError( \
strprintf("%s:%d (%s)\n" \
"Internal bug detected: '%s'\n" \
"You may report this issue here: %s\n", \
__FILE__, __LINE__, __func__, \
(#condition), \
PACKAGE_BUGREPORT)); \
} \
} while (false)

#endif // BITCOIN_UTIL_CHECK_H
7 changes: 7 additions & 0 deletions test/functional/rpc_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ def set_test_params(self):
def run_test(self):
node = self.nodes[0]

self.log.info("test CHECK_NONFATAL")
assert_raises_rpc_error(
-1,
"Internal bug detected: 'request.params.size() != 100'",
lambda: node.echo(*[0] * 100),
)

self.log.info("test getmemoryinfo")
memory = node.getmemoryinfo()['locked']
assert_greater_than(memory['used'], 0)
Expand Down

0 comments on commit 7c71de1

Please sign in to comment.