6#ifndef ALT_INTEGRATION_VERIBLOCK_MEMPOOL_HPP
7#define ALT_INTEGRATION_VERIBLOCK_MEMPOOL_HPP
11#include <unordered_map>
14#include "blockchain/alt_block_tree.hpp"
15#include "blockchain/mempool_block_tree.hpp"
16#include "entities/popdata.hpp"
17#include "mempool_result.hpp"
20#include "value_sorted_map.hpp"
21#include "veriblock/pop/assert.hpp"
22#include "veriblock/pop/json.hpp"
23#include "veriblock/pop/validation_state.hpp"
42 enum Status { VALID = 0, FAILED_STATEFUL = 1, FAILED_STATELESS = 2 };
46 Status status = VALID;
53 state,
"SubmitResult can be implicitly constructed from bool=true");
58 operator bool()
const {
return isAccepted(); }
60 bool isAccepted()
const {
61 return status == VALID || status == FAILED_STATEFUL;
64 bool isValid()
const {
return status == VALID; }
66 bool isFailedStateless()
const {
return status == FAILED_STATELESS; }
68 bool isFailedStateful()
const {
return status == FAILED_STATEFUL; }
73 template <
typename Payload>
75 std::unordered_map<typename Payload::id_t, std::shared_ptr<Payload>>;
77 template <
typename Payload>
78 using payload_value_sorted_map =
79 ValueSortedMap<typename Payload::id_t, std::shared_ptr<Payload>>;
81 using vbk_map_t = payload_map<VbkBlock>;
82 using atv_map_t = payload_map<ATV>;
83 using vtb_map_t = payload_map<VTB>;
84 using relations_map_t = payload_map<VbkPayloadsRelations>;
86 using vbk_value_sorted_map_t = payload_value_sorted_map<VbkBlock>;
87 using vtb_value_sorted_map_t = payload_value_sorted_map<VTB>;
88 using atv_value_sorted_map_t = payload_value_sorted_map<ATV>;
102 template <
typename T,
103 typename =
typename std::enable_if<IsPopPayload<T>::value>::type>
104 VBK_CHECK_RETURN
bool isKnown(
const typename T::id_t&
id,
105 const bool onlyInMempool =
false)
const {
107 auto* inmempool = get<T>(
id);
108 if (inmempool !=
nullptr) {
117 const std::vector<uint8_t> v(
id.begin(),
id.end());
119 auto& tree = mempool_tree_.alt();
120 auto& fpl = tree.getFinalizedPayloadsIndex();
121 const auto* blockhash = fpl.find(v);
122 if (blockhash !=
nullptr) {
128 auto& pl = tree.getPayloadsIndex();
130 const auto& set = pl.find(v);
136 for (
const auto& hash : set) {
137 const auto* candidate = tree.getBlockIndex(hash);
141 VBK_ASSERT_MSG(candidate !=
nullptr, candidate->toPrettyString());
142 if (tree.getBestChain().contains(candidate)) {
153 template <
typename T,
154 typename =
typename std::enable_if<IsPopPayload<T>::value>::type>
155 VBK_CHECK_RETURN
const T*
get(
const typename T::id_t&
id)
const {
156 const auto& map = getMap<T>();
157 auto it = map.find(
id);
158 if (it != map.end()) {
159 return it->second.get();
162 const auto& inflight = getInFlightMap<T>();
163 auto it2 = inflight.find(
id);
164 if (it2 != inflight.end()) {
165 return it2->second.get();
189 template <
typename T,
190 typename =
typename std::enable_if<IsPopPayload<T>::value>::type>
192 bool doIsBlockOldCheck,
197 return {FAILED_STATELESS,
198 state.Invalid(
"pop-mempool-submit-deserialize")};
201 return submit<T>(payload, doIsBlockOldCheck, state);
222 template <
typename T,
223 typename =
typename std::enable_if<IsPopPayload<T>::value>::type>
225 bool doIsBlockOldCheck,
227 return submit<T>(std::make_shared<T>(pl), doIsBlockOldCheck, state);
247 template <
typename T,
248 typename =
typename std::enable_if<IsPopPayload<T>::value>::type>
250 bool doIsBlockOldCheck,
254 (void)doIsBlockOldCheck;
255 static_assert(
sizeof(T) == 0,
"Undefined type used in MemPool::submit");
260 template <
typename T,
261 typename =
typename std::enable_if<IsPopPayload<T>::value>::type>
262 const payload_map<T>& getMap()
const {
263 static_assert(
sizeof(T) == 0,
"Undefined type used in MemPool::getMap");
267 template <
typename T,
268 typename =
typename std::enable_if<IsPopPayload<T>::value>::type>
269 const payload_value_sorted_map<T>& getInFlightMap()
const {
270 static_assert(
sizeof(T) == 0,
271 "Undefined type used in MemPool::getInFlightMap");
274 std::vector<BtcBlock::hash_t> getMissingBtcBlocks()
const;
327 template <
typename T,
328 typename =
typename std::enable_if<IsPopPayload<T>::value>::type>
330 auto& sig = getSignal<T>();
331 return sig.connect(f);
342 MemPoolBlockTree mempool_tree_;
344 relations_map_t relations_;
345 vbk_map_t vbkblocks_;
346 atv_map_t stored_atvs_;
347 vtb_map_t stored_vtbs_;
349 atv_value_sorted_map_t atvs_in_flight_{
350 [](
const std::shared_ptr<ATV>& v1,
351 const std::shared_ptr<ATV>& v2) ->
bool {
352 return v1->blockOfProof.getHeight() < v2->blockOfProof.getHeight();
354 vtb_value_sorted_map_t vtbs_in_flight_{
355 [](
const std::shared_ptr<VTB>& v1,
356 const std::shared_ptr<VTB>& v2) ->
bool {
357 return v1->containingBlock.getHeight() <
358 v2->containingBlock.getHeight();
360 vbk_value_sorted_map_t vbkblocks_in_flight_{
361 [](
const std::shared_ptr<VbkBlock>& v1,
362 const std::shared_ptr<VbkBlock>& v2) ->
bool {
363 return v1->getHeight() < v2->getHeight();
366 VbkPayloadsRelations& getOrPutVbkRelation(
367 const std::shared_ptr<VbkBlock>& block);
369 void tryConnectPayloads();
371 template <
typename T>
372 void makePayloadConnected(
const std::shared_ptr<T>& t) {
373 auto& signal = getSignal<T>();
374 auto& inflight = getInFlightMapMut<T>();
375 auto& connected = getMapMut<T>();
377 auto id = t->getId();
383 template <
typename POP>
384 void cleanupStale(std::set<std::shared_ptr<POP>,
385 VbkPayloadsRelations::AtvCombinedComparator>& c,
386 std::function<
void(POP&)> remove) {
387 for (
auto it = c.begin(); it != c.end();) {
389 ValidationState state;
390 auto valid = mempool_tree_.checkContextually(pl, state);
391 it = !valid ? (remove(pl), c.erase(it)) : std::next(it);
395 template <
typename POP>
396 void cleanupStale(std::vector<std::shared_ptr<POP>>& c,
397 std::function<
void(POP&)> remove) {
398 for (
auto it = c.begin(); it != c.end();) {
400 ValidationState state;
401 auto valid = mempool_tree_.checkContextually(pl, state);
402 it = !valid ? (remove(pl), c.erase(it)) : std::next(it);
406 template <
typename POP>
407 void cleanupStale(payload_value_sorted_map<POP>& c) {
408 for (
auto it = c.begin(); it != c.end();) {
409 auto& pl = *it->second;
410 ValidationState state;
411 auto valid = mempool_tree_.checkContextually(pl, state);
412 it = !valid ? c.erase(it) : std::next(it);
416 template <
typename Pop>
417 signals::Signal<void(
const Pop&)>& getSignal() {
418 static_assert(
sizeof(Pop) == 0,
"Unknown type in getSignal");
422 template <
typename T>
423 payload_map<T>& getMapMut() {
424 return const_cast<payload_map<T>&
>(this->getMap<T>());
428 template <
typename T>
429 payload_value_sorted_map<T>& getInFlightMapMut() {
430 return const_cast<payload_value_sorted_map<T>&
>(this->getInFlightMap<T>());
442template <>
const MemPool::payload_map<VbkBlock>& MemPool::getMap()
const;
444template <>
const MemPool::payload_map<ATV>& MemPool::getMap()
const;
446template <>
const MemPool::payload_map<VTB>& MemPool::getMap()
const;
448template<>
const MemPool::payload_value_sorted_map<VbkBlock>& MemPool::getInFlightMap()
const;
450template<>
const MemPool::payload_value_sorted_map<ATV>& MemPool::getInFlightMap()
const;
452template<>
const MemPool::payload_value_sorted_map<VTB>& MemPool::getInFlightMap()
const;
454template <> signals::Signal<void(
const ATV&)>& MemPool::getSignal();
456template <> signals::Signal<void(
const VTB&)>& MemPool::getSignal();
458template <> signals::Signal<void(
const VbkBlock&)>& MemPool::getSignal();
464template <
typename Value,
typename T>
465inline void mapToJson(Value& obj,
467 const std::string& key,
468 bool verbose =
false) {
469 auto arr = json::makeEmptyArray<Value>();
470 for (
auto& p : mp.getMap<T>()) {
472 json::arrayPushBack(arr, ToJSON<Value>(*p.second));
474 json::arrayPushBack(arr, ToJSON<Value>(p.first));
477 for (
auto& p : mp.getInFlightMap<T>()) {
479 json::arrayPushBack(arr, ToJSON<Value>(*p.second));
481 json::arrayPushBack(arr, ToJSON<Value>(p.first));
484 json::putKV(obj, key, arr);
489template <
typename Value>
490Value ToJSON(
const MemPool& mp,
bool verbose =
false) {
491 auto obj = json::makeEmptyObject<Value>();
493 detail::mapToJson<Value, VbkBlock>(obj, mp,
"vbkblocks", verbose);
494 detail::mapToJson<Value, ATV>(obj, mp,
"atvs", verbose);
495 detail::mapToJson<Value, VTB>(obj, mp,
"vtbs", verbose);
Class that is used for storing validation state.
bool DeserializeFromVbkEncoding(ReadStream &stream, AltBlockAddon &out, ValidationState &state)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Represents simplified view on Altchain's block tree, maintains VBK tree and BTC tree.
Result of submission to mempool.
Data structure, that stores in memory all valid payloads (ATV, VTB, VbkBlock) submitted by other peer...
VBK_CHECK_RETURN PopData generatePopData()
(POW) Miners should execute this to get POP content for "next block".
void removeAll(const PopData &popData)
Remove payloads from mempool by their IDs.
VBK_CHECK_RETURN const T * get(const typename T::id_t &id) const
getter for payloads stored in mempool
void clear()
Clear mempool from all payloads.
signals::Signal< void(const VTB &atv)> on_vtb_accepted
fires when new valid VTB is accepted to mempool
VBK_CHECK_RETURN SubmitResult submit(Slice< const uint8_t > bytes, bool doIsBlockOldCheck, ValidationState &state)
Add new payload to mempool.
size_t onAccepted(std::function< void(const T &p)> f)
Subscribe on "accepted" event - fires whenever new payload is added into mempool.
VBK_CHECK_RETURN SubmitResult submit(const std::shared_ptr< T > &pl, bool doIsBlockOldCheck, ValidationState &state)
Add new payload to mempool.
VBK_CHECK_RETURN bool isKnown(const typename T::id_t &id, const bool onlyInMempool=false) const
Use this method to determine if payload of type T with id id is already known to active chain.
signals::Signal< void(const VbkBlock &atv)> on_vbkblock_accepted
fires when new valid VbkBlock is accepted to mempool
void cleanUp()
Remove paylaods that are statefully invalid anymore (duplicated, staled payloads)
VBK_CHECK_RETURN PopData generatePopData(const std::function< void(const ATV &, const ValidationState &)> &onATV, const std::function< void(const VTB &, const ValidationState &)> &onVTB, const std::function< void(const VbkBlock &, const ValidationState &)> &onVBK)
This is an overloaded member function, provided for convenience. It differs from the above function o...
VBK_CHECK_RETURN SubmitResult submit(const T &pl, bool doIsBlockOldCheck, ValidationState &state)
Add new payload to mempool.
signals::Signal< void(const ATV &atv)> on_atv_accepted
fires when new valid ATV is accepted to mempool
Represents ALT block body of POP-related info.
Binary reading stream, that is useful during binary deserialization.
Non-owning contiguous array.
Veriblock to Bitcoin publication, committed to Veriblock blockchain in containingBlock.