// Copyright (c) 2026 The Limenka developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef LIMENKA_NODE_MEMPOOLBRIDGE_H #define LIMENKA_NODE_MEMPOOLBRIDGE_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace node { class NodeContext; } // namespace node namespace boost::asio { class io_context; } namespace node { // A foreign bitcoin-protocol network the bridge gossips with. struct BridgeNetwork { std::string name; MessageStartChars magic{}; uint16_t default_port{0}; std::vector peers; }; /** Cross-chain mempool gossip bridge. * * Connects limenka to foreign bitcoin-protocol networks (spamchain * mainnet, blakecoin, whatever else forks from the same transaction * format) and unifies their mempools: transactions received from a * foreign peer are validated under limenka rules and enter the limenka * mempool; transactions entering the limenka mempool (local or foreign) * are announced to every foreign network. Blocks and headers are never * requested or relayed - only transaction gossip crosses the boundary, * so the fork's consensus is untouched while the transaction flow can no * longer be separated from the parent chain's. * * Transactions that fail limenka validation (e.g. from a network whose * UTXO root differs, like blakecoin's testnet4 lab) are logged and * dropped, never forwarded - announcing invalid transactions would only * get the bridge banned from the destination network. */ class MempoolBridge final : public CValidationInterface, public std::enable_shared_from_this { public: explicit MempoolBridge(node::NodeContext& node); ~MempoolBridge(); // Parse a "-bridgepeer=net:host[:port]" argument. static std::optional> ParseBridgePeer(const std::string& spec); bool Start(const std::vector& peer_specs); void Stop(); // CValidationInterface void TransactionAddedToMempool(const NewMempoolTransactionInfo& tx, uint64_t mempool_sequence) override; private: class Peer; node::NodeContext& m_node; std::unique_ptr m_io; std::thread m_thread; std::atomic m_running{false}; mutable RecursiveMutex m_net_mutex; std::vector m_networks GUARDED_BY(m_net_mutex); std::vector> m_peers GUARDED_BY(m_net_mutex); // wtxids already announced per network (loop suppression). mutable RecursiveMutex m_seen_mutex; std::map> m_seen GUARDED_BY(m_seen_mutex); // Foreign transactions received (served back via getdata). mutable RecursiveMutex m_cache_mutex; std::map m_tx_cache GUARDED_BY(m_cache_mutex); void OnForeignTx(const std::string& from_network, CTransactionRef tx); void AnnounceToNetwork(const BridgeNetwork& net, const CTransactionRef& tx, const uint256& wtxid); bool NoteSeen(const std::string& network, const uint256& wtxid); void MaintainConnections(); // Transaction lookup for getdata serving (bridge cache + limenka mempool). bool HasTx(const uint256& hash) const; CTransactionRef GetTx(const uint256& hash) const; }; } // namespace node #endif // LIMENKA_NODE_MEMPOOLBRIDGE_H