As described in util/ref.h: "This implements a small subset of the functionality in C++17's std::any class, and can be dropped when the project updates to C++17". For accessing the contained object of a std::any instance, a helper template function AnyPtr is introduced (thanks to ryanofsky).
refactor: replace util::Ref with std::any (C++17) #21366
pull theStack wants to merge 3 commits into bitcoin:master from theStack:202012-replace-util_ref-by-std_any changing 23 files +90 −156-
theStack commented at 12:16 AM on March 5, 2021: member
- fanquake added the label Refactoring on Mar 5, 2021
-
fanquake commented at 2:49 AM on March 5, 2021: member
Concept ACK on removing no-longer needed abstraction. Currently failing to compile:
CXX wallet/libbitcoin_wallet_a-coincontrol.o In file included from /usr/include/c++/9/bits/move.h:55, from /usr/include/c++/9/bits/nested_exception.h:40, from /usr/include/c++/9/exception:144, from /usr/include/c++/9/new:40, from /usr/include/c++/9/any:37, from ./rpc/request.h:9, from ./rpc/server.h:10, from rpc/server.cpp:6: /usr/include/c++/9/type_traits: In instantiation of ‘struct std::__and_<std::is_copy_constructible<JSONRPCRequest>, std::__not_<std::is_constructible<JSONRPCRequest, const JSONRPCRequest&> >, std::__not_<std::__is_in_place_type<JSONRPCRequest> > >’: /usr/include/c++/9/type_traits:150:27: required from ‘constexpr const bool std::__and_v<std::is_copy_constructible<JSONRPCRequest>, std::__not_<std::is_constructible<JSONRPCRequest, const JSONRPCRequest&> >, std::__not_<std::__is_in_place_type<JSONRPCRequest> > >’ /usr/include/c++/9/any:192:27: required by substitution of ‘template<class _ValueType, class _Tp, class _Mgr, typename std::enable_if<__and_v<std::is_copy_constructible<_Tp>, std::__not_<std::is_constructible<_Tp, _ValueType&&> >, std::__not_<std::__is_in_place_type<_Tp> > >, bool>::type <anonymous> > std::any::any(_ValueType&&) [with _ValueType = const JSONRPCRequest&; _Tp = JSONRPCRequest; _Mgr = std::any::_Manager_external<JSONRPCRequest>; typename std::enable_if<__and_v<std::is_copy_constructible<_Tp>, std::__not_<std::is_constructible<_Tp, _ValueType&&> >, std::__not_<std::__is_in_place_type<_Tp> > >, bool>::type <anonymous> = <missing>]’ /usr/include/c++/9/type_traits:883:12: required from ‘struct std::is_constructible<JSONRPCRequest, const JSONRPCRequest&>’ /usr/include/c++/9/type_traits:901:12: required from ‘struct std::__is_copy_constructible_impl<JSONRPCRequest, true>’ /usr/include/c++/9/type_traits:907:12: required from ‘struct std::is_copy_constructible<JSONRPCRequest>’ /usr/include/c++/9/type_traits:131:12: required from ‘struct std::__and_<std::is_copy_constructible<JSONRPCRequest>, std::is_constructible<JSONRPCRequest, const JSONRPCRequest&> >’ /usr/include/c++/9/any:181:58: required by substitution of ‘template<class _ValueType, class _Tp, class _Mgr, typename std::enable_if<std::__and_<std::is_copy_constructible<_Tp>, std::is_constructible<_Tp, _ValueType&&> >::value, bool>::type <anonymous>, typename std::enable_if<(! std::__is_in_place_type<_Tp>::value), bool>::type <anonymous> > std::any::any(_ValueType&&) [with _ValueType = const JSONRPCRequest&; _Tp = JSONRPCRequest; _Mgr = std::any::_Manager_external<JSONRPCRequest>; typename std::enable_if<std::__and_<std::is_copy_constructible<_Tp>, std::is_constructible<_Tp, _ValueType&&> >::value, bool>::type <anonymous> = <missing>; typename std::enable_if<(! std::__is_in_place_type<_Tp>::value), bool>::type <anonymous> = <missing>]’ rpc/server.cpp:91:32: required from here /usr/include/c++/9/type_traits:136:12: error: incomplete type ‘std::is_copy_constructible<JSONRPCRequest>’ used in nested name specifier 136 | struct __and_<_B1, _B2, _B3, _Bn...> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/include/c++/9/type_traits: In instantiation of ‘constexpr const bool std::__and_v<std::is_copy_constructible<JSONRPCRequest>, std::__not_<std::is_constructible<JSONRPCRequest, const JSONRPCRequest&> >, std::__not_<std::__is_in_place_type<JSONRPCRequest> > >’: /usr/include/c++/9/any:192:27: required by substitution of ‘template<class _ValueType, class _Tp, class _Mgr, typename std::enable_if<__and_v<std::is_copy_constructible<_Tp>, std::__not_<std::is_constructible<_Tp, _ValueType&&> >, std::__not_<std::__is_in_place_type<_Tp> > >, bool>::type <anonymous> > std::any::any(_ValueType&&) [with _ValueType = const JSONRPCRequest&; _Tp = JSONRPCRequest; _Mgr = std::any::_Manager_external<JSONRPCRequest>; typename std::enable_if<__and_v<std::is_copy_constructible<_Tp>, std::__not_<std::is_constructible<_Tp, _ValueType&&> >, std::__not_<std::__is_in_place_type<_Tp> > >, bool>::type <anonymous> = <missing>]’ /usr/include/c++/9/type_traits:883:12: required from ‘struct std::is_constructible<JSONRPCRequest, const JSONRPCRequest&>’ /usr/include/c++/9/type_traits:901:12: required from ‘struct std::__is_copy_constructible_impl<JSONRPCRequest, true>’ /usr/include/c++/9/type_traits:907:12: required from ‘struct std::is_copy_constructible<JSONRPCRequest>’ /usr/include/c++/9/type_traits:131:12: required from ‘struct std::__and_<std::is_copy_constructible<JSONRPCRequest>, std::is_constructible<JSONRPCRequest, const JSONRPCRequest&> >’ /usr/include/c++/9/any:181:58: required by substitution of ‘template<class _ValueType, class _Tp, class _Mgr, typename std::enable_if<std::__and_<std::is_copy_constructible<_Tp>, std::is_constructible<_Tp, _ValueType&&> >::value, bool>::type <anonymous>, typename std::enable_if<(! std::__is_in_place_type<_Tp>::value), bool>::type <anonymous> > std::any::any(_ValueType&&) [with _ValueType = const JSONRPCRequest&; _Tp = JSONRPCRequest; _Mgr = std::any::_Manager_external<JSONRPCRequest>; typename std::enable_if<std::__and_<std::is_copy_constructible<_Tp>, std::is_constructible<_Tp, _ValueType&&> >::value, bool>::type <anonymous> = <missing>; typename std::enable_if<(! std::__is_in_place_type<_Tp>::value), bool>::type <anonymous> = <missing>]’ rpc/server.cpp:91:32: required from here /usr/include/c++/9/type_traits:150:27: error: ‘value’ is not a member of ‘std::__and_<std::is_copy_constructible<JSONRPCRequest>, std::__not_<std::is_constructible<JSONRPCRequest, const JSONRPCRequest&> >, std::__not_<std::__is_in_place_type<JSONRPCRequest> > >’ 150 | inline constexpr bool __and_v = __and_<_Bn...>::value; | ^~~~~~~ make[2]: *** [Makefile:8807: rpc/libbitcoin_server_a-server.o] Error 1 -
DrahtBot commented at 9:56 AM on March 5, 2021: member
<!--e57a25ab6845829454e8d69fc972939a-->
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
<!--174a7506f384e20aa4161008e828411d-->
Conflicts
Reviewers, this pull request conflicts with the following ones:
- #20459 (rpc: Fail to return undocumented return values by MarcoFalke)
- #19101 (refactor: remove ::vpwallets and related global variables by ryanofsky)
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
- theStack force-pushed on Mar 5, 2021
- theStack force-pushed on Mar 5, 2021
-
theStack commented at 1:05 PM on March 5, 2021: member
Meh, there seems to be a problem with the (default) copy-constructor of
class JSONRPCRequestthat is invoked inCRPCTable::help:... (..., const JSONRPCRequest& helpreq) { ... JSONRPCRequest jreq(helpreq); ... }No idea why this compiles locally with clang11 and obviously also for the CI jobs for MacOS and ARM.
-
in src/rest.cpp:107 in c6686a3a58 outdated
104 | + try { 105 | + NodeContext& node_context = std::any_cast<std::reference_wrapper<NodeContext>>(context); 106 | + node = &node_context; 107 | + } catch (const std::bad_any_cast&) { 108 | + node = nullptr; 109 | + }
ryanofsky commented at 1:15 PM on March 5, 2021:In commit "refactor: replace util::Ref by std::any (C++17)" (c6686a3a582670618b685e69bdfa2ba893b5ce92)
This change and other changes in this commit seems pretty obscure and verbose. It would be nice to define a helper function so these 7 lines could be just be replaced with:
const NodeContext* node = util::AnyPtr<NodeContext>(context);Helper could go in
util/system.hand look like:template<typename T> T* AnyPtr(const std::any& any) { try { return std::any_cast<T*>(any); } catch (const std::bad_any_cast&) { return nullptr; } }Also I think it would be better to just assign
context = &nodeinstead ofcontext = std::ref(node). I think the only reason you would use reference_wrappers instead of pointers is when you want non-nullable references, but std::any is inherently nullable so combining it with std::reference_wrapper just makes things complicated for no benefit.
theStack commented at 2:57 PM on March 5, 2021:Both introducing a
std::anyaccess helper and using pointers instead of references are great ideas, thanks! Looks much cleaner now, with the clunky try/catch-construct deduplicated and hidden in util/system.h.ryanofsky commented at 1:16 PM on March 5, 2021: memberThanks for this followup!
theStack force-pushed on Mar 5, 2021theStack force-pushed on Mar 5, 2021theStack commented at 2:59 PM on March 5, 2021: memberForce-pushed with suggestions by @ryanofsky (https://github.com/bitcoin/bitcoin/pull/21366#discussion_r588287531): introduced a helper
AnyPtrto accessstd::anycontents and generally assigned pointers to std::any instances instead of references. Code looks much cleaner now.in src/rpc/server.cpp:91 in feb55dde39 outdated
87 | @@ -87,7 +88,7 @@ std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& 88 | vCommands.push_back(make_pair(entry.second.front()->category + entry.first, entry.second.front())); 89 | sort(vCommands.begin(), vCommands.end()); 90 | 91 | - JSONRPCRequest jreq(helpreq); 92 | + JSONRPCRequest jreq(&helpreq);
ryanofsky commented at 3:34 PM on March 6, 2021:In commit "refactor: replace util::Ref by std::any (C++17)" (feb55dde39e59a2709ecefff848a1d8eb9fe69ca)
There's a bug here ~and this change should be reverted~. This line is supposed to create
jreqas a copy ofhelprequsing theJSONRPCRequestcopy constructor. Now it creates a newjreqrequest using thehelpreqobject as an embedded request context.I'm not sure if this is a new bug, or this bug was present previously (even previously
util::Refconstructor might have take precedence over copy constructor), but passing&helpreqhere is not intended.
EDIT: Instead of reverting this, would suggest changing it to:
JSONRPCRequest jreq = helpreq;This would be more clear and prevent the context constructor from being called (since it's marked explicit).
theStack commented at 8:29 PM on March 6, 2021:Thanks, done.
in src/rpc/request.h:40 in feb55dde39 outdated
34 | @@ -38,14 +35,14 @@ class JSONRPCRequest 35 | std::string URI; 36 | std::string authUser; 37 | std::string peerAddr; 38 | - const util::Ref& context; 39 | + const std::any& context; 40 | 41 | - explicit JSONRPCRequest(const util::Ref& context) : id(NullUniValue), params(NullUniValue), fHelp(false), context(context) {} 42 | + explicit JSONRPCRequest(const std::any& context) : id(NullUniValue), params(NullUniValue), fHelp(false), context(context) {}
ryanofsky commented at 3:41 PM on March 6, 2021:In commit "refactor: replace util::Ref by std::any (C++17)" (feb55dde39e59a2709ecefff848a1d8eb9fe69ca)
This turns out to be dangerous because in some cases like
JSONRPCRequest jreq(helpreq);this constructor will take precedence over the copy constructor.~Would suggest changing this only to accept pointer arguments so it won't be accidentally invoked trying to create a copy:~
template<typename T> explicit JSONRPCRequest(T* context) : id(NullUniValue), params(NullUniValue), fHelp(false), context(context) {}
EDIT: Struck out suggestion above. It doesn't work because the JSONRPCRequest needs a reference to a long-lived std::any object and can't use a internal one. I'm not actually sure why this is the case, and think it may be worth simplifying in the future, but this would be a bigger change. Can disregard this comment.
ryanofsky commented at 4:06 PM on March 6, 2021: memberCode review almost-ack 659537886dba809ca2adfa26c92a117066deb5cc. JSONRPCRequest std::any constructor isn't as safe as it could be because it can take precedence over the copy constructor
theStack force-pushed on Mar 6, 2021in src/util/system.h:511 in 003e76c29c outdated
506 | + * Helper function to access the contained object of a std::any instance. 507 | + * Returns a pointer to the object if passed instance has a value and the type 508 | + * matches, nullptr otherwise. 509 | + */ 510 | +template<typename T> 511 | +T* AnyPtr(const std::any& any)
JeremyRubin commented at 7:29 PM on March 6, 2021:Concept NACK this implementation.
You should label this function as noexcept and use the noexcept versions of any_cast which will already return you a nullptr. See variants 4 and 5 https://en.cppreference.com/w/cpp/utility/any/any_cast. These are implemented AFAIK internally without using exceptions.
Exceptions have a non negligible performance overhead if hitting the
catchcase we may want to avoid.You could -- if you want -- introduce a try/catch variant that is called
AnyPtrLikelythat uses try/catch where we're already pretty sure that we'll succeed, but that seems like over optimizing.
ryanofsky commented at 7:55 PM on March 6, 2021:Oops, sorry. I didn't know about the noexcept casts. This can be simplified to:
template<typename T> T* AnyPtr(const std::any& any) { T* const* ptr = std::any_cast<T*>(&any); return ptr ? *ptr : nullptr; }I don't think this is used in any performance critical code, but no reason this needs to be slower and more complicated.
theStack commented at 8:19 PM on March 6, 2021:Good catch, I somehow missed that there was a noexcept version of
std::any_cast. But then I guess we can as well directly use that instead of introducing AnyPtr? This would be in effect just another name for the same purpose.
ryanofsky commented at 8:36 PM on March 6, 2021:Good catch, I somehow missed that there was a noexcept version of
std::any_cast. But then I guess we can as well directly use that instead of introducing AnyPtr? This would be in effect just another name for the same purpose.My preference would be to keep AnyPtr instead of introducing NodeContext* const* temporary variables because I think the two different ways these could be null could be confusing and cause non-obvious bugs, but feel free to take any approach.
JeremyRubin commented at 1:50 AM on March 7, 2021:using any_cast bare is a code smell IMO because it can arbitrarily become the non noexcept version :(, the wrapper makes the version guaranteed. If anything, you could declare it as inline so there is no overhead? (idk about template + inline...)
I think that's what @ryanofsky is saying.
theStack commented at 10:09 PM on March 7, 2021:After having tried out using std::any_cast directly yesterday, I can confirm ryanofsky's point of the drawback, needing temporary variables, making the code clunky and potentially confusing. Also the ambiguity on which version is chosen is a strong argument against it. Kept the AnyPtr function, changed it to the proposed implementation, see #21366 (comment).
ryanofsky commented at 8:09 PM on March 6, 2021: memberAnother batch of simplifications you could consider. There's no need really to require request objects to have contexts assigned.
<details><summary>diff</summary> <p>
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 87c63593051..7d246325e44 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -131,7 +131,7 @@ static bool AppInit(int argc, char* argv[]) // If locking the data directory failed, exit immediately return false; } - fRet = AppInitInterfaces(node) && AppInitMain(context, node); + fRet = AppInitInterfaces(node) && AppInitMain(node); } catch (const std::exception& e) { PrintExceptionContinue(&e, "AppInit()"); diff --git a/src/httprpc.cpp b/src/httprpc.cpp index d33e671ee42..cd45eccc4ed 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -159,7 +159,8 @@ static bool HTTPReq_JSONRPC(const std::any& context, HTTPRequest* req) return false; } - JSONRPCRequest jreq(context); + JSONRPCRequest jreq; + jreq.context = context; jreq.peerAddr = req->GetPeer().ToString(); if (!RPCAuthorized(authHeader.second, jreq.authUser)) { LogPrintf("ThreadRPCServer incorrect password attempt from %s\n", jreq.peerAddr); @@ -294,7 +295,7 @@ bool StartHTTPRPC(const std::any& context) if (!InitRPCAuthentication()) return false; - auto handle_rpc = [&context](HTTPRequest* req, const std::string&) { return HTTPReq_JSONRPC(context, req); }; + auto handle_rpc = [context](HTTPRequest* req, const std::string&) { return HTTPReq_JSONRPC(context, req); }; RegisterHTTPHandler("/", true, handle_rpc); if (g_wallet_init_interface.HasWalletSupport()) { RegisterHTTPHandler("/wallet/", false, handle_rpc); diff --git a/src/init.cpp b/src/init.cpp index efb92802126..c166af10f1f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -785,7 +785,7 @@ static bool InitSanityCheck() return true; } -static bool AppInitServers(const std::any& context, NodeContext& node) +static bool AppInitServers(NodeContext& node) { const ArgsManager& args = *Assert(node.args); RPCServer::OnStarted(&OnRPCStarted); @@ -794,9 +794,9 @@ static bool AppInitServers(const std::any& context, NodeContext& node) return false; StartRPC(); node.rpc_interruption_point = RpcInterruptionPoint; - if (!StartHTTPRPC(context)) + if (!StartHTTPRPC(&node)) return false; - if (args.GetBoolArg("-rest", DEFAULT_REST_ENABLE)) StartREST(context); + if (args.GetBoolArg("-rest", DEFAULT_REST_ENABLE)) StartREST(&node); StartHTTPServer(); return true; } @@ -1274,7 +1274,7 @@ bool AppInitInterfaces(NodeContext& node) return true; } -bool AppInitMain(const std::any& context, NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) +bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) { const ArgsManager& args = *Assert(node.args); const CChainParams& chainparams = Params(); @@ -1379,7 +1379,7 @@ bool AppInitMain(const std::any& context, NodeContext& node, interfaces::BlockAn */ if (args.GetBoolArg("-server", false)) { uiInterface.InitMessage_connect(SetRPCWarmupStatus); - if (!AppInitServers(context, node)) + if (!AppInitServers(node)) return InitError(_("Unable to start HTTP server. See debug log for details.")); } diff --git a/src/init.h b/src/init.h index fe1c66202bf..d8fcb1e0ce3 100644 --- a/src/init.h +++ b/src/init.h @@ -59,7 +59,7 @@ bool AppInitInterfaces(NodeContext& node); * [@note](/bitcoin-bitcoin/contributor/note/) This should only be done after daemonization. Call Shutdown() if this function fails. * [@pre](/bitcoin-bitcoin/contributor/pre/) Parameters should be parsed and config file should be read, AppInitLockDataDirectory should have been called. */ -bool AppInitMain(const std::any& context, NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info = nullptr); +bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info = nullptr); /** * Register all arguments with the ArgsManager diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 8cf0dee5b4e..7d195688032 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -76,7 +76,7 @@ public: } bool appInitMain(interfaces::BlockAndHeaderTipInfo* tip_info) override { - return AppInitMain(m_context_ref, *m_context, tip_info); + return AppInitMain(*m_context, tip_info); } void appShutdown() override { @@ -218,7 +218,8 @@ public: CFeeRate getDustRelayFee() override { return ::dustRelayFee; } UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override { - JSONRPCRequest req(m_context_ref); + JSONRPCRequest req; + req.context = m_context; req.params = params; req.strMethod = command; req.URI = uri; @@ -287,14 +288,8 @@ public: void setContext(NodeContext* context) override { m_context = context; - if (context) { - m_context_ref = context; - } else { - m_context_ref.reset(); - } } NodeContext* m_context{nullptr}; - std::any m_context_ref; }; bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock, const CChain& active) diff --git a/src/rest.cpp b/src/rest.cpp index 452435f3e92..e2af5128121 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -317,7 +317,8 @@ static bool rest_chaininfo(const std::any& context, HTTPRequest* req, const std: switch (rf) { case RetFormat::JSON: { - JSONRPCRequest jsonRequest(context); + JSONRPCRequest jsonRequest; + jsonRequest.context = context; jsonRequest.params = UniValue(UniValue::VARR); UniValue chainInfoObject = getblockchaininfo().HandleRequest(jsonRequest); std::string strJSON = chainInfoObject.write() + "\n"; @@ -687,7 +688,7 @@ static const struct { void StartREST(const std::any& context) { for (const auto& up : uri_prefixes) { - auto handler = [&context, up](HTTPRequest* req, const std::string& prefix) { return up.handler(context, req, prefix); }; + auto handler = [context, up](HTTPRequest* req, const std::string& prefix) { return up.handler(context, req, prefix); }; RegisterHTTPHandler(up.prefix, false, handler); } } diff --git a/src/rpc/request.h b/src/rpc/request.h index 82d8fdc63ae..7a78d382cc9 100644 --- a/src/rpc/request.h +++ b/src/rpc/request.h @@ -35,18 +35,7 @@ public: std::string URI; std::string authUser; std::string peerAddr; - const std::any& context; - - explicit JSONRPCRequest(const std::any& context) : id(NullUniValue), params(NullUniValue), fHelp(false), context(context) {} - - //! Initializes request information from another request object and the - //! given context. The implementation should be updated if any members are - //! added or removed above. - JSONRPCRequest(const JSONRPCRequest& other, const std::any& context) - : id(other.id), strMethod(other.strMethod), params(other.params), fHelp(other.fHelp), URI(other.URI), - authUser(other.authUser), peerAddr(other.peerAddr), context(context) - { - } + std::any context; void parse(const UniValue& valRequest); }; diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 3d5216055ce..f16adf96d3e 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -88,7 +88,7 @@ std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& vCommands.push_back(make_pair(entry.second.front()->category + entry.first, entry.second.front())); sort(vCommands.begin(), vCommands.end()); - JSONRPCRequest jreq(&helpreq); + JSONRPCRequest jreq(helpreq); jreq.fHelp = true; jreq.params = UniValue(); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 4ffc2478696..d2749c89599 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -33,8 +33,8 @@ UniValue RPCTestingSetup::CallRPC(std::string args) boost::split(vArgs, args, boost::is_any_of(" \t")); std::string strMethod = vArgs[0]; vArgs.erase(vArgs.begin()); - std::any context{&m_node}; - JSONRPCRequest request(context); + JSONRPCRequest request; + request.context = &m_node; request.strMethod = strMethod; request.params = RPCConvertValues(strMethod, vArgs); request.fHelp = false; diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp index c91ede94f95..46533d8704c 100644 --- a/src/wallet/interfaces.cpp +++ b/src/wallet/interfaces.cpp @@ -514,7 +514,9 @@ public: { for (const CRPCCommand& command : GetWalletRPCCommands()) { m_rpc_commands.emplace_back(command.category, command.name, [this, &command](const JSONRPCRequest& request, UniValue& result, bool last_handler) { - return command.actor({request, &m_context}, result, last_handler); + JSONRPCRequest wrapped = request; + wrapped.context = &m_context; + return command.actor(wrapped, result, last_handler); }, command.argNames, command.unique_id); m_rpc_handlers.emplace_back(m_context.chain->handleRpc(m_rpc_commands.back())); } diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index e48f7b4d4f5..a9c20921abd 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -213,8 +213,7 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup) key.pushKV("timestamp", newTip->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1); key.pushKV("internal", UniValue(true)); keys.push_back(key); - std::any context; - JSONRPCRequest request(context); + JSONRPCRequest request; request.params.setArray(); request.params.push_back(keys); @@ -265,8 +264,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) AddWallet(wallet); wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash()); } - std::any context; - JSONRPCRequest request(context); + JSONRPCRequest request; request.params.setArray(); request.params.push_back(backup_file); @@ -281,8 +279,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) LOCK(wallet->cs_wallet); wallet->SetupLegacyScriptPubKeyMan(); - std::any context; - JSONRPCRequest request(context); + JSONRPCRequest request; request.params.setArray(); request.params.push_back(backup_file); AddWallet(wallet);</p> </details>
theStack force-pushed on Mar 6, 2021theStack commented at 11:59 PM on March 6, 2021: memberForce-pushed with feedback from @JeremyRubin (https://github.com/bitcoin/bitcoin/pull/21366#discussion_r588921151) and @ryanofsky (https://github.com/bitcoin/bitcoin/pull/21366#discussion_r588923880) taken into account:
AnyPtruses now the variant ofstd::any_castthat doesn't use exceptions. Also updated the PR description which still referred to the changeset without theAnyPtrhelper and the exception variant ofstd::any_cast.Another batch of simplifications you could consider. There's no need really to require request objects to have contexts assigned.
Good idea. I think those changes are out of scope for this PR, as the proposed simplifications are not connected to the
util::Ref/std::anyreplacements. Happy to open a follow-up PR though or review if someone else does.practicalswift commented at 6:31 PM on March 7, 2021: contributorConcept ACK
+89 −155 -- very nice! :)
ryanofsky approvedryanofsky commented at 3:08 AM on March 9, 2021: memberCode review ACK 6b6b8999ba67ceee6259db5d37a4798283064f00. Looks good! Only change since last review is simplifying AnyPtr function.
DrahtBot added the label Needs rebase on Mar 10, 2021theStack force-pushed on Mar 10, 2021theStack commented at 8:18 PM on March 10, 2021: memberRebased on master.
DrahtBot removed the label Needs rebase on Mar 10, 2021DrahtBot added the label Needs rebase on Mar 11, 2021MarcoFalke referenced this in commit e0bc27a14c on Mar 12, 2021theStack force-pushed on Mar 16, 2021theStack commented at 12:49 AM on March 16, 2021: memberRebased on master again.
DrahtBot removed the label Needs rebase on Mar 16, 2021theStack force-pushed on Mar 16, 2021hebasto commented at 12:38 AM on March 28, 2021: memberConcept ACK.
in src/node/interfaces.cpp:41 in 39069499a6 outdated
37 | @@ -38,7 +38,6 @@ 38 | #include <uint256.h> 39 | #include <univalue.h> 40 | #include <util/check.h> 41 | -#include <util/ref.h>
hebasto commented at 2:46 AM on March 28, 2021:Add
#include <any>?
theStack commented at 9:36 PM on March 29, 2021:Done.
in src/rest.cpp:80 in 39069499a6 outdated
74 | @@ -73,18 +75,18 @@ static bool RESTERR(HTTPRequest* req, enum HTTPStatusCode status, std::string me 75 | * context is not found. 76 | * @returns Pointer to the node context or nullptr if not found. 77 | */ 78 | -static NodeContext* GetNodeContext(const util::Ref& context, HTTPRequest* req) 79 | +static NodeContext* GetNodeContext(const std::any& context, HTTPRequest* req) 80 | { 81 | - NodeContext* node = context.Has<NodeContext>() ? &context.Get<NodeContext>() : nullptr; 82 | - if (!node) { 83 | + NodeContext* node_context = util::AnyPtr<NodeContext>(context);
hebasto commented at 2:50 AM on March 28, 2021:nit: Could be more concise without losing much details:
auto node_context = util::AnyPtr<NodeContext>(context);(Here and in other places when
util::AnyPtr<T>is used)
theStack commented at 9:41 PM on March 29, 2021:Good idea. I agree that for the reader it is obvious enough to see that "AnyPtr< T >(...)" returns type "T*" and using "auto" makes sense here. Done for all instances.
in src/rpc/server.cpp:18 in 39069499a6 outdated
14 | @@ -15,6 +15,7 @@ 15 | #include <boost/algorithm/string/split.hpp> 16 | #include <boost/signals2/signal.hpp> 17 | 18 | +#include <any>
hebasto commented at 2:51 AM on March 28, 2021:No need to
#include <any>here.
theStack commented at 9:42 PM on March 29, 2021:Thanks, removed.
hebasto approvedhebasto commented at 2:51 AM on March 28, 2021: memberACK 39069499a61d7c2cab8594162c99bf00ea2ac88b, I have reviewed the code and it looks OK, I agree it can be merged.
DrahtBot added the label Needs rebase on Mar 29, 202195cccf8a4butil: introduce helper AnyPtr to access std::any instances
Co-authored-by: Russell Yanofsky <russ@yanofsky.org>
refactor: replace util::Ref by std::any (C++17) 8dbb87a393remove unused class util::Ref and its unit test 916ab0195dtheStack force-pushed on Mar 29, 2021theStack commented at 9:45 PM on March 29, 2021: memberRebased on master and took in all suggestions by @hebasto (https://github.com/bitcoin/bitcoin/pull/21366#pullrequestreview-622716405) -- thanks a lot for reviewing!
hebasto approvedhebasto commented at 9:56 PM on March 29, 2021: memberre-ACK 916ab0195d567fd0a9097045e73a6654c453adea, with command
$ git range-diff master 39069499a61d7c2cab8594162c99bf00ea2ac88b 916ab0195d567fd0a9097045e73a6654c453adeaverified that since my previous review only rebased and implemented suggestions.
DrahtBot removed the label Needs rebase on Mar 29, 2021ryanofsky approvedryanofsky commented at 5:29 PM on March 31, 2021: memberCode review ACK 916ab0195d567fd0a9097045e73a6654c453adea. Changes since last review: rebase and replacing types with
auto. I might have usedconst auto*andauto*instead of plainautobecause I think the qualifiers are useful, but this is all good.laanwj merged this on Mar 31, 2021laanwj closed this on Mar 31, 2021sidhujag referenced this in commit 2429e592bd on Mar 31, 2021ryanofsky referenced this in commit 937fd4a66f on Apr 2, 2021ryanofsky referenced this in commit 2b98711426 on Apr 2, 2021ryanofsky referenced this in commit 03db28fd91 on Apr 3, 2021ryanofsky referenced this in commit 2dd05d5912 on Apr 3, 2021MarcoFalke referenced this in commit aa69471ecd on Apr 7, 2021ryanofsky referenced this in commit 9044522ef7 on Apr 7, 2021ryanofsky referenced this in commit 641ef117b3 on Apr 7, 2021sidhujag referenced this in commit dd30e4b655 on Apr 7, 2021MarcoFalke referenced this in commit 6664211be2 on Apr 8, 2021sidhujag referenced this in commit 3d28753d27 on Apr 8, 2021ryanofsky referenced this in commit fc47057c03 on Apr 8, 2021ryanofsky referenced this in commit b8c188e59e on Apr 8, 2021hebasto referenced this in commit 6fbbc3985b on May 5, 2021fanquake deleted a comment on May 16, 2021fanquake locked this on May 16, 2021theStack deleted the branch on Jul 31, 2021
github-metadata-mirror
This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-21 21:14 UTC
This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me