From 769dc84852e6f14876d595a7d628cc02fa074c75 Mon Sep 17 00:00:00 2001 From: Fabian Jahr Date: Wed, 4 Sep 2024 01:53:07 +0200 Subject: [PATCH] rpc: Manage dumptxoutset rollback with RAII class --- src/rpc/blockchain.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 43d5dd462088ac..ce33ba34484bd0 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -2683,6 +2683,23 @@ class NetworkDisable }; }; +/** + * RAII class that temporarily rolls back the local chain in it's constructor + * and rolls it forward again in it's destructor. + */ +class TemporaryRollback +{ + ChainstateManager& m_chainman; + const CBlockIndex* m_invalidate_index; +public: + TemporaryRollback(ChainstateManager& chainman, const CBlockIndex* index) : m_chainman(chainman), m_invalidate_index(index) { + InvalidateBlock(m_chainman, m_invalidate_index->GetBlockHash()); + }; + ~TemporaryRollback() { + ReconsiderBlock(m_chainman, m_invalidate_index->GetBlockHash()); + }; +}; + /** * Serialize the UTXO set to a file for loading elsewhere. * @@ -2770,6 +2787,7 @@ static RPCHelpMan dumptxoutset() CConnman& connman = EnsureConnman(node); const CBlockIndex* invalidate_index{nullptr}; std::unique_ptr disable_network; + std::unique_ptr temporary_rollback; // If the user wants to dump the txoutset of the current tip, we don't have // to roll back at all @@ -2798,7 +2816,7 @@ static RPCHelpMan dumptxoutset() } invalidate_index = WITH_LOCK(::cs_main, return node.chainman->ActiveChain().Next(target_index)); - InvalidateBlock(*node.chainman, invalidate_index->GetBlockHash()); + temporary_rollback = std::make_unique(*node.chainman, invalidate_index); } Chainstate* chainstate; @@ -2823,22 +2841,14 @@ static RPCHelpMan dumptxoutset() // be activated as the new tip and we would not get to new_tip_index. if (target_index != chainstate->m_chain.Tip()) { LogInfo("Failed to roll back to requested height, reverting to tip.\n"); - error = JSONRPCError(RPC_MISC_ERROR, "Could not roll back to requested height."); + throw JSONRPCError(RPC_MISC_ERROR, "Could not roll back to requested height."); } else { std::tie(cursor, stats, tip) = PrepareUTXOSnapshot(*chainstate, node.rpc_interruption_point); } } - if (error.isNull()) { - result = WriteUTXOSnapshot(*chainstate, cursor.get(), &stats, tip, afile, path, temppath, node.rpc_interruption_point); - fs::rename(temppath, path); - } - if (invalidate_index) { - ReconsiderBlock(*node.chainman, invalidate_index->GetBlockHash()); - } - if (!error.isNull()) { - throw error; - } + result = WriteUTXOSnapshot(*chainstate, cursor.get(), &stats, tip, afile, path, temppath, node.rpc_interruption_point); + fs::rename(temppath, path); result.pushKV("path", path.utf8string()); return result;