validationinterface.h raw

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