mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-04 17:27:00 +00:00
214 lines
4.1 KiB
C++
214 lines
4.1 KiB
C++
#pragma once
|
|
|
|
#include <xrpl/beast/hash/hash_append.h>
|
|
#include <xrpl/beast/hash/uhash.h>
|
|
|
|
#include <boost/container/flat_set.hpp>
|
|
#include <boost/iterator/function_output_iterator.hpp>
|
|
|
|
#include <algorithm>
|
|
#include <map>
|
|
#include <ostream>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <type_traits>
|
|
|
|
namespace xrpl {
|
|
namespace test {
|
|
namespace csf {
|
|
|
|
//! A single transaction
|
|
class Tx
|
|
{
|
|
public:
|
|
using ID = std::uint32_t;
|
|
|
|
Tx(ID i) : id_{i}
|
|
{
|
|
}
|
|
|
|
template <typename T, typename = std::enable_if_t<std::is_same_v<T, Tx>>>
|
|
Tx(T const* t) : id_{t->id_}
|
|
{
|
|
}
|
|
|
|
ID const&
|
|
id() const
|
|
{
|
|
return id_;
|
|
}
|
|
|
|
bool
|
|
operator<(Tx const& o) const
|
|
{
|
|
return id_ < o.id_;
|
|
}
|
|
|
|
bool
|
|
operator==(Tx const& o) const
|
|
{
|
|
return id_ == o.id_;
|
|
}
|
|
|
|
private:
|
|
ID id_;
|
|
};
|
|
|
|
//!-------------------------------------------------------------------------
|
|
//! All sets of Tx are represented as a flat_set for performance.
|
|
using TxSetType = boost::container::flat_set<Tx>;
|
|
|
|
//! TxSet is a set of transactions to consider including in the ledger
|
|
class TxSet
|
|
{
|
|
public:
|
|
using ID = beast::uhash<>::result_type;
|
|
using Tx = csf::Tx;
|
|
|
|
static ID
|
|
calcID(TxSetType const& txs)
|
|
{
|
|
return beast::uhash<>{}(txs);
|
|
}
|
|
|
|
class MutableTxSet
|
|
{
|
|
friend class TxSet;
|
|
|
|
TxSetType txs_;
|
|
|
|
public:
|
|
MutableTxSet(TxSet const& s) : txs_{s.txs_}
|
|
{
|
|
}
|
|
|
|
bool
|
|
insert(Tx const& t)
|
|
{
|
|
return txs_.insert(t).second;
|
|
}
|
|
|
|
bool
|
|
erase(Tx::ID const& txId)
|
|
{
|
|
return txs_.erase(Tx{txId}) > 0;
|
|
}
|
|
};
|
|
|
|
TxSet() = default;
|
|
TxSet(TxSetType const& s) : txs_{s}, id_{calcID(txs_)}
|
|
{
|
|
}
|
|
|
|
TxSet(MutableTxSet&& m) // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
|
|
: txs_{m.txs_}, id_{calcID(txs_)}
|
|
{
|
|
}
|
|
|
|
bool
|
|
exists(Tx::ID const txId) const
|
|
{
|
|
auto it = txs_.find(Tx{txId});
|
|
return it != txs_.end();
|
|
}
|
|
|
|
Tx const*
|
|
find(Tx::ID const& txId) const
|
|
{
|
|
auto it = txs_.find(Tx{txId});
|
|
if (it != txs_.end())
|
|
return &(*it);
|
|
return nullptr;
|
|
}
|
|
|
|
TxSetType const&
|
|
txs() const
|
|
{
|
|
return txs_;
|
|
}
|
|
|
|
ID
|
|
id() const
|
|
{
|
|
return id_;
|
|
}
|
|
|
|
/** @return Map of Tx::ID that are missing. True means
|
|
it was in this set and not other. False means
|
|
it was in the other set and not this
|
|
*/
|
|
std::map<Tx::ID, bool>
|
|
compare(TxSet const& other) const
|
|
{
|
|
std::map<Tx::ID, bool> res;
|
|
|
|
auto populate_diffs = [&res](auto const& a, auto const& b, bool s) {
|
|
auto populator = [&](auto const& tx) { res[tx.id()] = s; };
|
|
std::set_difference(
|
|
a.begin(),
|
|
a.end(),
|
|
b.begin(),
|
|
b.end(),
|
|
boost::make_function_output_iterator(std::ref(populator)));
|
|
};
|
|
|
|
populate_diffs(txs_, other.txs_, true);
|
|
populate_diffs(other.txs_, txs_, false);
|
|
return res;
|
|
}
|
|
|
|
private:
|
|
//! The set contains the actual transactions
|
|
TxSetType txs_;
|
|
|
|
//! The unique ID of this tx set
|
|
ID id_{};
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Helper functions for debug printing
|
|
|
|
inline std::ostream&
|
|
operator<<(std::ostream& o, Tx const& t)
|
|
{
|
|
return o << t.id();
|
|
}
|
|
|
|
template <class T>
|
|
inline std::ostream&
|
|
operator<<(std::ostream& o, boost::container::flat_set<T> const& ts)
|
|
{
|
|
o << "{ ";
|
|
bool do_comma = false;
|
|
for (auto const& t : ts)
|
|
{
|
|
if (do_comma)
|
|
o << ", ";
|
|
else
|
|
do_comma = true;
|
|
o << t;
|
|
}
|
|
o << " }";
|
|
return o;
|
|
}
|
|
|
|
inline std::string
|
|
to_string(TxSetType const& txs)
|
|
{
|
|
std::stringstream ss;
|
|
ss << txs;
|
|
return ss.str();
|
|
}
|
|
|
|
template <class Hasher>
|
|
inline void
|
|
hash_append(Hasher& h, Tx const& tx)
|
|
{
|
|
using beast::hash_append;
|
|
hash_append(h, tx.id());
|
|
}
|
|
|
|
} // namespace csf
|
|
} // namespace test
|
|
} // namespace xrpl
|