Merge bitcoin/bitcoin#32862: rpc: use CScheduler for relocking wallet and remove RPCTimer

fcfd3db563 remove RPCTimerInterface and RPCRunLater (Matthew Zipkin)
8a1765795f use WalletContext scheduler for walletpassphrase callback (Matthew Zipkin)

Pull request description:

  This removes the dependency on libevent for events scheduled by RPC commands, like re-locking a wallet some time after decryption with walletpassphrase. Since walletpassphrase is currently the only RPC that does this, `RPCRunLater`, `RPCTimerInterface` and all related methods are left unused, and deleted in the second commit. Any future RPC that needs to execute a callback in the future can follow the pattern in this PR and just use a scheduler from node or wallet context.

  This is an alternative approach to #32796, described in https://github.com/bitcoin/bitcoin/pull/32796#issuecomment-3014309449

ACKs for top commit:
  fjahr:
    Code Review ACK fcfd3db563
  achow101:
    ACK fcfd3db563
  furszy:
    ACK fcfd3db563

Tree-SHA512: 04f5e9c3f73f598c3d41d6e35bb59c64c7b93b03ad9fce3c40901733147ce7764f41f475fef1527d44af18f722759996a31ca83b48cb52153795d5022fecfd14
This commit is contained in:
Ava Chow
2025-07-07 17:59:21 -07:00
10 changed files with 14 additions and 187 deletions

View File

@@ -34,11 +34,6 @@ static GlobalMutex g_rpc_warmup_mutex;
static std::atomic<bool> g_rpc_running{false};
static bool fRPCInWarmup GUARDED_BY(g_rpc_warmup_mutex) = true;
static std::string rpcWarmupStatus GUARDED_BY(g_rpc_warmup_mutex) = "RPC server started";
/* Timer-creating functions */
static RPCTimerInterface* timerInterface = nullptr;
/* Map of name to timer. */
static GlobalMutex g_deadline_timers_mutex;
static std::map<std::string, std::unique_ptr<RPCTimerBase> > deadlineTimers GUARDED_BY(g_deadline_timers_mutex);
static bool ExecuteCommand(const CRPCCommand& command, const JSONRPCRequest& request, UniValue& result, bool last_handler);
struct RPCCommandExecutionInfo
@@ -301,7 +296,6 @@ void StopRPC()
assert(!g_rpc_running);
std::call_once(g_rpc_stop_flag, [&]() {
LogDebug(BCLog::RPC, "Stopping RPC\n");
WITH_LOCK(g_deadline_timers_mutex, deadlineTimers.clear());
DeleteAuthCookie();
LogDebug(BCLog::RPC, "RPC stopped.\n");
});
@@ -543,31 +537,4 @@ UniValue CRPCTable::dumpArgMap(const JSONRPCRequest& args_request) const
return ret;
}
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
{
if (!timerInterface)
timerInterface = iface;
}
void RPCSetTimerInterface(RPCTimerInterface *iface)
{
timerInterface = iface;
}
void RPCUnsetTimerInterface(RPCTimerInterface *iface)
{
if (timerInterface == iface)
timerInterface = nullptr;
}
void RPCRunLater(const std::string& name, std::function<void()> func, int64_t nSeconds)
{
if (!timerInterface)
throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC");
LOCK(g_deadline_timers_mutex);
deadlineTimers.erase(name);
LogDebug(BCLog::RPC, "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name());
deadlineTimers.emplace(name, std::unique_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000)));
}
CRPCTable tableRPC;

View File

@@ -35,47 +35,6 @@ void SetRPCWarmupFinished();
/* returns the current warmup state. */
bool RPCIsInWarmup(std::string *outStatus);
/** Opaque base class for timers returned by NewTimerFunc.
* This provides no methods at the moment, but makes sure that delete
* cleans up the whole state.
*/
class RPCTimerBase
{
public:
virtual ~RPCTimerBase() = default;
};
/**
* RPC timer "driver".
*/
class RPCTimerInterface
{
public:
virtual ~RPCTimerInterface() = default;
/** Implementation name */
virtual const char *Name() = 0;
/** Factory function for timers.
* RPC will call the function to create a timer that will call func in *millis* milliseconds.
* @note As the RPC mechanism is backend-neutral, it can use different implementations of timers.
* This is needed to cope with the case in which there is no HTTP server, but
* only GUI RPC console, and to break the dependency of pcserver on httprpc.
*/
virtual RPCTimerBase* NewTimer(std::function<void()>& func, int64_t millis) = 0;
};
/** Set the factory function for timers */
void RPCSetTimerInterface(RPCTimerInterface *iface);
/** Set the factory function for timer, but only, if unset */
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface);
/** Unset factory function for timers */
void RPCUnsetTimerInterface(RPCTimerInterface *iface);
/**
* Run func nSeconds from now.
* Overrides previous timer <name> (if any).
*/
void RPCRunLater(const std::string& name, std::function<void()> func, int64_t nSeconds);
typedef RPCHelpMan (*RpcMethodFnType)();
class CRPCCommand