validationinterface.h raw

   1  // Copyright (c) 2009-2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-present The Bitcoin Core developers
   3  // Distributed under the MIT software license, see the accompanying
   4  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   5  
   6  #ifndef BITCOIN_VALIDATIONINTERFACE_H
   7  #define BITCOIN_VALIDATIONINTERFACE_H
   8  
   9  #include <kernel/cs_main.h>
  10  #include <primitives/transaction.h>
  11  #include <sync.h>
  12  
  13  #include <cstddef>
  14  #include <cstdint>
  15  #include <functional>
  16  #include <memory>
  17  #include <vector>
  18  
  19  namespace kernel {
  20  struct ChainstateRole;
  21  } // namespace kernel
  22  namespace util {
  23  class TaskRunnerInterface;
  24  } // namespace util
  25  
  26  class BlockValidationState;
  27  class CBlock;
  28  class CBlockIndex;
  29  struct CBlockLocator;
  30  enum class MemPoolRemovalReason;
  31  struct RemovedMempoolTransactionInfo;
  32  struct NewMempoolTransactionInfo;
  33  
  34  /**
  35   * Implement this to subscribe to events generated in validation and mempool
  36   *
  37   * Each CValidationInterface() subscriber will receive event callbacks
  38   * in the order in which the events were generated by validation and mempool.
  39   * Furthermore, each ValidationInterface() subscriber may assume that
  40   * callbacks effectively run in a single thread with single-threaded
  41   * memory consistency. That is, for a given ValidationInterface()
  42   * instantiation, each callback will complete before the next one is
  43   * invoked. This means, for example when a block is connected that the
  44   * UpdatedBlockTip() callback may depend on an operation performed in
  45   * the BlockConnected() callback without worrying about explicit
  46   * synchronization. No ordering should be assumed across
  47   * ValidationInterface() subscribers.
  48   */
  49  class CValidationInterface {
  50  protected:
  51      /**
  52       * Protected destructor so that instances can only be deleted by derived classes.
  53       * If that restriction is no longer desired, this should be made public and virtual.
  54       */
  55      ~CValidationInterface() = default;
  56      /**
  57       * Notifies listeners when the block chain tip advances.
  58       *
  59       * When multiple blocks are connected at once, UpdatedBlockTip will be called on the final tip
  60       * but may not be called on every intermediate tip. If the latter behavior is desired,
  61       * subscribe to BlockConnected() instead.
  62       *
  63       * Called on a background thread. Only called for the active chainstate.
  64       */
  65      virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {}
  66      /**
  67       * Notifies listeners any time the block chain tip changes, synchronously.
  68       */
  69      virtual void ActiveTipChange(const CBlockIndex& new_tip, bool is_ibd) {};
  70      /**
  71       * Notifies listeners of a transaction having been added to mempool.
  72       *
  73       * Called on a background thread.
  74       */
  75      virtual void TransactionAddedToMempool(const NewMempoolTransactionInfo& tx, uint64_t mempool_sequence) {}
  76  
  77      /**
  78       * Notifies listeners of a transaction leaving mempool.
  79       *
  80       * This notification fires for transactions that are removed from the
  81       * mempool for the following reasons:
  82       *
  83       * - EXPIRY (expired from mempool after -mempoolexpiry hours)
  84       * - SIZELIMIT (removed in size limiting if the mempool exceeds -maxmempool megabytes)
  85       * - REORG (removed during a reorg)
  86       * - CONFLICT (removed because it conflicts with in-block transaction)
  87       * - REPLACED (removed due to RBF replacement)
  88       *
  89       * This does not fire for transactions that are removed from the mempool
  90       * because they have been included in a block. Any client that is interested
  91       * in transactions removed from the mempool for inclusion in a block can learn
  92       * about those transactions from the MempoolTransactionsRemovedForBlock notification.
  93       *
  94       * Transactions that are removed from the mempool because they conflict
  95       * with a transaction in the new block will have
  96       * TransactionRemovedFromMempool events fired *before* the BlockConnected
  97       * event is fired. If multiple blocks are connected in one step, then the
  98       * ordering could be:
  99       *
 100       * - TransactionRemovedFromMempool(tx1 from block A)
 101       * - TransactionRemovedFromMempool(tx2 from block A)
 102       * - TransactionRemovedFromMempool(tx1 from block B)
 103       * - TransactionRemovedFromMempool(tx2 from block B)
 104       * - BlockConnected(A)
 105       * - BlockConnected(B)
 106       *
 107       * Called on a background thread.
 108       */
 109      virtual void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) {}
 110      /*
 111       * Notifies listeners of transactions removed from the mempool as
 112       * as a result of new block being connected.
 113       * MempoolTransactionsRemovedForBlock will be fired before BlockConnected.
 114       *
 115       * Called on a background thread.
 116       */
 117      virtual void MempoolTransactionsRemovedForBlock(const std::vector<RemovedMempoolTransactionInfo>& txs_removed_for_block, unsigned int nBlockHeight) {}
 118      /**
 119       * Notifies listeners of a block being connected.
 120       *
 121       * Called on a background thread.
 122       */
 123      virtual void BlockConnected(const kernel::ChainstateRole& role, const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) {}
 124      /**
 125       * Notifies listeners of a block being disconnected
 126       * Provides the block that was disconnected.
 127       *
 128       * Called on a background thread. Only called for the active chainstate, since
 129       * background chainstates should never disconnect blocks.
 130       */
 131      virtual void BlockDisconnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex* pindex) {}
 132      /**
 133       * Notifies listeners of the new active block chain on-disk.
 134       *
 135       * Prior to this callback, any updates are not guaranteed to persist on disk
 136       * (ie clients need to handle shutdown/restart safety by being able to
 137       * understand when some updates were lost due to unclean shutdown).
 138       *
 139       * When this callback is invoked, the validation changes done by any prior
 140       * callback are guaranteed to exist on disk and survive a restart, including
 141       * an unclean shutdown.
 142       *
 143       * Provides a locator describing the best chain, which is likely useful for
 144       * storing current state on disk in client DBs.
 145       *
 146       * Called on a background thread.
 147       */
 148      virtual void ChainStateFlushed(const kernel::ChainstateRole& role, const CBlockLocator& locator) {}
 149      /**
 150       * Notifies listeners of a block validation result.
 151       * If the provided BlockValidationState IsValid, the provided block
 152       * is guaranteed to be the current best block at the time the
 153       * callback was generated (not necessarily now).
 154       */
 155      virtual void BlockChecked(const std::shared_ptr<const CBlock>&, const BlockValidationState&) {}
 156      /**
 157       * Notifies listeners that a block which builds directly on our current tip
 158       * has been received and connected to the headers tree, though not validated yet.
 159       */
 160      virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& block) {};
 161      friend class ValidationSignals;
 162      friend class ValidationInterfaceTest;
 163  };
 164  
 165  class ValidationSignalsImpl;
 166  class ValidationSignals {
 167  private:
 168      std::unique_ptr<ValidationSignalsImpl> m_internals;
 169  
 170  public:
 171      // The task runner will block validation if it calls its insert method's
 172      // func argument synchronously. In this class func contains a loop that
 173      // dispatches a single validation event to all subscribers sequentially.
 174      explicit ValidationSignals(std::unique_ptr<util::TaskRunnerInterface> task_runner);
 175  
 176      ~ValidationSignals();
 177  
 178      /** Call any remaining callbacks on the calling thread */
 179      void FlushBackgroundCallbacks();
 180  
 181      size_t CallbacksPending();
 182  
 183      /** Register subscriber */
 184      void RegisterValidationInterface(CValidationInterface* callbacks);
 185      /** Unregister subscriber. DEPRECATED. This is not safe to use when the RPC server or main message handler thread is running. */
 186      void UnregisterValidationInterface(CValidationInterface* callbacks);
 187      /** Unregister all subscribers */
 188      void UnregisterAllValidationInterfaces();
 189  
 190      // Alternate registration functions that release a shared_ptr after the last
 191      // notification is sent. These are useful for race-free cleanup, since
 192      // unregistration is nonblocking and can return before the last notification is
 193      // processed.
 194      /** Register subscriber */
 195      void RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks);
 196      /** Unregister subscriber */
 197      void UnregisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks);
 198  
 199      /**
 200       * Pushes a function to callback onto the notification queue, guaranteeing any
 201       * callbacks generated prior to now are finished when the function is called.
 202       *
 203       * Be very careful blocking on func to be called if any locks are held -
 204       * validation interface clients may not be able to make progress as they often
 205       * wait for things like cs_main, so blocking until func is called with cs_main
 206       * will result in a deadlock (that DEBUG_LOCKORDER will miss).
 207       */
 208      void CallFunctionInValidationInterfaceQueue(std::function<void ()> func);
 209  
 210      /**
 211       * This is a synonym for the following, which asserts certain locks are not
 212       * held:
 213       *     std::promise<void> promise;
 214       *     CallFunctionInValidationInterfaceQueue([&promise] {
 215       *         promise.set_value();
 216       *     });
 217       *     promise.get_future().wait();
 218       */
 219      void SyncWithValidationInterfaceQueue() LOCKS_EXCLUDED(cs_main);
 220  
 221      void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload);
 222      void ActiveTipChange(const CBlockIndex&, bool);
 223      void TransactionAddedToMempool(const NewMempoolTransactionInfo&, uint64_t mempool_sequence);
 224      void TransactionRemovedFromMempool(const CTransactionRef&, MemPoolRemovalReason, uint64_t mempool_sequence);
 225      void MempoolTransactionsRemovedForBlock(const std::vector<RemovedMempoolTransactionInfo>&, unsigned int nBlockHeight);
 226      void BlockConnected(const kernel::ChainstateRole&, std::shared_ptr<const CBlock>, const CBlockIndex* pindex);
 227      void BlockDisconnected(std::shared_ptr<const CBlock>, const CBlockIndex* pindex);
 228      void ChainStateFlushed(const kernel::ChainstateRole&, const CBlockLocator&);
 229      void BlockChecked(const std::shared_ptr<const CBlock>&, const BlockValidationState&);
 230      void NewPoWValidBlock(const CBlockIndex *, const std::shared_ptr<const CBlock>&);
 231  };
 232  
 233  #endif // BITCOIN_VALIDATIONINTERFACE_H
 234