mempoolbridge.h raw
1 // Copyright (c) 2026 The Limenka developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5 #ifndef LIMENKA_NODE_MEMPOOLBRIDGE_H
6 #define LIMENKA_NODE_MEMPOOLBRIDGE_H
7
8 #include <kernel/messagestartchars.h>
9 #include <netaddress.h>
10 #include <primitives/transaction.h>
11 #include <protocol.h>
12 #include <sync.h>
13 #include <validationinterface.h>
14
15 #include <atomic>
16 #include <map>
17 #include <memory>
18 #include <mutex>
19 #include <optional>
20 #include <set>
21 #include <thread>
22 #include <vector>
23
24 namespace node {
25 class NodeContext;
26 } // namespace node
27 namespace boost::asio { class io_context; }
28
29 namespace node {
30
31 // A foreign bitcoin-protocol network the bridge gossips with.
32 struct BridgeNetwork {
33 std::string name;
34 MessageStartChars magic{};
35 uint16_t default_port{0};
36 std::vector<CService> peers;
37 };
38
39 /** Cross-chain mempool gossip bridge.
40 *
41 * Connects limenka to foreign bitcoin-protocol networks (spamchain
42 * mainnet, blakecoin, whatever else forks from the same transaction
43 * format) and unifies their mempools: transactions received from a
44 * foreign peer are validated under limenka rules and enter the limenka
45 * mempool; transactions entering the limenka mempool (local or foreign)
46 * are announced to every foreign network. Blocks and headers are never
47 * requested or relayed - only transaction gossip crosses the boundary,
48 * so the fork's consensus is untouched while the transaction flow can no
49 * longer be separated from the parent chain's.
50 *
51 * Transactions that fail limenka validation (e.g. from a network whose
52 * UTXO root differs, like blakecoin's testnet4 lab) are logged and
53 * dropped, never forwarded - announcing invalid transactions would only
54 * get the bridge banned from the destination network.
55 */
56 class MempoolBridge final : public CValidationInterface,
57 public std::enable_shared_from_this<MempoolBridge>
58 {
59 public:
60 explicit MempoolBridge(node::NodeContext& node);
61 ~MempoolBridge();
62
63 // Parse a "-bridgepeer=net:host[:port]" argument.
64 static std::optional<std::pair<std::string, CService>> ParseBridgePeer(const std::string& spec);
65
66 bool Start(const std::vector<std::string>& peer_specs);
67 void Stop();
68
69 // CValidationInterface
70 void TransactionAddedToMempool(const NewMempoolTransactionInfo& tx, uint64_t mempool_sequence) override;
71
72 private:
73 class Peer;
74
75 node::NodeContext& m_node;
76 std::unique_ptr<boost::asio::io_context> m_io;
77 std::thread m_thread;
78 std::atomic<bool> m_running{false};
79
80 mutable RecursiveMutex m_net_mutex;
81 std::vector<BridgeNetwork> m_networks GUARDED_BY(m_net_mutex);
82 std::vector<std::shared_ptr<Peer>> m_peers GUARDED_BY(m_net_mutex);
83
84 // wtxids already announced per network (loop suppression).
85 mutable RecursiveMutex m_seen_mutex;
86 std::map<std::string, std::set<uint256>> m_seen GUARDED_BY(m_seen_mutex);
87
88 // Foreign transactions received (served back via getdata).
89 mutable RecursiveMutex m_cache_mutex;
90 std::map<uint256, CTransactionRef> m_tx_cache GUARDED_BY(m_cache_mutex);
91
92 void OnForeignTx(const std::string& from_network, CTransactionRef tx);
93 void AnnounceToNetwork(const BridgeNetwork& net, const CTransactionRef& tx, const uint256& wtxid);
94 bool NoteSeen(const std::string& network, const uint256& wtxid);
95 void MaintainConnections();
96
97 // Transaction lookup for getdata serving (bridge cache + limenka mempool).
98 bool HasTx(const uint256& hash) const;
99 CTransactionRef GetTx(const uint256& hash) const;
100 };
101
102 } // namespace node
103
104 #endif // LIMENKA_NODE_MEMPOOLBRIDGE_H
105