mirror of
https://github.com/XRPLF/rippled.git
synced 2026-02-12 09:52:28 +00:00
Compare commits
26 Commits
tapanito/t
...
bthomee/ke
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
578a9853f2 | ||
|
|
a3f5a05f95 | ||
|
|
02db2943f3 | ||
|
|
ef284692db | ||
|
|
e11f6190b7 | ||
|
|
803cd100f3 | ||
|
|
9639b79155 | ||
|
|
eabd485927 | ||
|
|
f3ea3e9646 | ||
|
|
4306d9ccc3 | ||
|
|
1a4d9732ca | ||
|
|
aad6edb6b1 | ||
|
|
a4a1c4eecf | ||
|
|
fca6a8768f | ||
|
|
d96c4164b9 | ||
|
|
965fc75e8a | ||
|
|
2fa1c711d3 | ||
|
|
4650e7d2c6 | ||
|
|
a213127852 | ||
|
|
6e7537dada | ||
|
|
0777f7c64b | ||
|
|
39bfcaf95c | ||
|
|
61c9a19868 | ||
|
|
d01851bc5a | ||
|
|
d1703842e7 | ||
|
|
8d31b1739d |
@@ -4,14 +4,11 @@ Loop: test.jtx test.toplevel
|
||||
Loop: test.jtx test.unit_test
|
||||
test.unit_test == test.jtx
|
||||
|
||||
Loop: xrpld.app xrpld.core
|
||||
xrpld.app > xrpld.core
|
||||
|
||||
Loop: xrpld.app xrpld.overlay
|
||||
xrpld.overlay > xrpld.app
|
||||
|
||||
Loop: xrpld.app xrpld.peerfinder
|
||||
xrpld.peerfinder ~= xrpld.app
|
||||
xrpld.peerfinder == xrpld.app
|
||||
|
||||
Loop: xrpld.app xrpld.rpc
|
||||
xrpld.rpc > xrpld.app
|
||||
|
||||
@@ -17,12 +17,15 @@ libxrpl.nodestore > xrpl.protocol
|
||||
libxrpl.protocol > xrpl.basics
|
||||
libxrpl.protocol > xrpl.json
|
||||
libxrpl.protocol > xrpl.protocol
|
||||
libxrpl.rdb > xrpl.basics
|
||||
libxrpl.rdb > xrpl.rdb
|
||||
libxrpl.resource > xrpl.basics
|
||||
libxrpl.resource > xrpl.json
|
||||
libxrpl.resource > xrpl.resource
|
||||
libxrpl.server > xrpl.basics
|
||||
libxrpl.server > xrpl.json
|
||||
libxrpl.server > xrpl.protocol
|
||||
libxrpl.server > xrpl.rdb
|
||||
libxrpl.server > xrpl.server
|
||||
libxrpl.shamap > xrpl.basics
|
||||
libxrpl.shamap > xrpl.protocol
|
||||
@@ -41,7 +44,9 @@ test.app > xrpl.json
|
||||
test.app > xrpl.ledger
|
||||
test.app > xrpl.nodestore
|
||||
test.app > xrpl.protocol
|
||||
test.app > xrpl.rdb
|
||||
test.app > xrpl.resource
|
||||
test.app > xrpl.server
|
||||
test.basics > test.jtx
|
||||
test.basics > test.unit_test
|
||||
test.basics > xrpl.basics
|
||||
@@ -67,6 +72,7 @@ test.core > xrpl.basics
|
||||
test.core > xrpl.core
|
||||
test.core > xrpld.core
|
||||
test.core > xrpl.json
|
||||
test.core > xrpl.rdb
|
||||
test.core > xrpl.server
|
||||
test.csf > xrpl.basics
|
||||
test.csf > xrpld.consensus
|
||||
@@ -95,8 +101,8 @@ test.nodestore > test.jtx
|
||||
test.nodestore > test.toplevel
|
||||
test.nodestore > test.unit_test
|
||||
test.nodestore > xrpl.basics
|
||||
test.nodestore > xrpld.core
|
||||
test.nodestore > xrpl.nodestore
|
||||
test.nodestore > xrpl.rdb
|
||||
test.overlay > test.jtx
|
||||
test.overlay > test.toplevel
|
||||
test.overlay > test.unit_test
|
||||
@@ -154,6 +160,7 @@ tests.libxrpl > xrpl.net
|
||||
xrpl.core > xrpl.basics
|
||||
xrpl.core > xrpl.json
|
||||
xrpl.core > xrpl.ledger
|
||||
xrpl.core > xrpl.protocol
|
||||
xrpl.json > xrpl.basics
|
||||
xrpl.ledger > xrpl.basics
|
||||
xrpl.ledger > xrpl.protocol
|
||||
@@ -162,12 +169,16 @@ xrpl.nodestore > xrpl.basics
|
||||
xrpl.nodestore > xrpl.protocol
|
||||
xrpl.protocol > xrpl.basics
|
||||
xrpl.protocol > xrpl.json
|
||||
xrpl.rdb > xrpl.basics
|
||||
xrpl.rdb > xrpl.core
|
||||
xrpl.resource > xrpl.basics
|
||||
xrpl.resource > xrpl.json
|
||||
xrpl.resource > xrpl.protocol
|
||||
xrpl.server > xrpl.basics
|
||||
xrpl.server > xrpl.core
|
||||
xrpl.server > xrpl.json
|
||||
xrpl.server > xrpl.protocol
|
||||
xrpl.server > xrpl.rdb
|
||||
xrpl.shamap > xrpl.basics
|
||||
xrpl.shamap > xrpl.nodestore
|
||||
xrpl.shamap > xrpl.protocol
|
||||
@@ -176,12 +187,15 @@ xrpld.app > xrpl.basics
|
||||
xrpld.app > xrpl.core
|
||||
xrpld.app > xrpld.conditions
|
||||
xrpld.app > xrpld.consensus
|
||||
xrpld.app > xrpld.core
|
||||
xrpld.app > xrpl.json
|
||||
xrpld.app > xrpl.ledger
|
||||
xrpld.app > xrpl.net
|
||||
xrpld.app > xrpl.nodestore
|
||||
xrpld.app > xrpl.protocol
|
||||
xrpld.app > xrpl.rdb
|
||||
xrpld.app > xrpl.resource
|
||||
xrpld.app > xrpl.server
|
||||
xrpld.app > xrpl.shamap
|
||||
xrpld.conditions > xrpl.basics
|
||||
xrpld.conditions > xrpl.protocol
|
||||
@@ -193,6 +207,7 @@ xrpld.core > xrpl.core
|
||||
xrpld.core > xrpl.json
|
||||
xrpld.core > xrpl.net
|
||||
xrpld.core > xrpl.protocol
|
||||
xrpld.core > xrpl.rdb
|
||||
xrpld.overlay > xrpl.basics
|
||||
xrpld.overlay > xrpl.core
|
||||
xrpld.overlay > xrpld.core
|
||||
@@ -204,6 +219,7 @@ xrpld.overlay > xrpl.server
|
||||
xrpld.peerfinder > xrpl.basics
|
||||
xrpld.peerfinder > xrpld.core
|
||||
xrpld.peerfinder > xrpl.protocol
|
||||
xrpld.peerfinder > xrpl.rdb
|
||||
xrpld.perflog > xrpl.basics
|
||||
xrpld.perflog > xrpl.core
|
||||
xrpld.perflog > xrpld.rpc
|
||||
|
||||
@@ -84,9 +84,6 @@ add_module(xrpl net)
|
||||
target_link_libraries(xrpl.libxrpl.net PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol
|
||||
xrpl.libxrpl.resource)
|
||||
|
||||
add_module(xrpl server)
|
||||
target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol)
|
||||
|
||||
add_module(xrpl nodestore)
|
||||
target_link_libraries(xrpl.libxrpl.nodestore PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol)
|
||||
|
||||
@@ -94,8 +91,15 @@ add_module(xrpl shamap)
|
||||
target_link_libraries(xrpl.libxrpl.shamap PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.crypto xrpl.libxrpl.protocol
|
||||
xrpl.libxrpl.nodestore)
|
||||
|
||||
add_module(xrpl rdb)
|
||||
target_link_libraries(xrpl.libxrpl.rdb PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.core)
|
||||
|
||||
add_module(xrpl server)
|
||||
target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol xrpl.libxrpl.core xrpl.libxrpl.rdb)
|
||||
|
||||
add_module(xrpl ledger)
|
||||
target_link_libraries(xrpl.libxrpl.ledger PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol)
|
||||
target_link_libraries(xrpl.libxrpl.ledger PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol
|
||||
xrpl.libxrpl.rdb)
|
||||
|
||||
add_library(xrpl.libxrpl)
|
||||
set_target_properties(xrpl.libxrpl PROPERTIES OUTPUT_NAME xrpl)
|
||||
@@ -113,13 +117,14 @@ target_link_modules(
|
||||
core
|
||||
crypto
|
||||
json
|
||||
ledger
|
||||
net
|
||||
nodestore
|
||||
protocol
|
||||
rdb
|
||||
resource
|
||||
server
|
||||
nodestore
|
||||
shamap
|
||||
net
|
||||
ledger)
|
||||
shamap)
|
||||
|
||||
# All headers in libxrpl are in modules.
|
||||
# Uncomment this stanza if you have not yet moved new headers into a module.
|
||||
|
||||
@@ -23,6 +23,7 @@ install(TARGETS common
|
||||
xrpl.libxrpl.core
|
||||
xrpl.libxrpl.crypto
|
||||
xrpl.libxrpl.json
|
||||
xrpl.libxrpl.rdb
|
||||
xrpl.libxrpl.ledger
|
||||
xrpl.libxrpl.net
|
||||
xrpl.libxrpl.nodestore
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <xrpl/basics/TaggedCache.h>
|
||||
#include <xrpl/ledger/CachedSLEs.h>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
// Forward declarations
|
||||
@@ -18,6 +20,10 @@ namespace perf {
|
||||
class PerfLog;
|
||||
}
|
||||
|
||||
// This is temporary until we migrate all code to use ServiceRegistry.
|
||||
class Application;
|
||||
|
||||
// Forward declarations
|
||||
class AcceptedLedger;
|
||||
class AmendmentTable;
|
||||
class Cluster;
|
||||
@@ -194,6 +200,24 @@ public:
|
||||
|
||||
virtual perf::PerfLog&
|
||||
getPerfLog() = 0;
|
||||
|
||||
// Configuration and state
|
||||
virtual bool
|
||||
isStopping() const = 0;
|
||||
|
||||
virtual beast::Journal
|
||||
journal(std::string const& name) = 0;
|
||||
|
||||
virtual boost::asio::io_context&
|
||||
getIOContext() = 0;
|
||||
|
||||
virtual Logs&
|
||||
logs() = 0;
|
||||
|
||||
// Temporary: Get the underlying Application for functions that haven't
|
||||
// been migrated yet. This should be removed once all code is migrated.
|
||||
virtual Application&
|
||||
app() = 0;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
16
include/xrpl/core/StartUpType.h
Normal file
16
include/xrpl/core/StartUpType.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <iosfwd>
|
||||
#include <type_traits>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
enum class StartUpType { FRESH, NORMAL, LOAD, LOAD_FILE, REPLAY, NETWORK };
|
||||
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& os, StartUpType const& type)
|
||||
{
|
||||
return os << static_cast<std::underlying_type_t<StartUpType>>(type);
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -76,16 +76,16 @@ public:
|
||||
If the object is not found or an error is encountered, the
|
||||
result will indicate the condition.
|
||||
@note This will be called concurrently.
|
||||
@param key A pointer to the key data.
|
||||
@param hash The hash of the object.
|
||||
@param pObject [out] The created object if successful.
|
||||
@return The result of the operation.
|
||||
*/
|
||||
virtual Status
|
||||
fetch(void const* key, std::shared_ptr<NodeObject>* pObject) = 0;
|
||||
fetch(uint256 const& hash, std::shared_ptr<NodeObject>* pObject) = 0;
|
||||
|
||||
/** Fetch a batch synchronously. */
|
||||
virtual std::pair<std::vector<std::shared_ptr<NodeObject>>, Status>
|
||||
fetchBatch(std::vector<uint256 const*> const& hashes) = 0;
|
||||
fetchBatch(std::vector<uint256> const& hashes) = 0;
|
||||
|
||||
/** Store a single object.
|
||||
Depending on the implementation this may happen immediately
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
// Add new amendments to the top of this list.
|
||||
// Keep it sorted in reverse chronological order.
|
||||
|
||||
XRPL_FIX (PermissionedDomainInvariant, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (ExpiredNFTokenOfferRemoval, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (BatchInnerSigs, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(LendingProtocol, Supported::yes, VoteBehavior::DefaultNo)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* To ease maintenance, you may replace any unneeded values with "..."
|
||||
* e.g. #define TRANSACTION(tag, value, name, ...)
|
||||
*
|
||||
* You must define a transactor class in the `xrpl` namespace named `name`,
|
||||
* You must define a transactor class in the `ripple` namespace named `name`,
|
||||
* and include its header alongside the TRANSACTOR definition using this
|
||||
* format:
|
||||
* #if TRANSACTION_INCLUDE
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/main/DBInit.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/SociDB.h>
|
||||
|
||||
#include <xrpl/core/PerfLog.h>
|
||||
#include <xrpl/core/StartUpType.h>
|
||||
#include <xrpl/rdb/DBInit.h>
|
||||
#include <xrpl/rdb/SociDB.h>
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
@@ -68,7 +67,7 @@ public:
|
||||
{
|
||||
explicit Setup() = default;
|
||||
|
||||
Config::StartUpType startUp = Config::NORMAL;
|
||||
StartUpType startUp = StartUpType::NORMAL;
|
||||
bool standAlone = false;
|
||||
boost::filesystem::path dataDir;
|
||||
// Indicates whether or not to return the `globalPragma`
|
||||
@@ -105,8 +104,8 @@ public:
|
||||
beast::Journal journal)
|
||||
// Use temporary files or regular DB files?
|
||||
: DatabaseCon(
|
||||
setup.standAlone && setup.startUp != Config::LOAD && setup.startUp != Config::LOAD_FILE &&
|
||||
setup.startUp != Config::REPLAY
|
||||
setup.standAlone && setup.startUp != StartUpType::LOAD && setup.startUp != StartUpType::LOAD_FILE &&
|
||||
setup.startUp != StartUpType::REPLAY
|
||||
? ""
|
||||
: (setup.dataDir / dbName),
|
||||
setup.commonPragma(),
|
||||
@@ -229,7 +228,4 @@ private:
|
||||
std::shared_ptr<Checkpointer>
|
||||
checkpointerFromId(std::uintptr_t id);
|
||||
|
||||
DatabaseCon::Setup
|
||||
setup_DatabaseCon(Config const& c, std::optional<beast::Journal> j = std::nullopt);
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -1,10 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/ledger/Ledger.h>
|
||||
#include <xrpld/app/misc/Manifest.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
#include <xrpld/peerfinder/detail/Store.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
#include <xrpl/server/Manifest.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/misc/Manifest.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
#include <xrpld/overlay/PeerReservationTable.h>
|
||||
#include <xrpl/core/PeerReservationTable.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
#include <xrpl/server/Manifest.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -29,7 +29,7 @@ DatabaseNodeImp::fetchNodeObject(uint256 const& hash, std::uint32_t, FetchReport
|
||||
|
||||
try
|
||||
{
|
||||
status = backend_->fetch(hash.data(), &nodeObject);
|
||||
status = backend_->fetch(hash, &nodeObject);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
@@ -62,18 +62,10 @@ DatabaseNodeImp::fetchBatch(std::vector<uint256> const& hashes)
|
||||
using namespace std::chrono;
|
||||
auto const before = steady_clock::now();
|
||||
|
||||
std::vector<uint256 const*> batch{};
|
||||
batch.reserve(hashes.size());
|
||||
for (size_t i = 0; i < hashes.size(); ++i)
|
||||
{
|
||||
auto const& hash = hashes[i];
|
||||
batch.push_back(&hash);
|
||||
}
|
||||
|
||||
// Get the node objects that match the hashes from the backend. To protect
|
||||
// against the backends returning fewer or more results than expected, the
|
||||
// container is resized to the number of hashes.
|
||||
auto results = backend_->fetchBatch(batch).first;
|
||||
auto results = backend_->fetchBatch(hashes).first;
|
||||
XRPL_ASSERT(
|
||||
results.size() == hashes.size() || results.empty(),
|
||||
"number of output objects either matches number of input hashes or is empty");
|
||||
|
||||
@@ -101,7 +101,7 @@ DatabaseRotatingImp::fetchNodeObject(uint256 const& hash, std::uint32_t, FetchRe
|
||||
std::shared_ptr<NodeObject> nodeObject;
|
||||
try
|
||||
{
|
||||
status = backend->fetch(hash.data(), &nodeObject);
|
||||
status = backend->fetch(hash, &nodeObject);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
|
||||
@@ -115,10 +115,9 @@ public:
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
Status
|
||||
fetch(void const* key, std::shared_ptr<NodeObject>* pObject) override
|
||||
fetch(uint256 const& hash, std::shared_ptr<NodeObject>* pObject) override
|
||||
{
|
||||
XRPL_ASSERT(db_, "xrpl::NodeStore::MemoryBackend::fetch : non-null database");
|
||||
uint256 const hash(uint256::fromVoid(key));
|
||||
|
||||
std::lock_guard _(db_->mutex);
|
||||
|
||||
@@ -133,14 +132,14 @@ public:
|
||||
}
|
||||
|
||||
std::pair<std::vector<std::shared_ptr<NodeObject>>, Status>
|
||||
fetchBatch(std::vector<uint256 const*> const& hashes) override
|
||||
fetchBatch(std::vector<uint256> const& hashes) override
|
||||
{
|
||||
std::vector<std::shared_ptr<NodeObject>> results;
|
||||
results.reserve(hashes.size());
|
||||
for (auto const& h : hashes)
|
||||
{
|
||||
std::shared_ptr<NodeObject> nObj;
|
||||
Status status = fetch(h->begin(), &nObj);
|
||||
Status status = fetch(h, &nObj);
|
||||
if (status != ok)
|
||||
results.push_back({});
|
||||
else
|
||||
|
||||
@@ -177,17 +177,17 @@ public:
|
||||
}
|
||||
|
||||
Status
|
||||
fetch(void const* key, std::shared_ptr<NodeObject>* pno) override
|
||||
fetch(uint256 const& hash, std::shared_ptr<NodeObject>* pno) override
|
||||
{
|
||||
Status status;
|
||||
pno->reset();
|
||||
nudb::error_code ec;
|
||||
db_.fetch(
|
||||
key,
|
||||
[key, pno, &status](void const* data, std::size_t size) {
|
||||
hash.data(),
|
||||
[hash, pno, &status](void const* data, std::size_t size) {
|
||||
nudb::detail::buffer bf;
|
||||
auto const result = nodeobject_decompress(data, size, bf);
|
||||
DecodedBlob decoded(key, result.first, result.second);
|
||||
DecodedBlob decoded(hash.data(), result.first, result.second);
|
||||
if (!decoded.wasOk())
|
||||
{
|
||||
status = dataCorrupt;
|
||||
@@ -205,14 +205,14 @@ public:
|
||||
}
|
||||
|
||||
std::pair<std::vector<std::shared_ptr<NodeObject>>, Status>
|
||||
fetchBatch(std::vector<uint256 const*> const& hashes) override
|
||||
fetchBatch(std::vector<uint256> const& hashes) override
|
||||
{
|
||||
std::vector<std::shared_ptr<NodeObject>> results;
|
||||
results.reserve(hashes.size());
|
||||
for (auto const& h : hashes)
|
||||
{
|
||||
std::shared_ptr<NodeObject> nObj;
|
||||
Status status = fetch(h->begin(), &nObj);
|
||||
Status status = fetch(h, &nObj);
|
||||
if (status != ok)
|
||||
results.push_back({});
|
||||
else
|
||||
|
||||
@@ -36,13 +36,13 @@ public:
|
||||
}
|
||||
|
||||
Status
|
||||
fetch(void const*, std::shared_ptr<NodeObject>*) override
|
||||
fetch(uint256 const&, std::shared_ptr<NodeObject>*) override
|
||||
{
|
||||
return notFound;
|
||||
}
|
||||
|
||||
std::pair<std::vector<std::shared_ptr<NodeObject>>, Status>
|
||||
fetchBatch(std::vector<uint256 const*> const& hashes) override
|
||||
fetchBatch(std::vector<uint256> const& hashes) override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ public:
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
Status
|
||||
fetch(void const* key, std::shared_ptr<NodeObject>* pObject) override
|
||||
fetch(uint256 const& hash, std::shared_ptr<NodeObject>* pObject) override
|
||||
{
|
||||
XRPL_ASSERT(m_db, "xrpl::NodeStore::RocksDBBackend::fetch : non-null database");
|
||||
pObject->reset();
|
||||
@@ -245,7 +245,7 @@ public:
|
||||
Status status(ok);
|
||||
|
||||
rocksdb::ReadOptions const options;
|
||||
rocksdb::Slice const slice(static_cast<char const*>(key), m_keyBytes);
|
||||
rocksdb::Slice const slice(reinterpret_cast<char const*>(hash.data()), m_keyBytes);
|
||||
|
||||
std::string string;
|
||||
|
||||
@@ -253,7 +253,7 @@ public:
|
||||
|
||||
if (getStatus.ok())
|
||||
{
|
||||
DecodedBlob decoded(key, string.data(), string.size());
|
||||
DecodedBlob decoded(hash.data(), string.data(), string.size());
|
||||
|
||||
if (decoded.wasOk())
|
||||
{
|
||||
@@ -288,14 +288,14 @@ public:
|
||||
}
|
||||
|
||||
std::pair<std::vector<std::shared_ptr<NodeObject>>, Status>
|
||||
fetchBatch(std::vector<uint256 const*> const& hashes) override
|
||||
fetchBatch(std::vector<uint256> const& hashes) override
|
||||
{
|
||||
std::vector<std::shared_ptr<NodeObject>> results;
|
||||
results.reserve(hashes.size());
|
||||
for (auto const& h : hashes)
|
||||
{
|
||||
std::shared_ptr<NodeObject> nObj;
|
||||
Status status = fetch(h->begin(), &nObj);
|
||||
Status status = fetch(h, &nObj);
|
||||
if (status != ok)
|
||||
results.push_back({});
|
||||
else
|
||||
|
||||
92
src/libxrpl/rdb/DatabaseCon.cpp
Normal file
92
src/libxrpl/rdb/DatabaseCon.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
#include <xrpl/rdb/SociDB.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class CheckpointersCollection
|
||||
{
|
||||
std::uintptr_t nextId_{0};
|
||||
// Mutex protects the CheckpointersCollection
|
||||
std::mutex mutex_;
|
||||
// Each checkpointer is given a unique id. All the checkpointers that are
|
||||
// part of a DatabaseCon are part of this collection. When the DatabaseCon
|
||||
// is destroyed, its checkpointer is removed from the collection
|
||||
std::unordered_map<std::uintptr_t, std::shared_ptr<Checkpointer>> checkpointers_;
|
||||
|
||||
public:
|
||||
std::shared_ptr<Checkpointer>
|
||||
fromId(std::uintptr_t id)
|
||||
{
|
||||
std::lock_guard l{mutex_};
|
||||
auto it = checkpointers_.find(id);
|
||||
if (it != checkpointers_.end())
|
||||
return it->second;
|
||||
return {};
|
||||
}
|
||||
|
||||
void
|
||||
erase(std::uintptr_t id)
|
||||
{
|
||||
std::lock_guard lock{mutex_};
|
||||
checkpointers_.erase(id);
|
||||
}
|
||||
|
||||
std::shared_ptr<Checkpointer>
|
||||
create(std::shared_ptr<soci::session> const& session, JobQueue& jobQueue, Logs& logs)
|
||||
{
|
||||
std::lock_guard lock{mutex_};
|
||||
auto const id = nextId_++;
|
||||
auto const r = makeCheckpointer(id, session, jobQueue, logs);
|
||||
checkpointers_[id] = r;
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
CheckpointersCollection checkpointers;
|
||||
|
||||
std::shared_ptr<Checkpointer>
|
||||
checkpointerFromId(std::uintptr_t id)
|
||||
{
|
||||
return checkpointers.fromId(id);
|
||||
}
|
||||
|
||||
DatabaseCon::~DatabaseCon()
|
||||
{
|
||||
if (checkpointer_)
|
||||
{
|
||||
checkpointers.erase(checkpointer_->id());
|
||||
|
||||
std::weak_ptr<Checkpointer> wk(checkpointer_);
|
||||
checkpointer_.reset();
|
||||
|
||||
// The references to our Checkpointer held by 'checkpointer_' and
|
||||
// 'checkpointers' have been removed, so if the use count is nonzero, a
|
||||
// checkpoint is currently in progress. Wait for it to end, otherwise
|
||||
// creating a new DatabaseCon to the same database may fail due to the
|
||||
// database being locked by our (now old) Checkpointer.
|
||||
while (wk.use_count())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<std::string> const> DatabaseCon::Setup::globalPragma;
|
||||
|
||||
void
|
||||
DatabaseCon::setupCheckpointing(JobQueue* q, Logs& l)
|
||||
{
|
||||
if (!q)
|
||||
Throw<std::logic_error>("No JobQueue");
|
||||
checkpointer_ = checkpointers.create(session_, *q, l);
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -3,12 +3,10 @@
|
||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
||||
#endif
|
||||
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
#include <xrpld/core/SociDB.h>
|
||||
|
||||
#include <xrpl/basics/ByteUtilities.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
#include <xrpl/rdb/SociDB.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <xrpld/app/rdb/State.h>
|
||||
#include <xrpl/server/State.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include <xrpld/app/rdb/Vacuum.h>
|
||||
#include <xrpl/server/Vacuum.h>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
bool
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <xrpld/app/rdb/Wallet.h>
|
||||
#include <xrpl/rdb/DBInit.h>
|
||||
#include <xrpl/server/Wallet.h>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
@@ -36,6 +36,12 @@ class Invariants_test : public beast::unit_test::suite
|
||||
// changes that will cause the check to fail.
|
||||
using Precheck = std::function<bool(test::jtx::Account const& a, test::jtx::Account const& b, ApplyContext& ac)>;
|
||||
|
||||
static FeatureBitset
|
||||
defaultAmendments()
|
||||
{
|
||||
return xrpl::test::jtx::testable_amendments() | featureInvariantsV1_1 | featureSingleAssetVault;
|
||||
}
|
||||
|
||||
/** Run a specific test case to put the ledger into a state that will be
|
||||
* detected by an invariant. Simulates the actions of a transaction that
|
||||
* would violate an invariant.
|
||||
@@ -62,10 +68,23 @@ class Invariants_test : public beast::unit_test::suite
|
||||
std::initializer_list<TER> ters = {tecINVARIANT_FAILED, tefINVARIANT_FAILED},
|
||||
Preclose const& preclose = {},
|
||||
TxAccount setTxAccount = TxAccount::None)
|
||||
{
|
||||
return doInvariantCheck(
|
||||
test::jtx::Env(*this, defaultAmendments()), expect_logs, precheck, fee, tx, ters, preclose, setTxAccount);
|
||||
}
|
||||
|
||||
void
|
||||
doInvariantCheck(
|
||||
test::jtx::Env&& env,
|
||||
std::vector<std::string> const& expect_logs,
|
||||
Precheck const& precheck,
|
||||
XRPAmount fee = XRPAmount{},
|
||||
STTx tx = STTx{ttACCOUNT_SET, [](STObject&) {}},
|
||||
std::initializer_list<TER> ters = {tecINVARIANT_FAILED, tefINVARIANT_FAILED},
|
||||
Preclose const& preclose = {},
|
||||
TxAccount setTxAccount = TxAccount::None)
|
||||
{
|
||||
using namespace test::jtx;
|
||||
FeatureBitset amendments = testable_amendments() | featureInvariantsV1_1 | featureSingleAssetVault;
|
||||
Env env{*this, amendments};
|
||||
|
||||
Account const A1{"A1"};
|
||||
Account const A2{"A2"};
|
||||
@@ -74,11 +93,28 @@ class Invariants_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(preclose(A1, A2, env));
|
||||
env.close();
|
||||
|
||||
if (setTxAccount != TxAccount::None)
|
||||
tx.setAccountID(sfAccount, setTxAccount == TxAccount::A1 ? A1.id() : A2.id());
|
||||
|
||||
return doInvariantCheck(std::move(env), A1, A2, expect_logs, precheck, fee, tx, ters);
|
||||
}
|
||||
|
||||
void
|
||||
doInvariantCheck(
|
||||
test::jtx::Env&& env,
|
||||
test::jtx::Account const& A1,
|
||||
test::jtx::Account const& A2,
|
||||
std::vector<std::string> const& expect_logs,
|
||||
Precheck const& precheck,
|
||||
XRPAmount fee = XRPAmount{},
|
||||
STTx tx = STTx{ttACCOUNT_SET, [](STObject&) {}},
|
||||
std::initializer_list<TER> ters = {tecINVARIANT_FAILED, tefINVARIANT_FAILED})
|
||||
{
|
||||
using namespace test::jtx;
|
||||
|
||||
OpenView ov{*env.current()};
|
||||
test::StreamSink sink{beast::severities::kWarning};
|
||||
beast::Journal jlog{sink};
|
||||
if (setTxAccount != TxAccount::None)
|
||||
tx.setAccountID(sfAccount, setTxAccount == TxAccount::A1 ? A1.id() : A2.id());
|
||||
ApplyContext ac{env.app(), ov, tx, tesSUCCESS, env.current()->fees().base, tapNONE, jlog};
|
||||
|
||||
BEAST_EXPECT(precheck(A1, A2, ac));
|
||||
@@ -91,19 +127,21 @@ class Invariants_test : public beast::unit_test::suite
|
||||
for (TER const& terExpect : ters)
|
||||
{
|
||||
terActual = ac.checkInvariants(terActual, fee);
|
||||
BEAST_EXPECT(terExpect == terActual);
|
||||
BEAST_EXPECTS(terExpect == terActual, std::to_string(TERtoInt(terActual)));
|
||||
auto const messages = sink.messages().str();
|
||||
BEAST_EXPECT(
|
||||
messages.starts_with("Invariant failed:") || messages.starts_with("Transaction caused an exception"));
|
||||
|
||||
if (terActual != tesSUCCESS)
|
||||
{
|
||||
BEAST_EXPECTS(
|
||||
messages.starts_with("Invariant failed:") ||
|
||||
messages.starts_with("Transaction caused an exception"),
|
||||
messages);
|
||||
}
|
||||
|
||||
// std::cerr << messages << '\n';
|
||||
for (auto const& m : expect_logs)
|
||||
{
|
||||
if (messages.find(m) == std::string::npos)
|
||||
{
|
||||
// uncomment if you want to log the invariant failure
|
||||
// std::cerr << " --> " << m << std::endl;
|
||||
fail();
|
||||
}
|
||||
BEAST_EXPECTS(messages.find(m) != std::string::npos, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1119,86 +1157,80 @@ class Invariants_test : public beast::unit_test::suite
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
static std::shared_ptr<SLE>
|
||||
createPermissionedDomain(
|
||||
ApplyContext& ac,
|
||||
std::shared_ptr<SLE>& sle,
|
||||
test::jtx::Account const& A1,
|
||||
test::jtx::Account const& A2)
|
||||
test::jtx::Account const& A2,
|
||||
std::uint32_t numCreds = 2,
|
||||
std::uint32_t seq = 10)
|
||||
{
|
||||
sle->setAccountID(sfOwner, A1);
|
||||
sle->setFieldU32(sfSequence, 10);
|
||||
Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), seq);
|
||||
auto sle = std::make_shared<SLE>(pdKeylet);
|
||||
|
||||
STArray credentials(sfAcceptedCredentials, 2);
|
||||
for (std::size_t n = 0; n < 2; ++n)
|
||||
sle->setAccountID(sfOwner, A1);
|
||||
sle->setFieldU32(sfSequence, seq);
|
||||
|
||||
if (numCreds)
|
||||
{
|
||||
auto cred = STObject::makeInnerObject(sfCredential);
|
||||
cred.setAccountID(sfIssuer, A2);
|
||||
auto credType = "cred_type" + std::to_string(n);
|
||||
cred.setFieldVL(sfCredentialType, Slice(credType.c_str(), credType.size()));
|
||||
credentials.push_back(std::move(cred));
|
||||
// This array is sorted naturally, but if you willing to change this
|
||||
// behavior don't forget to use credentials::makeSorted
|
||||
STArray credentials(sfAcceptedCredentials, numCreds);
|
||||
for (std::size_t n = 0; n < numCreds; ++n)
|
||||
{
|
||||
auto cred = STObject::makeInnerObject(sfCredential);
|
||||
cred.setAccountID(sfIssuer, A2);
|
||||
auto credType = "cred_type" + std::to_string(n);
|
||||
cred.setFieldVL(sfCredentialType, Slice(credType.c_str(), credType.size()));
|
||||
credentials.push_back(std::move(cred));
|
||||
}
|
||||
sle->setFieldArray(sfAcceptedCredentials, credentials);
|
||||
}
|
||||
sle->setFieldArray(sfAcceptedCredentials, credentials);
|
||||
|
||||
ac.view().insert(sle);
|
||||
return sle;
|
||||
};
|
||||
|
||||
void
|
||||
testPermissionedDomainInvariants()
|
||||
testPermissionedDomainInvariants(FeatureBitset features)
|
||||
{
|
||||
using namespace test::jtx;
|
||||
|
||||
testcase << "PermissionedDomain";
|
||||
doInvariantCheck(
|
||||
{{"permissioned domain with no rules."}},
|
||||
[](Account const& A1, Account const&, ApplyContext& ac) {
|
||||
Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10);
|
||||
auto slePd = std::make_shared<SLE>(pdKeylet);
|
||||
slePd->setAccountID(sfOwner, A1);
|
||||
slePd->setFieldU32(sfSequence, 10);
|
||||
bool const fixPDEnabled = features[fixPermissionedDomainInvariant];
|
||||
std::initializer_list<TER> badTers = {tecINVARIANT_FAILED, tecINVARIANT_FAILED};
|
||||
std::initializer_list<TER> failTers = {tecINVARIANT_FAILED, tefINVARIANT_FAILED};
|
||||
|
||||
ac.view().insert(slePd);
|
||||
return true;
|
||||
testcase << "PermissionedDomain" + std::string(fixPDEnabled ? " fix" : "");
|
||||
|
||||
doInvariantCheck(
|
||||
Env(*this, features),
|
||||
{{"permissioned domain with no rules."}},
|
||||
[](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
return createPermissionedDomain(ac, A1, A2, 0).get();
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject& tx) {}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}},
|
||||
fixPDEnabled ? failTers : badTers);
|
||||
|
||||
testcase << "PermissionedDomain 2";
|
||||
|
||||
auto constexpr tooBig = maxPermissionedDomainCredentialsArraySize + 1;
|
||||
doInvariantCheck(
|
||||
Env(*this, features),
|
||||
{{"permissioned domain bad credentials size " + std::to_string(tooBig)}},
|
||||
[](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10);
|
||||
auto slePd = std::make_shared<SLE>(pdKeylet);
|
||||
slePd->setAccountID(sfOwner, A1);
|
||||
slePd->setFieldU32(sfSequence, 10);
|
||||
|
||||
STArray credentials(sfAcceptedCredentials, tooBig);
|
||||
for (std::size_t n = 0; n < tooBig; ++n)
|
||||
{
|
||||
auto cred = STObject::makeInnerObject(sfCredential);
|
||||
cred.setAccountID(sfIssuer, A2);
|
||||
auto credType = std::string("cred_type") + std::to_string(n);
|
||||
cred.setFieldVL(sfCredentialType, Slice(credType.c_str(), credType.size()));
|
||||
credentials.push_back(std::move(cred));
|
||||
}
|
||||
slePd->setFieldArray(sfAcceptedCredentials, credentials);
|
||||
ac.view().insert(slePd);
|
||||
return true;
|
||||
return !!createPermissionedDomain(ac, A1, A2, tooBig);
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
fixPDEnabled ? failTers : badTers);
|
||||
|
||||
testcase << "PermissionedDomain 3";
|
||||
doInvariantCheck(
|
||||
Env(*this, features),
|
||||
{{"permissioned domain credentials aren't sorted"}},
|
||||
[](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10);
|
||||
auto slePd = std::make_shared<SLE>(pdKeylet);
|
||||
slePd->setAccountID(sfOwner, A1);
|
||||
slePd->setFieldU32(sfSequence, 10);
|
||||
auto slePd = createPermissionedDomain(ac, A1, A2, 0);
|
||||
|
||||
STArray credentials(sfAcceptedCredentials, 2);
|
||||
for (std::size_t n = 0; n < 2; ++n)
|
||||
@@ -1210,21 +1242,19 @@ class Invariants_test : public beast::unit_test::suite
|
||||
credentials.push_back(std::move(cred));
|
||||
}
|
||||
slePd->setFieldArray(sfAcceptedCredentials, credentials);
|
||||
ac.view().insert(slePd);
|
||||
ac.view().update(slePd);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
fixPDEnabled ? failTers : badTers);
|
||||
|
||||
testcase << "PermissionedDomain 4";
|
||||
doInvariantCheck(
|
||||
Env(*this, features),
|
||||
{{"permissioned domain credentials aren't unique"}},
|
||||
[](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10);
|
||||
auto slePd = std::make_shared<SLE>(pdKeylet);
|
||||
slePd->setAccountID(sfOwner, A1);
|
||||
slePd->setFieldU32(sfSequence, 10);
|
||||
auto slePd = createPermissionedDomain(ac, A1, A2, 0);
|
||||
|
||||
STArray credentials(sfAcceptedCredentials, 2);
|
||||
for (std::size_t n = 0; n < 2; ++n)
|
||||
@@ -1235,22 +1265,20 @@ class Invariants_test : public beast::unit_test::suite
|
||||
credentials.push_back(std::move(cred));
|
||||
}
|
||||
slePd->setFieldArray(sfAcceptedCredentials, credentials);
|
||||
ac.view().insert(slePd);
|
||||
ac.view().update(slePd);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject& tx) {}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}},
|
||||
fixPDEnabled ? failTers : badTers);
|
||||
|
||||
testcase << "PermissionedDomain Set 1";
|
||||
doInvariantCheck(
|
||||
Env(*this, features),
|
||||
{{"permissioned domain with no rules."}},
|
||||
[&](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10);
|
||||
auto slePd = std::make_shared<SLE>(pdKeylet);
|
||||
|
||||
// create PD
|
||||
createPermissionedDomain(ac, slePd, A1, A2);
|
||||
auto slePd = createPermissionedDomain(ac, A1, A2);
|
||||
|
||||
// update PD with empty rules
|
||||
{
|
||||
@@ -1262,18 +1290,16 @@ class Invariants_test : public beast::unit_test::suite
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject& tx) {}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}},
|
||||
fixPDEnabled ? failTers : badTers);
|
||||
|
||||
testcase << "PermissionedDomain Set 2";
|
||||
doInvariantCheck(
|
||||
Env(*this, features),
|
||||
{{"permissioned domain bad credentials size " + std::to_string(tooBig)}},
|
||||
[&](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10);
|
||||
auto slePd = std::make_shared<SLE>(pdKeylet);
|
||||
|
||||
// create PD
|
||||
createPermissionedDomain(ac, slePd, A1, A2);
|
||||
auto slePd = createPermissionedDomain(ac, A1, A2);
|
||||
|
||||
// update PD
|
||||
{
|
||||
@@ -1295,18 +1321,16 @@ class Invariants_test : public beast::unit_test::suite
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject& tx) {}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}},
|
||||
fixPDEnabled ? failTers : badTers);
|
||||
|
||||
testcase << "PermissionedDomain Set 3";
|
||||
doInvariantCheck(
|
||||
Env(*this, features),
|
||||
{{"permissioned domain credentials aren't sorted"}},
|
||||
[&](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10);
|
||||
auto slePd = std::make_shared<SLE>(pdKeylet);
|
||||
|
||||
// create PD
|
||||
createPermissionedDomain(ac, slePd, A1, A2);
|
||||
auto slePd = createPermissionedDomain(ac, A1, A2);
|
||||
|
||||
// update PD
|
||||
{
|
||||
@@ -1327,18 +1351,16 @@ class Invariants_test : public beast::unit_test::suite
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject& tx) {}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}},
|
||||
fixPDEnabled ? failTers : badTers);
|
||||
|
||||
testcase << "PermissionedDomain Set 4";
|
||||
doInvariantCheck(
|
||||
Env(*this, features),
|
||||
{{"permissioned domain credentials aren't unique"}},
|
||||
[&](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10);
|
||||
auto slePd = std::make_shared<SLE>(pdKeylet);
|
||||
|
||||
// create PD
|
||||
createPermissionedDomain(ac, slePd, A1, A2);
|
||||
auto slePd = createPermissionedDomain(ac, A1, A2);
|
||||
|
||||
// update PD
|
||||
{
|
||||
@@ -1357,8 +1379,155 @@ class Invariants_test : public beast::unit_test::suite
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject& tx) {}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}},
|
||||
fixPDEnabled ? failTers : badTers);
|
||||
|
||||
std::initializer_list<TER> goodTers = {tesSUCCESS, tesSUCCESS};
|
||||
|
||||
std::vector<std::string> badMoreThan1{{"transaction affected more than 1 permissioned domain entry."}};
|
||||
std::vector<std::string> emptyV;
|
||||
std::vector<std::string> badNoDomains{{"no domain objects affected by"}};
|
||||
std::vector<std::string> badNotDeleted{{"domain object modified, but not deleted by "}};
|
||||
std::vector<std::string> badDeleted{{"domain object deleted by"}};
|
||||
std::vector<std::string> badTx{{"domain object(s) affected by an unauthorized transaction."}};
|
||||
|
||||
{
|
||||
testcase << "PermissionedDomain set 2 domains ";
|
||||
doInvariantCheck(
|
||||
Env(*this, features),
|
||||
fixPDEnabled ? badMoreThan1 : emptyV,
|
||||
[](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
createPermissionedDomain(ac, A1, A2);
|
||||
createPermissionedDomain(ac, A1, A2, 2, 11);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}},
|
||||
fixPDEnabled ? failTers : goodTers);
|
||||
}
|
||||
|
||||
{
|
||||
testcase << "PermissionedDomain del 2 domains";
|
||||
|
||||
Env env1(*this, features);
|
||||
|
||||
Account const A1{"A1"};
|
||||
Account const A2{"A2"};
|
||||
env1.fund(XRP(1000), A1, A2);
|
||||
env1.close();
|
||||
|
||||
[[maybe_unused]] auto [seq1, pd1] = createPermissionedDomainEnv(env1, A1, A2);
|
||||
[[maybe_unused]] auto [seq2, pd2] = createPermissionedDomainEnv(env1, A1, A2);
|
||||
env1.close();
|
||||
|
||||
doInvariantCheck(
|
||||
std::move(env1),
|
||||
A1,
|
||||
A2,
|
||||
fixPDEnabled ? badMoreThan1 : emptyV,
|
||||
[&pd1, &pd2](Account const&, Account const&, ApplyContext& ac) {
|
||||
auto sle1 = ac.view().peek({ltPERMISSIONED_DOMAIN, pd1});
|
||||
auto sle2 = ac.view().peek({ltPERMISSIONED_DOMAIN, pd2});
|
||||
ac.view().erase(sle1);
|
||||
ac.view().erase(sle2);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttPERMISSIONED_DOMAIN_DELETE, [](STObject&) {}},
|
||||
fixPDEnabled ? failTers : goodTers);
|
||||
}
|
||||
|
||||
{
|
||||
testcase << "PermissionedDomain set 0 domains ";
|
||||
doInvariantCheck(
|
||||
Env(*this, features),
|
||||
fixPDEnabled ? badNoDomains : emptyV,
|
||||
[](Account const&, Account const&, ApplyContext&) { return true; },
|
||||
XRPAmount{},
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}},
|
||||
fixPDEnabled ? badTers : goodTers);
|
||||
}
|
||||
|
||||
{
|
||||
testcase << "PermissionedDomain del 0 domains";
|
||||
|
||||
Env env1(*this, features);
|
||||
|
||||
Account const A1{"A1"};
|
||||
Account const A2{"A2"};
|
||||
env1.fund(XRP(1000), A1, A2);
|
||||
env1.close();
|
||||
|
||||
[[maybe_unused]] auto [seq1, pd1] = createPermissionedDomainEnv(env1, A1, A2);
|
||||
[[maybe_unused]] auto [seq2, pd2] = createPermissionedDomainEnv(env1, A1, A2);
|
||||
env1.close();
|
||||
|
||||
doInvariantCheck(
|
||||
Env(*this, features),
|
||||
A1,
|
||||
A2,
|
||||
fixPDEnabled ? badNoDomains : emptyV,
|
||||
[](Account const&, Account const&, ApplyContext&) { return true; },
|
||||
XRPAmount{},
|
||||
STTx{ttPERMISSIONED_DOMAIN_DELETE, [](STObject&) {}},
|
||||
fixPDEnabled ? badTers : goodTers);
|
||||
}
|
||||
|
||||
{
|
||||
testcase << "PermissionedDomain set, delete domain";
|
||||
|
||||
Env env1(*this, features);
|
||||
|
||||
Account const A1{"A1"};
|
||||
Account const A2{"A2"};
|
||||
env1.fund(XRP(1000), A1, A2);
|
||||
env1.close();
|
||||
|
||||
[[maybe_unused]] auto [seq1, pd1] = createPermissionedDomainEnv(env1, A1, A2);
|
||||
env1.close();
|
||||
|
||||
doInvariantCheck(
|
||||
std::move(env1),
|
||||
A1,
|
||||
A2,
|
||||
fixPDEnabled ? badDeleted : emptyV,
|
||||
[&pd1](Account const&, Account const&, ApplyContext& ac) {
|
||||
auto sle1 = ac.view().peek({ltPERMISSIONED_DOMAIN, pd1});
|
||||
ac.view().erase(sle1);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}},
|
||||
fixPDEnabled ? failTers : goodTers);
|
||||
}
|
||||
|
||||
{
|
||||
testcase << "PermissionedDomain del, create domain ";
|
||||
doInvariantCheck(
|
||||
Env(*this, features),
|
||||
fixPDEnabled ? badNotDeleted : emptyV,
|
||||
[](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
createPermissionedDomain(ac, A1, A2);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttPERMISSIONED_DOMAIN_DELETE, [](STObject&) {}},
|
||||
fixPDEnabled ? failTers : goodTers);
|
||||
}
|
||||
|
||||
{
|
||||
testcase << "PermissionedDomain invalid tx";
|
||||
|
||||
doInvariantCheck(
|
||||
fixPDEnabled ? badTx : emptyV,
|
||||
[&](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
createPermissionedDomain(ac, A1, A2);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttPAYMENT, [](STObject&) {}},
|
||||
failTers);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1478,13 +1647,43 @@ class Invariants_test : public beast::unit_test::suite
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
testPermissionedDEX()
|
||||
static std::pair<std::uint32_t, uint256>
|
||||
createPermissionedDomainEnv(
|
||||
test::jtx::Env& env,
|
||||
test::jtx::Account const& A1,
|
||||
test::jtx::Account const& A2,
|
||||
std::uint32_t numCreds = 2)
|
||||
{
|
||||
using namespace test::jtx;
|
||||
testcase << "PermissionedDEX";
|
||||
|
||||
pdomain::Credentials credentials;
|
||||
|
||||
for (std::size_t n = 0; n < numCreds; ++n)
|
||||
{
|
||||
auto credType = "cred_type" + std::to_string(n);
|
||||
credentials.push_back({A2, credType});
|
||||
}
|
||||
|
||||
std::uint32_t const seq = env.seq(A1);
|
||||
env(pdomain::setTx(A1, credentials));
|
||||
uint256 key = pdomain::getNewDomain(env.meta());
|
||||
|
||||
// std::cout << "PD, acc: " << A1.id() << ", seq: " << seq << ", k: " <<
|
||||
// key << std::endl;
|
||||
return {seq, key};
|
||||
}
|
||||
|
||||
void
|
||||
testPermissionedDEX(FeatureBitset features)
|
||||
{
|
||||
using namespace test::jtx;
|
||||
|
||||
bool const fixPDEnabled = features[fixPermissionedDomainInvariant];
|
||||
|
||||
testcase << "PermissionedDEX" + std::string(fixPDEnabled ? " fix" : "");
|
||||
|
||||
doInvariantCheck(
|
||||
Env(*this, features),
|
||||
{{"domain doesn't exist"}},
|
||||
[](Account const& A1, Account const&, ApplyContext& ac) {
|
||||
Keylet const offerKey = keylet::offer(A1.id(), 10);
|
||||
@@ -1511,12 +1710,9 @@ class Invariants_test : public beast::unit_test::suite
|
||||
|
||||
// missing domain ID in offer object
|
||||
doInvariantCheck(
|
||||
Env(*this, features),
|
||||
{{"hybrid offer is malformed"}},
|
||||
[&](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10);
|
||||
auto slePd = std::make_shared<SLE>(pdKeylet);
|
||||
createPermissionedDomain(ac, slePd, A1, A2);
|
||||
|
||||
Keylet const offerKey = keylet::offer(A2.id(), 10);
|
||||
auto sleOffer = std::make_shared<SLE>(offerKey);
|
||||
sleOffer->setAccountID(sfAccount, A2);
|
||||
@@ -1531,116 +1727,154 @@ class Invariants_test : public beast::unit_test::suite
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttOFFER_CREATE, [&](STObject& tx) {}},
|
||||
STTx{ttOFFER_CREATE, [&](STObject&) {}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
|
||||
// more than one entry in sfAdditionalBooks
|
||||
doInvariantCheck(
|
||||
{{"hybrid offer is malformed"}},
|
||||
[&](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10);
|
||||
auto slePd = std::make_shared<SLE>(pdKeylet);
|
||||
createPermissionedDomain(ac, slePd, A1, A2);
|
||||
{
|
||||
Env env1(*this, features);
|
||||
|
||||
Keylet const offerKey = keylet::offer(A2.id(), 10);
|
||||
auto sleOffer = std::make_shared<SLE>(offerKey);
|
||||
sleOffer->setAccountID(sfAccount, A2);
|
||||
sleOffer->setFieldAmount(sfTakerPays, A1["USD"](10));
|
||||
sleOffer->setFieldAmount(sfTakerGets, XRP(1));
|
||||
sleOffer->setFlag(lsfHybrid);
|
||||
sleOffer->setFieldH256(sfDomainID, pdKeylet.key);
|
||||
Account const A1{"A1"};
|
||||
Account const A2{"A2"};
|
||||
env1.fund(XRP(1000), A1, A2);
|
||||
env1.close();
|
||||
|
||||
STArray bookArr;
|
||||
bookArr.push_back(STObject::makeInnerObject(sfBook));
|
||||
bookArr.push_back(STObject::makeInnerObject(sfBook));
|
||||
sleOffer->setFieldArray(sfAdditionalBooks, bookArr);
|
||||
ac.view().insert(sleOffer);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttOFFER_CREATE, [&](STObject& tx) {}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
[[maybe_unused]] auto [seq1, pd1] = createPermissionedDomainEnv(env1, A1, A2);
|
||||
env1.close();
|
||||
|
||||
doInvariantCheck(
|
||||
std::move(env1),
|
||||
A1,
|
||||
A2,
|
||||
{{"hybrid offer is malformed"}},
|
||||
[&pd1](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const offerKey = keylet::offer(A2.id(), 10);
|
||||
auto sleOffer = std::make_shared<SLE>(offerKey);
|
||||
sleOffer->setAccountID(sfAccount, A2);
|
||||
sleOffer->setFieldAmount(sfTakerPays, A1["USD"](10));
|
||||
sleOffer->setFieldAmount(sfTakerGets, XRP(1));
|
||||
sleOffer->setFlag(lsfHybrid);
|
||||
sleOffer->setFieldH256(sfDomainID, pd1);
|
||||
|
||||
STArray bookArr;
|
||||
bookArr.push_back(STObject::makeInnerObject(sfBook));
|
||||
bookArr.push_back(STObject::makeInnerObject(sfBook));
|
||||
sleOffer->setFieldArray(sfAdditionalBooks, bookArr);
|
||||
ac.view().insert(sleOffer);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttOFFER_CREATE, [&](STObject&) {}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
}
|
||||
|
||||
// hybrid offer missing sfAdditionalBooks
|
||||
doInvariantCheck(
|
||||
{{"hybrid offer is malformed"}},
|
||||
[&](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10);
|
||||
auto slePd = std::make_shared<SLE>(pdKeylet);
|
||||
createPermissionedDomain(ac, slePd, A1, A2);
|
||||
{
|
||||
Env env1(*this, features);
|
||||
|
||||
Keylet const offerKey = keylet::offer(A2.id(), 10);
|
||||
auto sleOffer = std::make_shared<SLE>(offerKey);
|
||||
sleOffer->setAccountID(sfAccount, A2);
|
||||
sleOffer->setFieldAmount(sfTakerPays, A1["USD"](10));
|
||||
sleOffer->setFieldAmount(sfTakerGets, XRP(1));
|
||||
sleOffer->setFlag(lsfHybrid);
|
||||
sleOffer->setFieldH256(sfDomainID, pdKeylet.key);
|
||||
ac.view().insert(sleOffer);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttOFFER_CREATE, [&](STObject& tx) {}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
Account const A1{"A1"};
|
||||
Account const A2{"A2"};
|
||||
env1.fund(XRP(1000), A1, A2);
|
||||
env1.close();
|
||||
|
||||
doInvariantCheck(
|
||||
{{"transaction consumed wrong domains"}},
|
||||
[&](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10);
|
||||
auto slePd = std::make_shared<SLE>(pdKeylet);
|
||||
createPermissionedDomain(ac, slePd, A1, A2);
|
||||
[[maybe_unused]] auto [seq1, pd1] = createPermissionedDomainEnv(env1, A1, A2);
|
||||
env1.close();
|
||||
|
||||
Keylet const badDomainKeylet = keylet::permissionedDomain(A1.id(), 20);
|
||||
auto sleBadPd = std::make_shared<SLE>(badDomainKeylet);
|
||||
createPermissionedDomain(ac, sleBadPd, A1, A2);
|
||||
doInvariantCheck(
|
||||
std::move(env1),
|
||||
A1,
|
||||
A2,
|
||||
{{"hybrid offer is malformed"}},
|
||||
[&pd1](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const offerKey = keylet::offer(A2.id(), 10);
|
||||
auto sleOffer = std::make_shared<SLE>(offerKey);
|
||||
sleOffer->setAccountID(sfAccount, A2);
|
||||
sleOffer->setFieldAmount(sfTakerPays, A1["USD"](10));
|
||||
sleOffer->setFieldAmount(sfTakerGets, XRP(1));
|
||||
sleOffer->setFlag(lsfHybrid);
|
||||
sleOffer->setFieldH256(sfDomainID, pd1);
|
||||
ac.view().insert(sleOffer);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttOFFER_CREATE, [&](STObject&) {}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
}
|
||||
|
||||
Keylet const offerKey = keylet::offer(A2.id(), 10);
|
||||
auto sleOffer = std::make_shared<SLE>(offerKey);
|
||||
sleOffer->setAccountID(sfAccount, A2);
|
||||
sleOffer->setFieldAmount(sfTakerPays, A1["USD"](10));
|
||||
sleOffer->setFieldAmount(sfTakerGets, XRP(1));
|
||||
sleOffer->setFieldH256(sfDomainID, pdKeylet.key);
|
||||
ac.view().insert(sleOffer);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{
|
||||
ttOFFER_CREATE,
|
||||
[&](STObject& tx) {
|
||||
Account const A1{"A1"};
|
||||
Keylet const badDomainKey = keylet::permissionedDomain(A1.id(), 20);
|
||||
tx.setFieldH256(sfDomainID, badDomainKey.key);
|
||||
tx.setFieldAmount(sfTakerPays, A1["USD"](10));
|
||||
tx.setFieldAmount(sfTakerGets, XRP(1));
|
||||
}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
{
|
||||
Env env1(*this, features);
|
||||
|
||||
doInvariantCheck(
|
||||
{{"domain transaction affected regular offers"}},
|
||||
[&](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10);
|
||||
auto slePd = std::make_shared<SLE>(pdKeylet);
|
||||
createPermissionedDomain(ac, slePd, A1, A2);
|
||||
Account const A1{"A1"};
|
||||
Account const A2{"A2"};
|
||||
env1.fund(XRP(1000), A1, A2);
|
||||
env1.close();
|
||||
|
||||
Keylet const offerKey = keylet::offer(A2.id(), 10);
|
||||
auto sleOffer = std::make_shared<SLE>(offerKey);
|
||||
sleOffer->setAccountID(sfAccount, A2);
|
||||
sleOffer->setFieldAmount(sfTakerPays, A1["USD"](10));
|
||||
sleOffer->setFieldAmount(sfTakerGets, XRP(1));
|
||||
ac.view().insert(sleOffer);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{
|
||||
ttOFFER_CREATE,
|
||||
[&](STObject& tx) {
|
||||
Account const A1{"A1"};
|
||||
Keylet const domainKey = keylet::permissionedDomain(A1.id(), 10);
|
||||
tx.setFieldH256(sfDomainID, domainKey.key);
|
||||
tx.setFieldAmount(sfTakerPays, A1["USD"](10));
|
||||
tx.setFieldAmount(sfTakerGets, XRP(1));
|
||||
}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
[[maybe_unused]] auto [seq1, pd1] = createPermissionedDomainEnv(env1, A1, A2);
|
||||
[[maybe_unused]] auto [seq2, pd2] = createPermissionedDomainEnv(env1, A1, A2);
|
||||
env1.close();
|
||||
|
||||
doInvariantCheck(
|
||||
std::move(env1),
|
||||
A1,
|
||||
A2,
|
||||
{{"transaction consumed wrong domains"}},
|
||||
[&pd1](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const offerKey = keylet::offer(A2.id(), 10);
|
||||
auto sleOffer = std::make_shared<SLE>(offerKey);
|
||||
sleOffer->setAccountID(sfAccount, A2);
|
||||
sleOffer->setFieldAmount(sfTakerPays, A1["USD"](10));
|
||||
sleOffer->setFieldAmount(sfTakerGets, XRP(1));
|
||||
sleOffer->setFieldH256(sfDomainID, pd1);
|
||||
ac.view().insert(sleOffer);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{
|
||||
ttOFFER_CREATE,
|
||||
[&pd2, &A1](STObject& tx) {
|
||||
tx.setFieldH256(sfDomainID, pd2);
|
||||
tx.setFieldAmount(sfTakerPays, A1["USD"](10));
|
||||
tx.setFieldAmount(sfTakerGets, XRP(1));
|
||||
}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
}
|
||||
|
||||
{
|
||||
Env env1(*this, features);
|
||||
|
||||
Account const A1{"A1"};
|
||||
Account const A2{"A2"};
|
||||
env1.fund(XRP(1000), A1, A2);
|
||||
env1.close();
|
||||
|
||||
[[maybe_unused]] auto [seq1, pd1] = createPermissionedDomainEnv(env1, A1, A2);
|
||||
env1.close();
|
||||
|
||||
doInvariantCheck(
|
||||
std::move(env1),
|
||||
A1,
|
||||
A2,
|
||||
{{"domain transaction affected regular offers"}},
|
||||
[&](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
Keylet const offerKey = keylet::offer(A2.id(), 10);
|
||||
auto sleOffer = std::make_shared<SLE>(offerKey);
|
||||
sleOffer->setAccountID(sfAccount, A2);
|
||||
sleOffer->setFieldAmount(sfTakerPays, A1["USD"](10));
|
||||
sleOffer->setFieldAmount(sfTakerGets, XRP(1));
|
||||
ac.view().insert(sleOffer);
|
||||
return true;
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{
|
||||
ttOFFER_CREATE,
|
||||
[&](STObject& tx) {
|
||||
Account const A1{"A1"};
|
||||
tx.setFieldH256(sfDomainID, pd1);
|
||||
tx.setFieldAmount(sfTakerPays, A1["USD"](10));
|
||||
tx.setFieldAmount(sfTakerGets, XRP(1));
|
||||
}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
}
|
||||
}
|
||||
|
||||
Keylet
|
||||
@@ -3490,8 +3724,10 @@ public:
|
||||
testNoZeroEscrow();
|
||||
testValidNewAccountRoot();
|
||||
testNFTokenPageInvariants();
|
||||
testPermissionedDomainInvariants();
|
||||
testPermissionedDEX();
|
||||
testPermissionedDomainInvariants(defaultAmendments() | fixPermissionedDomainInvariant);
|
||||
testPermissionedDomainInvariants(defaultAmendments() - fixPermissionedDomainInvariant);
|
||||
testPermissionedDEX(defaultAmendments() | fixPermissionedDomainInvariant);
|
||||
testPermissionedDEX(defaultAmendments() - fixPermissionedDomainInvariant);
|
||||
testNoModifiedUnmodifiableFields();
|
||||
testValidPseudoAccounts();
|
||||
testValidLoanBroker();
|
||||
|
||||
@@ -21,7 +21,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
std::unique_ptr<Config> cfg,
|
||||
std::string const& dbPath,
|
||||
std::string const& ledger,
|
||||
Config::StartUpType type,
|
||||
StartUpType type,
|
||||
std::optional<uint256> trapTxHash)
|
||||
{
|
||||
cfg->START_LEDGER = ledger;
|
||||
@@ -105,7 +105,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
// create a new env with the ledger file specified for startup
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, sd.ledgerFile, Config::LOAD_FILE, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, sd.ledgerFile, StartUpType::LOAD_FILE, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
auto jrb = env.rpc("ledger", "current", "full")[jss::result];
|
||||
@@ -123,7 +123,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
except([&] {
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, "", Config::LOAD_FILE, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, "", StartUpType::LOAD_FILE, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
});
|
||||
@@ -132,7 +132,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
except([&] {
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, "badfile.json", Config::LOAD_FILE, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, "badfile.json", StartUpType::LOAD_FILE, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
});
|
||||
@@ -153,7 +153,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
except([&] {
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerFileCorrupt.string(), Config::LOAD_FILE, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerFileCorrupt.string(), StartUpType::LOAD_FILE, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
});
|
||||
@@ -170,7 +170,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
boost::erase_all(ledgerHash, "\"");
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, Config::LOAD, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, StartUpType::LOAD, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
auto jrb = env.rpc("ledger", "current", "full")[jss::result];
|
||||
@@ -189,7 +189,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
boost::erase_all(ledgerHash, "\"");
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, Config::REPLAY, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, StartUpType::REPLAY, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
auto const jrb = env.rpc("ledger", "current", "full")[jss::result];
|
||||
@@ -213,7 +213,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
boost::erase_all(ledgerHash, "\"");
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, Config::REPLAY, sd.trapTxHash),
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, StartUpType::REPLAY, sd.trapTxHash),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
auto const jrb = env.rpc("ledger", "current", "full")[jss::result];
|
||||
@@ -241,7 +241,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
// replay when trapTxHash is set to an invalid transaction
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, Config::REPLAY, ~sd.trapTxHash),
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, StartUpType::REPLAY, ~sd.trapTxHash),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
BEAST_EXPECT(false);
|
||||
@@ -265,7 +265,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
// create a new env with the ledger "latest" specified for startup
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, "latest", Config::LOAD, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, "latest", StartUpType::LOAD, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
auto jrb = env.rpc("ledger", "current", "full")[jss::result];
|
||||
@@ -281,7 +281,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
// create a new env with specific ledger index at startup
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, "43", Config::LOAD, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, "43", StartUpType::LOAD, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
auto jrb = env.rpc("ledger", "current", "full")[jss::result];
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
#include <test/jtx.h>
|
||||
|
||||
#include <xrpld/app/main/DBInit.h>
|
||||
#include <xrpld/app/misc/Manifest.h>
|
||||
#include <xrpld/app/misc/ValidatorList.h>
|
||||
#include <xrpld/app/rdb/Wallet.h>
|
||||
|
||||
#include <xrpl/basics/base64.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/protocol/STExchange.h>
|
||||
#include <xrpl/protocol/SecretKey.h>
|
||||
#include <xrpl/protocol/Sign.h>
|
||||
#include <xrpl/rdb/DBInit.h>
|
||||
#include <xrpl/server/Manifest.h>
|
||||
#include <xrpl/server/Wallet.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
@@ -38,13 +38,17 @@ class PermissionedDomains_test : public beast::unit_test::suite
|
||||
testable_amendments() //
|
||||
| featurePermissionedDomains | featureCredentials};
|
||||
|
||||
FeatureBitset withFix_{
|
||||
testable_amendments() //
|
||||
| featurePermissionedDomains | featureCredentials};
|
||||
|
||||
// Verify that each tx type can execute if the feature is enabled.
|
||||
void
|
||||
testEnabled()
|
||||
testEnabled(FeatureBitset features)
|
||||
{
|
||||
testcase("Enabled");
|
||||
Account const alice("alice");
|
||||
Env env(*this, withFeature_);
|
||||
Env env(*this, features);
|
||||
env.fund(XRP(1000), alice);
|
||||
pdomain::Credentials credentials{{alice, "first credential"}};
|
||||
env(pdomain::setTx(alice, credentials));
|
||||
@@ -237,10 +241,10 @@ class PermissionedDomains_test : public beast::unit_test::suite
|
||||
|
||||
// Test PermissionedDomainSet
|
||||
void
|
||||
testSet()
|
||||
testSet(FeatureBitset features)
|
||||
{
|
||||
testcase("Set");
|
||||
Env env(*this, withFeature_);
|
||||
Env env(*this, features);
|
||||
env.set_parse_failure_expected(true);
|
||||
|
||||
int const accNum = 12;
|
||||
@@ -395,10 +399,10 @@ class PermissionedDomains_test : public beast::unit_test::suite
|
||||
|
||||
// Test PermissionedDomainDelete
|
||||
void
|
||||
testDelete()
|
||||
testDelete(FeatureBitset features)
|
||||
{
|
||||
testcase("Delete");
|
||||
Env env(*this, withFeature_);
|
||||
Env env(*this, features);
|
||||
Account const alice("alice");
|
||||
|
||||
env.fund(XRP(1000), alice);
|
||||
@@ -448,14 +452,14 @@ class PermissionedDomains_test : public beast::unit_test::suite
|
||||
}
|
||||
|
||||
void
|
||||
testAccountReserve()
|
||||
testAccountReserve(FeatureBitset features)
|
||||
{
|
||||
// Verify that the reserve behaves as expected for creating.
|
||||
testcase("Account Reserve");
|
||||
|
||||
using namespace test::jtx;
|
||||
|
||||
Env env(*this, withFeature_);
|
||||
Env env(*this, features);
|
||||
Account const alice("alice");
|
||||
|
||||
// Fund alice enough to exist, but not enough to meet
|
||||
@@ -500,12 +504,16 @@ public:
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testEnabled();
|
||||
testEnabled(withFeature_);
|
||||
testEnabled(withFix_);
|
||||
testCredentialsDisabled();
|
||||
testDisabled();
|
||||
testSet();
|
||||
testDelete();
|
||||
testAccountReserve();
|
||||
testSet(withFeature_);
|
||||
testSet(withFix_);
|
||||
testDelete(withFeature_);
|
||||
testDelete(withFix_);
|
||||
testAccountReserve(withFeature_);
|
||||
testAccountReserve(withFix_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#include <test/jtx/Env.h>
|
||||
|
||||
#include <xrpld/app/misc/Manifest.h>
|
||||
#include <xrpld/app/misc/ValidatorKeys.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/ConfigSections.h>
|
||||
|
||||
#include <xrpl/basics/base64.h>
|
||||
#include <xrpl/beast/unit_test.h>
|
||||
#include <xrpl/server/Manifest.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#include <test/jtx/TestSuite.h>
|
||||
|
||||
#include <xrpld/core/SociDB.h>
|
||||
|
||||
#include <xrpl/basics/BasicConfig.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/rdb/SociDB.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
@@ -4,6 +4,10 @@ namespace xrpl {
|
||||
namespace test {
|
||||
namespace jtx {
|
||||
|
||||
#define TEST_EXPECT(cond) env.test.expect(cond, __FILE__, __LINE__)
|
||||
#define TEST_EXPECTS(cond, reason) \
|
||||
((cond) ? (env.test.pass(), true) : (env.test.fail((reason), __FILE__, __LINE__), false))
|
||||
|
||||
void
|
||||
doBalance(Env& env, AccountID const& account, bool none, STAmount const& value, Issue const& issue)
|
||||
{
|
||||
@@ -12,11 +16,13 @@ doBalance(Env& env, AccountID const& account, bool none, STAmount const& value,
|
||||
auto const sle = env.le(keylet::account(account));
|
||||
if (none)
|
||||
{
|
||||
env.test.expect(!sle);
|
||||
TEST_EXPECT(!sle);
|
||||
}
|
||||
else if (env.test.expect(sle))
|
||||
else if (TEST_EXPECT(sle))
|
||||
{
|
||||
env.test.expect(sle->getFieldAmount(sfBalance) == value);
|
||||
TEST_EXPECTS(
|
||||
sle->getFieldAmount(sfBalance) == value,
|
||||
sle->getFieldAmount(sfBalance).getText() + " / " + value.getText());
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -24,15 +30,15 @@ doBalance(Env& env, AccountID const& account, bool none, STAmount const& value,
|
||||
auto const sle = env.le(keylet::line(account, issue));
|
||||
if (none)
|
||||
{
|
||||
env.test.expect(!sle);
|
||||
TEST_EXPECT(!sle);
|
||||
}
|
||||
else if (env.test.expect(sle))
|
||||
else if (TEST_EXPECT(sle))
|
||||
{
|
||||
auto amount = sle->getFieldAmount(sfBalance);
|
||||
amount.setIssuer(issue.account);
|
||||
if (account > issue.account)
|
||||
amount.negate();
|
||||
env.test.expect(amount == value);
|
||||
TEST_EXPECTS(amount == value, amount.getText());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,12 +49,12 @@ doBalance(Env& env, AccountID const& account, bool none, STAmount const& value,
|
||||
auto const sle = env.le(keylet::mptoken(mptIssue.getMptID(), account));
|
||||
if (none)
|
||||
{
|
||||
env.test.expect(!sle);
|
||||
TEST_EXPECT(!sle);
|
||||
}
|
||||
else if (env.test.expect(sle))
|
||||
else if (TEST_EXPECT(sle))
|
||||
{
|
||||
STAmount const amount{mptIssue, sle->getFieldU64(sfMPTAmount)};
|
||||
env.test.expect(amount == value);
|
||||
TEST_EXPECT(amount == value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
#include <test/nodestore/TestBase.h>
|
||||
#include <test/unit_test/SuiteJournal.h>
|
||||
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
|
||||
#include <xrpl/beast/utility/temp_dir.h>
|
||||
#include <xrpl/nodestore/DummyScheduler.h>
|
||||
#include <xrpl/nodestore/Manager.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ public:
|
||||
{
|
||||
std::shared_ptr<NodeObject> object;
|
||||
|
||||
Status const status = backend.fetch(batch[i]->getHash().cbegin(), &object);
|
||||
Status const status = backend.fetch(batch[i]->getHash(), &object);
|
||||
|
||||
BEAST_EXPECT(status == ok);
|
||||
|
||||
@@ -157,7 +157,7 @@ public:
|
||||
{
|
||||
std::shared_ptr<NodeObject> object;
|
||||
|
||||
Status const status = backend.fetch(batch[i]->getHash().cbegin(), &object);
|
||||
Status const status = backend.fetch(batch[i]->getHash(), &object);
|
||||
|
||||
BEAST_EXPECT(status == notFound);
|
||||
}
|
||||
|
||||
@@ -313,7 +313,7 @@ public:
|
||||
std::shared_ptr<NodeObject> obj;
|
||||
std::shared_ptr<NodeObject> result;
|
||||
obj = seq1_.obj(dist_(gen_));
|
||||
backend_.fetch(obj->getHash().data(), &result);
|
||||
backend_.fetch(obj->getHash(), &result);
|
||||
suite_.expect(result && isSame(result, obj));
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
@@ -371,9 +371,9 @@ public:
|
||||
{
|
||||
try
|
||||
{
|
||||
auto const key = seq2_.key(i);
|
||||
auto const hash = seq2_.key(i);
|
||||
std::shared_ptr<NodeObject> result;
|
||||
backend_.fetch(key.data(), &result);
|
||||
backend_.fetch(hash, &result);
|
||||
suite_.expect(!result);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
@@ -438,9 +438,9 @@ public:
|
||||
{
|
||||
if (rand_(gen_) < missingNodePercent)
|
||||
{
|
||||
auto const key = seq2_.key(dist_(gen_));
|
||||
auto const hash = seq2_.key(dist_(gen_));
|
||||
std::shared_ptr<NodeObject> result;
|
||||
backend_.fetch(key.data(), &result);
|
||||
backend_.fetch(hash, &result);
|
||||
suite_.expect(!result);
|
||||
}
|
||||
else
|
||||
@@ -448,7 +448,7 @@ public:
|
||||
std::shared_ptr<NodeObject> obj;
|
||||
std::shared_ptr<NodeObject> result;
|
||||
obj = seq1_.obj(dist_(gen_));
|
||||
backend_.fetch(obj->getHash().data(), &result);
|
||||
backend_.fetch(obj->getHash(), &result);
|
||||
suite_.expect(result && isSame(result, obj));
|
||||
}
|
||||
}
|
||||
@@ -524,8 +524,7 @@ public:
|
||||
std::shared_ptr<NodeObject> result;
|
||||
auto const j = older_(gen_);
|
||||
obj = seq1_.obj(j);
|
||||
std::shared_ptr<NodeObject> result1;
|
||||
backend_.fetch(obj->getHash().data(), &result);
|
||||
backend_.fetch(obj->getHash(), &result);
|
||||
suite_.expect(result != nullptr);
|
||||
suite_.expect(isSame(result, obj));
|
||||
}
|
||||
@@ -543,7 +542,7 @@ public:
|
||||
std::shared_ptr<NodeObject> result;
|
||||
auto const j = recent_(gen_);
|
||||
obj = seq1_.obj(j);
|
||||
backend_.fetch(obj->getHash().data(), &result);
|
||||
backend_.fetch(obj->getHash(), &result);
|
||||
suite_.expect(!result || isSame(result, obj));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2050,7 +2050,7 @@ class LedgerEntry_test : public beast::unit_test::suite
|
||||
Account const bob{"bob"};
|
||||
|
||||
Env env{*this, envconfig([](auto cfg) {
|
||||
cfg->START_UP = Config::FRESH;
|
||||
cfg->START_UP = StartUpType::FRESH;
|
||||
return cfg;
|
||||
})};
|
||||
|
||||
@@ -2241,7 +2241,7 @@ class LedgerEntry_test : public beast::unit_test::suite
|
||||
Account const bob{"bob"};
|
||||
|
||||
Env env{*this, envconfig([](auto cfg) {
|
||||
cfg->START_UP = Config::FRESH;
|
||||
cfg->START_UP = StartUpType::FRESH;
|
||||
return cfg;
|
||||
})};
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
|
||||
#include <xrpld/consensus/LedgerTiming.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/SociDB.h>
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <xrpld/app/ledger/TransactionMaster.h>
|
||||
#include <xrpld/app/main/Application.h>
|
||||
#include <xrpld/app/main/BasicApp.h>
|
||||
#include <xrpld/app/main/DBInit.h>
|
||||
#include <xrpld/app/main/GRPCServer.h>
|
||||
#include <xrpld/app/main/LoadManager.h>
|
||||
#include <xrpld/app/main/NodeIdentity.h>
|
||||
@@ -26,11 +25,8 @@
|
||||
#include <xrpld/app/misc/ValidatorSite.h>
|
||||
#include <xrpld/app/paths/PathRequests.h>
|
||||
#include <xrpld/app/rdb/RelationalDatabase.h>
|
||||
#include <xrpld/app/rdb/Wallet.h>
|
||||
#include <xrpld/app/tx/apply.h>
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
#include <xrpld/overlay/Cluster.h>
|
||||
#include <xrpld/overlay/PeerReservationTable.h>
|
||||
#include <xrpld/overlay/PeerSet.h>
|
||||
#include <xrpld/overlay/make_Overlay.h>
|
||||
#include <xrpld/shamap/NodeFamily.h>
|
||||
@@ -40,6 +36,7 @@
|
||||
#include <xrpl/basics/random.h>
|
||||
#include <xrpl/beast/asio/io_latency_probe.h>
|
||||
#include <xrpl/beast/core/LexicalCast.h>
|
||||
#include <xrpl/core/PeerReservationTable.h>
|
||||
#include <xrpl/core/PerfLog.h>
|
||||
#include <xrpl/crypto/csprng.h>
|
||||
#include <xrpl/json/json_reader.h>
|
||||
@@ -49,7 +46,9 @@
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/STParsedJSON.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
#include <xrpl/resource/Fees.h>
|
||||
#include <xrpl/server/Wallet.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
@@ -1021,6 +1020,12 @@ private:
|
||||
|
||||
void
|
||||
setMaxDisallowedLedger();
|
||||
|
||||
Application&
|
||||
app() override
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -1116,18 +1121,21 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline)
|
||||
|
||||
auto const startUp = config_->START_UP;
|
||||
JLOG(m_journal.debug()) << "startUp: " << startUp;
|
||||
if (startUp == Config::FRESH)
|
||||
if (startUp == StartUpType::FRESH)
|
||||
{
|
||||
JLOG(m_journal.info()) << "Starting new Ledger";
|
||||
|
||||
startGenesisLedger();
|
||||
}
|
||||
else if (startUp == Config::LOAD || startUp == Config::LOAD_FILE || startUp == Config::REPLAY)
|
||||
else if (startUp == StartUpType::LOAD || startUp == StartUpType::LOAD_FILE || startUp == StartUpType::REPLAY)
|
||||
{
|
||||
JLOG(m_journal.info()) << "Loading specified Ledger";
|
||||
|
||||
if (!loadOldLedger(
|
||||
config_->START_LEDGER, startUp == Config::REPLAY, startUp == Config::LOAD_FILE, config_->TRAP_TX_HASH))
|
||||
config_->START_LEDGER,
|
||||
startUp == StartUpType::REPLAY,
|
||||
startUp == StartUpType::LOAD_FILE,
|
||||
config_->TRAP_TX_HASH))
|
||||
{
|
||||
JLOG(m_journal.error()) << "The specified ledger could not be loaded.";
|
||||
if (config_->FAST_LOAD)
|
||||
@@ -1142,7 +1150,7 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (startUp == Config::NETWORK)
|
||||
else if (startUp == StartUpType::NETWORK)
|
||||
{
|
||||
// This should probably become the default once we have a stable
|
||||
// network.
|
||||
@@ -1529,7 +1537,7 @@ void
|
||||
ApplicationImp::startGenesisLedger()
|
||||
{
|
||||
std::vector<uint256> const initialAmendments =
|
||||
(config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired() : std::vector<uint256>{};
|
||||
(config_->START_UP == StartUpType::FRESH) ? m_amendmentTable->getDesired() : std::vector<uint256>{};
|
||||
|
||||
std::shared_ptr<Ledger> const genesis =
|
||||
std::make_shared<Ledger>(create_genesis, *config_, initialAmendments, nodeFamily_);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/overlay/PeerReservationTable.h>
|
||||
|
||||
#include <xrpl/basics/TaggedCache.h>
|
||||
#include <xrpl/beast/utility/PropertyStream.h>
|
||||
#include <xrpl/core/PeerReservationTable.h>
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/shamap/TreeNodeCache.h>
|
||||
@@ -112,8 +112,6 @@ public:
|
||||
public:
|
||||
Application();
|
||||
|
||||
virtual ~Application() = default;
|
||||
|
||||
virtual bool
|
||||
setup(boost::program_options::variables_map const& options) = 0;
|
||||
|
||||
@@ -127,8 +125,6 @@ public:
|
||||
checkSigs() const = 0;
|
||||
virtual void
|
||||
checkSigs(bool) = 0;
|
||||
virtual bool
|
||||
isStopping() const = 0;
|
||||
|
||||
//
|
||||
// ---
|
||||
@@ -138,14 +134,9 @@ public:
|
||||
virtual std::uint64_t
|
||||
instanceID() const = 0;
|
||||
|
||||
virtual Logs&
|
||||
logs() = 0;
|
||||
virtual Config&
|
||||
config() = 0;
|
||||
|
||||
virtual boost::asio::io_context&
|
||||
getIOContext() = 0;
|
||||
|
||||
virtual std::pair<PublicKey, SecretKey> const&
|
||||
nodeIdentity() = 0;
|
||||
|
||||
@@ -158,9 +149,6 @@ public:
|
||||
virtual bool
|
||||
serverOkay(std::string& reason) = 0;
|
||||
|
||||
virtual beast::Journal
|
||||
journal(std::string const& name) = 0;
|
||||
|
||||
/* Returns the number of file descriptors the application needs */
|
||||
virtual int
|
||||
fdRequired() const = 0;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <xrpld/app/main/Application.h>
|
||||
#include <xrpld/app/rdb/Vacuum.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/ConfigSections.h>
|
||||
#include <xrpld/core/TimeKeeper.h>
|
||||
@@ -8,6 +7,7 @@
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/beast/core/CurrentThreadName.h>
|
||||
#include <xrpl/protocol/BuildInfo.h>
|
||||
#include <xrpl/server/Vacuum.h>
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/process/v1/args.hpp>
|
||||
@@ -601,7 +601,7 @@ run(int argc, char** argv)
|
||||
|
||||
if (vm.count("start"))
|
||||
{
|
||||
config->START_UP = Config::FRESH;
|
||||
config->START_UP = StartUpType::FRESH;
|
||||
}
|
||||
|
||||
if (vm.count("import"))
|
||||
@@ -612,7 +612,7 @@ run(int argc, char** argv)
|
||||
config->START_LEDGER = vm["ledger"].as<std::string>();
|
||||
if (vm.count("replay"))
|
||||
{
|
||||
config->START_UP = Config::REPLAY;
|
||||
config->START_UP = StartUpType::REPLAY;
|
||||
if (vm.count("trap_tx_hash"))
|
||||
{
|
||||
uint256 tmp = {};
|
||||
@@ -631,16 +631,16 @@ run(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
else
|
||||
config->START_UP = Config::LOAD;
|
||||
config->START_UP = StartUpType::LOAD;
|
||||
}
|
||||
else if (vm.count("ledgerfile"))
|
||||
{
|
||||
config->START_LEDGER = vm["ledgerfile"].as<std::string>();
|
||||
config->START_UP = Config::LOAD_FILE;
|
||||
config->START_UP = StartUpType::LOAD_FILE;
|
||||
}
|
||||
else if (vm.count("load") || config->FAST_LOAD)
|
||||
{
|
||||
config->START_UP = Config::LOAD;
|
||||
config->START_UP = StartUpType::LOAD;
|
||||
}
|
||||
|
||||
if (vm.count("trap_tx_hash") && vm.count("replay") == 0)
|
||||
@@ -651,13 +651,13 @@ run(int argc, char** argv)
|
||||
|
||||
if (vm.count("net") && !config->FAST_LOAD)
|
||||
{
|
||||
if ((config->START_UP == Config::LOAD) || (config->START_UP == Config::REPLAY))
|
||||
if ((config->START_UP == StartUpType::LOAD) || (config->START_UP == StartUpType::REPLAY))
|
||||
{
|
||||
std::cerr << "Net and load/replay options are incompatible" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
config->START_UP = Config::NETWORK;
|
||||
config->START_UP = StartUpType::NETWORK;
|
||||
}
|
||||
|
||||
if (vm.count("valid"))
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#include <xrpld/app/main/Application.h>
|
||||
#include <xrpld/app/main/NodeIdentity.h>
|
||||
#include <xrpld/app/rdb/Wallet.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/ConfigSections.h>
|
||||
|
||||
#include <xrpl/server/Wallet.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
std::pair<PublicKey, SecretKey>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#include <xrpld/app/ledger/TransactionMaster.h>
|
||||
#include <xrpld/app/misc/NetworkOPs.h>
|
||||
#include <xrpld/app/misc/SHAMapStoreImp.h>
|
||||
#include <xrpld/app/rdb/State.h>
|
||||
#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
|
||||
#include <xrpld/core/ConfigSections.h>
|
||||
|
||||
#include <xrpl/beast/core/CurrentThreadName.h>
|
||||
#include <xrpl/nodestore/Scheduler.h>
|
||||
#include <xrpl/nodestore/detail/DatabaseRotatingImp.h>
|
||||
#include <xrpl/server/State.h>
|
||||
#include <xrpl/shamap/SHAMapMissingNode.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
#include <xrpld/app/ledger/LedgerMaster.h>
|
||||
#include <xrpld/app/misc/SHAMapStore.h>
|
||||
#include <xrpld/app/rdb/State.h>
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
|
||||
#include <xrpl/nodestore/DatabaseRotating.h>
|
||||
#include <xrpl/nodestore/Scheduler.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
#include <xrpl/server/State.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/misc/Manifest.h>
|
||||
#include <xrpld/core/TimeKeeper.h>
|
||||
#include <xrpld/overlay/Message.h>
|
||||
|
||||
@@ -9,6 +8,7 @@
|
||||
#include <xrpl/crypto/csprng.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/protocol/PublicKey.h>
|
||||
#include <xrpl/server/Manifest.h>
|
||||
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#include <xrpld/app/main/Application.h>
|
||||
#include <xrpld/app/misc/AmendmentTable.h>
|
||||
#include <xrpld/app/rdb/Wallet.h>
|
||||
#include <xrpld/core/ConfigSections.h>
|
||||
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/STValidation.h>
|
||||
#include <xrpl/protocol/TxFlags.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/server/Wallet.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
#include <xrpld/app/misc/Manifest.h>
|
||||
#include <xrpld/app/rdb/Wallet.h>
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/StringUtilities.h>
|
||||
#include <xrpl/basics/base64.h>
|
||||
#include <xrpl/json/json_reader.h>
|
||||
#include <xrpl/protocol/PublicKey.h>
|
||||
#include <xrpl/protocol/Sign.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
#include <xrpl/server/Manifest.h>
|
||||
#include <xrpl/server/Wallet.h>
|
||||
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include <xrpld/app/misc/Manifest.h>
|
||||
#include <xrpld/app/misc/ValidatorKeys.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/ConfigSections.h>
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/base64.h>
|
||||
#include <xrpl/server/Manifest.h>
|
||||
|
||||
namespace xrpl {
|
||||
ValidatorKeys::ValidatorKeys(Config const& config, beast::Journal j)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
#include <xrpld/peerfinder/detail/Store.h>
|
||||
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/ledger/Ledger.h>
|
||||
#include <xrpld/app/main/Application.h>
|
||||
#include <xrpld/app/misc/Transaction.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
#include <xrpld/rpc/detail/RPCLedgerHelpers.h>
|
||||
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
@@ -93,13 +93,13 @@ public:
|
||||
/**
|
||||
* @brief init Creates and returns an appropriate RelationalDatabase
|
||||
* instance based on configuration.
|
||||
* @param app Application object.
|
||||
* @param registry The service registry.
|
||||
* @param config Config object.
|
||||
* @param jobQueue JobQueue object.
|
||||
* @return Unique pointer to the interface.
|
||||
*/
|
||||
static std::unique_ptr<RelationalDatabase>
|
||||
init(Application& app, Config const& config, JobQueue& jobQueue);
|
||||
init(ServiceRegistry& registry, Config const& config, JobQueue& jobQueue);
|
||||
|
||||
virtual ~RelationalDatabase() = default;
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
#include <xrpld/app/ledger/TransactionMaster.h>
|
||||
#include <xrpld/app/rdb/RelationalDatabase.h>
|
||||
#include <xrpld/app/rdb/backend/detail/Node.h>
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
#include <xrpld/core/SociDB.h>
|
||||
|
||||
#include <xrpl/basics/BasicConfig.h>
|
||||
#include <xrpl/basics/StringUtilities.h>
|
||||
#include <xrpl/json/to_string.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
#include <xrpl/rdb/SociDB.h>
|
||||
|
||||
#include <boost/range/adaptor/transformed.hpp>
|
||||
|
||||
@@ -64,8 +64,8 @@ makeLedgerDBs(
|
||||
tx->getSession() << boost::str(
|
||||
boost::format("PRAGMA cache_size=-%d;") % kilobytes(config.getValueFor(SizedItem::txnDBCache)));
|
||||
|
||||
if (!setup.standAlone || setup.startUp == Config::LOAD || setup.startUp == Config::LOAD_FILE ||
|
||||
setup.startUp == Config::REPLAY)
|
||||
if (!setup.standAlone || setup.startUp == StartUpType::LOAD || setup.startUp == StartUpType::LOAD_FILE ||
|
||||
setup.startUp == StartUpType::REPLAY)
|
||||
{
|
||||
// Check if AccountTransactions has primary key
|
||||
std::string cid, name, type;
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
#include <xrpld/app/misc/detail/AccountTxPaging.h>
|
||||
#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
|
||||
#include <xrpld/app/rdb/backend/detail/Node.h>
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
#include <xrpld/core/SociDB.h>
|
||||
|
||||
#include <xrpl/basics/StringUtilities.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
#include <xrpl/rdb/SociDB.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class SQLiteDatabaseImp final : public SQLiteDatabase
|
||||
{
|
||||
public:
|
||||
SQLiteDatabaseImp(Application& app, Config const& config, JobQueue& jobQueue)
|
||||
: app_(app), useTxTables_(config.useTxTables()), j_(app_.journal("SQLiteDatabaseImp"))
|
||||
SQLiteDatabaseImp(ServiceRegistry& registry, Config const& config, JobQueue& jobQueue)
|
||||
: registry_(registry), useTxTables_(config.useTxTables()), j_(registry.journal("SQLiteDatabaseImp"))
|
||||
{
|
||||
DatabaseCon::Setup const setup = setup_DatabaseCon(config, j_);
|
||||
if (!makeLedgerDBs(config, setup, DatabaseCon::CheckpointerSetup{&jobQueue, &app_.logs()}))
|
||||
if (!makeLedgerDBs(config, setup, DatabaseCon::CheckpointerSetup{&jobQueue, ®istry_.logs()}))
|
||||
{
|
||||
std::string_view constexpr error = "Failed to create ledger databases";
|
||||
|
||||
@@ -139,7 +139,7 @@ public:
|
||||
closeTransactionDB() override;
|
||||
|
||||
private:
|
||||
Application& app_;
|
||||
ServiceRegistry& registry_;
|
||||
bool const useTxTables_;
|
||||
beast::Journal j_;
|
||||
std::unique_ptr<DatabaseCon> ledgerDb_, txdb_;
|
||||
@@ -370,7 +370,7 @@ SQLiteDatabaseImp::saveValidatedLedger(std::shared_ptr<Ledger const> const& ledg
|
||||
{
|
||||
if (existsLedger())
|
||||
{
|
||||
if (!detail::saveValidatedLedger(*ledgerDb_, txdb_, app_, ledger, current))
|
||||
if (!detail::saveValidatedLedger(*ledgerDb_, txdb_, registry_.app(), ledger, current))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -506,7 +506,7 @@ SQLiteDatabaseImp::getTxHistory(LedgerIndex startIndex)
|
||||
if (existsTransaction())
|
||||
{
|
||||
auto db = checkoutTransaction();
|
||||
auto const res = detail::getTxHistory(*db, app_, startIndex, 20).first;
|
||||
auto const res = detail::getTxHistory(*db, registry_.app(), startIndex, 20).first;
|
||||
|
||||
if (!res.empty())
|
||||
return res;
|
||||
@@ -521,12 +521,12 @@ SQLiteDatabaseImp::getOldestAccountTxs(AccountTxOptions const& options)
|
||||
if (!useTxTables_)
|
||||
return {};
|
||||
|
||||
LedgerMaster& ledgerMaster = app_.getLedgerMaster();
|
||||
LedgerMaster& ledgerMaster = registry_.getLedgerMaster();
|
||||
|
||||
if (existsTransaction())
|
||||
{
|
||||
auto db = checkoutTransaction();
|
||||
return detail::getOldestAccountTxs(*db, app_, ledgerMaster, options, j_).first;
|
||||
return detail::getOldestAccountTxs(*db, registry_.app(), ledgerMaster, options, j_).first;
|
||||
}
|
||||
|
||||
return {};
|
||||
@@ -538,12 +538,12 @@ SQLiteDatabaseImp::getNewestAccountTxs(AccountTxOptions const& options)
|
||||
if (!useTxTables_)
|
||||
return {};
|
||||
|
||||
LedgerMaster& ledgerMaster = app_.getLedgerMaster();
|
||||
LedgerMaster& ledgerMaster = registry_.getLedgerMaster();
|
||||
|
||||
if (existsTransaction())
|
||||
{
|
||||
auto db = checkoutTransaction();
|
||||
return detail::getNewestAccountTxs(*db, app_, ledgerMaster, options, j_).first;
|
||||
return detail::getNewestAccountTxs(*db, registry_.app(), ledgerMaster, options, j_).first;
|
||||
}
|
||||
|
||||
return {};
|
||||
@@ -558,7 +558,7 @@ SQLiteDatabaseImp::getOldestAccountTxsB(AccountTxOptions const& options)
|
||||
if (existsTransaction())
|
||||
{
|
||||
auto db = checkoutTransaction();
|
||||
return detail::getOldestAccountTxsB(*db, app_, options, j_).first;
|
||||
return detail::getOldestAccountTxsB(*db, registry_.app(), options, j_).first;
|
||||
}
|
||||
|
||||
return {};
|
||||
@@ -573,7 +573,7 @@ SQLiteDatabaseImp::getNewestAccountTxsB(AccountTxOptions const& options)
|
||||
if (existsTransaction())
|
||||
{
|
||||
auto db = checkoutTransaction();
|
||||
return detail::getNewestAccountTxsB(*db, app_, options, j_).first;
|
||||
return detail::getNewestAccountTxsB(*db, registry_.app(), options, j_).first;
|
||||
}
|
||||
|
||||
return {};
|
||||
@@ -586,10 +586,9 @@ SQLiteDatabaseImp::oldestAccountTxPage(AccountTxPageOptions const& options)
|
||||
return {};
|
||||
|
||||
static std::uint32_t const page_length(200);
|
||||
auto onUnsavedLedger = std::bind(saveLedgerAsync, std::ref(app_), std::placeholders::_1);
|
||||
auto onUnsavedLedger = std::bind(saveLedgerAsync, std::ref(registry_.app()), std::placeholders::_1);
|
||||
AccountTxs ret;
|
||||
Application& app = app_;
|
||||
auto onTransaction = [&ret, &app](
|
||||
auto onTransaction = [&ret, &app = registry_.app()](
|
||||
std::uint32_t ledger_index, std::string const& status, Blob&& rawTxn, Blob&& rawMeta) {
|
||||
convertBlobsToTxResult(ret, ledger_index, status, rawTxn, rawMeta, app);
|
||||
};
|
||||
@@ -611,10 +610,9 @@ SQLiteDatabaseImp::newestAccountTxPage(AccountTxPageOptions const& options)
|
||||
return {};
|
||||
|
||||
static std::uint32_t const page_length(200);
|
||||
auto onUnsavedLedger = std::bind(saveLedgerAsync, std::ref(app_), std::placeholders::_1);
|
||||
auto onUnsavedLedger = std::bind(saveLedgerAsync, std::ref(registry_.app()), std::placeholders::_1);
|
||||
AccountTxs ret;
|
||||
Application& app = app_;
|
||||
auto onTransaction = [&ret, &app](
|
||||
auto onTransaction = [&ret, &app = registry_.app()](
|
||||
std::uint32_t ledger_index, std::string const& status, Blob&& rawTxn, Blob&& rawMeta) {
|
||||
convertBlobsToTxResult(ret, ledger_index, status, rawTxn, rawMeta, app);
|
||||
};
|
||||
@@ -636,7 +634,7 @@ SQLiteDatabaseImp::oldestAccountTxPageB(AccountTxPageOptions const& options)
|
||||
return {};
|
||||
|
||||
static std::uint32_t const page_length(500);
|
||||
auto onUnsavedLedger = std::bind(saveLedgerAsync, std::ref(app_), std::placeholders::_1);
|
||||
auto onUnsavedLedger = std::bind(saveLedgerAsync, std::ref(registry_.app()), std::placeholders::_1);
|
||||
MetaTxsList ret;
|
||||
auto onTransaction = [&ret](std::uint32_t ledgerIndex, std::string const& status, Blob&& rawTxn, Blob&& rawMeta) {
|
||||
ret.emplace_back(std::move(rawTxn), std::move(rawMeta), ledgerIndex);
|
||||
@@ -659,7 +657,7 @@ SQLiteDatabaseImp::newestAccountTxPageB(AccountTxPageOptions const& options)
|
||||
return {};
|
||||
|
||||
static std::uint32_t const page_length(500);
|
||||
auto onUnsavedLedger = std::bind(saveLedgerAsync, std::ref(app_), std::placeholders::_1);
|
||||
auto onUnsavedLedger = std::bind(saveLedgerAsync, std::ref(registry_.app()), std::placeholders::_1);
|
||||
MetaTxsList ret;
|
||||
auto onTransaction = [&ret](std::uint32_t ledgerIndex, std::string const& status, Blob&& rawTxn, Blob&& rawMeta) {
|
||||
ret.emplace_back(std::move(rawTxn), std::move(rawMeta), ledgerIndex);
|
||||
@@ -687,7 +685,7 @@ SQLiteDatabaseImp::getTransaction(
|
||||
if (existsTransaction())
|
||||
{
|
||||
auto db = checkoutTransaction();
|
||||
return detail::getTransaction(*db, app_, id, range, ec);
|
||||
return detail::getTransaction(*db, registry_.app(), id, range, ec);
|
||||
}
|
||||
|
||||
return TxSearched::unknown;
|
||||
@@ -769,9 +767,9 @@ SQLiteDatabaseImp::closeTransactionDB()
|
||||
}
|
||||
|
||||
std::unique_ptr<RelationalDatabase>
|
||||
getSQLiteDatabase(Application& app, Config const& config, JobQueue& jobQueue)
|
||||
getSQLiteDatabase(ServiceRegistry& registry, Config const& config, JobQueue& jobQueue)
|
||||
{
|
||||
return std::make_unique<SQLiteDatabaseImp>(app, config, jobQueue);
|
||||
return std::make_unique<SQLiteDatabaseImp>(registry, config, jobQueue);
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
#include <xrpld/app/main/Application.h>
|
||||
#include <xrpld/app/rdb/RelationalDatabase.h>
|
||||
#include <xrpld/core/ConfigSections.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
extern std::unique_ptr<RelationalDatabase>
|
||||
getSQLiteDatabase(Application& app, Config const& config, JobQueue& jobQueue);
|
||||
getSQLiteDatabase(ServiceRegistry& registry, Config const& config, JobQueue& jobQueue);
|
||||
|
||||
std::unique_ptr<RelationalDatabase>
|
||||
RelationalDatabase::init(Application& app, Config const& config, JobQueue& jobQueue)
|
||||
RelationalDatabase::init(ServiceRegistry& registry, Config const& config, JobQueue& jobQueue)
|
||||
{
|
||||
bool use_sqlite = false;
|
||||
|
||||
@@ -31,7 +30,7 @@ RelationalDatabase::init(Application& app, Config const& config, JobQueue& jobQu
|
||||
|
||||
if (use_sqlite)
|
||||
{
|
||||
return getSQLiteDatabase(app, config, jobQueue);
|
||||
return getSQLiteDatabase(registry, config, jobQueue);
|
||||
}
|
||||
|
||||
return std::unique_ptr<RelationalDatabase>();
|
||||
|
||||
@@ -1507,7 +1507,7 @@ ValidMPTIssuance::finalize(
|
||||
|
||||
void
|
||||
ValidPermissionedDomain::visitEntry(
|
||||
bool,
|
||||
bool isDel,
|
||||
std::shared_ptr<SLE const> const& before,
|
||||
std::shared_ptr<SLE const> const& after)
|
||||
{
|
||||
@@ -1516,39 +1516,29 @@ ValidPermissionedDomain::visitEntry(
|
||||
if (after && after->getType() != ltPERMISSIONED_DOMAIN)
|
||||
return;
|
||||
|
||||
auto check = [](SleStatus& sleStatus, std::shared_ptr<SLE const> const& sle) {
|
||||
auto check = [isDel](std::vector<SleStatus>& sleStatus, std::shared_ptr<SLE const> const& sle) {
|
||||
auto const& credentials = sle->getFieldArray(sfAcceptedCredentials);
|
||||
sleStatus.credentialsSize_ = credentials.size();
|
||||
auto const sorted = credentials::makeSorted(credentials);
|
||||
sleStatus.isUnique_ = !sorted.empty();
|
||||
|
||||
SleStatus ss{credentials.size(), false, !sorted.empty(), isDel};
|
||||
|
||||
// If array have duplicates then all the other checks are invalid
|
||||
sleStatus.isSorted_ = false;
|
||||
|
||||
if (sleStatus.isUnique_)
|
||||
if (ss.isUnique_)
|
||||
{
|
||||
unsigned i = 0;
|
||||
for (auto const& cred : sorted)
|
||||
{
|
||||
auto const& credTx = credentials[i++];
|
||||
sleStatus.isSorted_ = (cred.first == credTx[sfIssuer]) && (cred.second == credTx[sfCredentialType]);
|
||||
if (!sleStatus.isSorted_)
|
||||
ss.isSorted_ = (cred.first == credTx[sfIssuer]) && (cred.second == credTx[sfCredentialType]);
|
||||
if (!ss.isSorted_)
|
||||
break;
|
||||
}
|
||||
}
|
||||
sleStatus.emplace_back(std::move(ss));
|
||||
};
|
||||
|
||||
if (before)
|
||||
{
|
||||
sleStatus_[0] = SleStatus();
|
||||
check(*sleStatus_[0], after);
|
||||
}
|
||||
|
||||
if (after)
|
||||
{
|
||||
sleStatus_[1] = SleStatus();
|
||||
check(*sleStatus_[1], after);
|
||||
}
|
||||
check(sleStatus_, after);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -1559,9 +1549,6 @@ ValidPermissionedDomain::finalize(
|
||||
ReadView const& view,
|
||||
beast::Journal const& j)
|
||||
{
|
||||
if (tx.getTxnType() != ttPERMISSIONED_DOMAIN_SET || result != tesSUCCESS)
|
||||
return true;
|
||||
|
||||
auto check = [](SleStatus const& sleStatus, beast::Journal const& j) {
|
||||
if (!sleStatus.credentialsSize_)
|
||||
{
|
||||
@@ -1595,7 +1582,76 @@ ValidPermissionedDomain::finalize(
|
||||
return true;
|
||||
};
|
||||
|
||||
return (sleStatus_[0] ? check(*sleStatus_[0], j) : true) && (sleStatus_[1] ? check(*sleStatus_[1], j) : true);
|
||||
if (view.rules().enabled(fixPermissionedDomainInvariant))
|
||||
{
|
||||
// No permissioned domains should be affected if the transaction failed
|
||||
if (result != tesSUCCESS)
|
||||
// If nothing changed, all is good. If there were changes, that's
|
||||
// bad.
|
||||
return sleStatus_.empty();
|
||||
|
||||
if (sleStatus_.size() > 1)
|
||||
{
|
||||
JLOG(j.fatal()) << "Invariant failed: transaction affected more "
|
||||
"than 1 permissioned domain entry.";
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (tx.getTxnType())
|
||||
{
|
||||
case ttPERMISSIONED_DOMAIN_SET: {
|
||||
if (sleStatus_.empty())
|
||||
{
|
||||
JLOG(j.fatal()) << "Invariant failed: no domain objects affected by "
|
||||
"PermissionedDomainSet";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto const& sleStatus = sleStatus_[0];
|
||||
if (sleStatus.isDelete_)
|
||||
{
|
||||
JLOG(j.fatal()) << "Invariant failed: domain object "
|
||||
"deleted by PermissionedDomainSet";
|
||||
return false;
|
||||
}
|
||||
return check(sleStatus, j);
|
||||
}
|
||||
case ttPERMISSIONED_DOMAIN_DELETE: {
|
||||
if (sleStatus_.empty())
|
||||
{
|
||||
JLOG(j.fatal()) << "Invariant failed: no domain objects affected by "
|
||||
"PermissionedDomainDelete";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sleStatus_[0].isDelete_)
|
||||
{
|
||||
JLOG(j.fatal()) << "Invariant failed: domain object "
|
||||
"modified, but not deleted by "
|
||||
"PermissionedDomainDelete";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
if (!sleStatus_.empty())
|
||||
{
|
||||
JLOG(j.fatal()) << "Invariant failed: " << sleStatus_.size()
|
||||
<< " domain object(s) affected by an "
|
||||
"unauthorized transaction. "
|
||||
<< tx.getTxnType();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tx.getTxnType() != ttPERMISSIONED_DOMAIN_SET || result != tesSUCCESS || sleStatus_.empty())
|
||||
return true;
|
||||
return check(sleStatus_[0], j);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -449,9 +449,11 @@ class ValidPermissionedDomain
|
||||
struct SleStatus
|
||||
{
|
||||
std::size_t credentialsSize_{0};
|
||||
bool isSorted_ = false, isUnique_ = false;
|
||||
bool isSorted_ = false;
|
||||
bool isUnique_ = false;
|
||||
bool isDelete_ = false;
|
||||
};
|
||||
std::optional<SleStatus> sleStatus_[2];
|
||||
std::vector<SleStatus> sleStatus_;
|
||||
|
||||
public:
|
||||
void
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/net/IPEndpoint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/core/StartUpType.h>
|
||||
#include <xrpl/protocol/SystemParameters.h> // VFALCO Breaks levelization
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
|
||||
#include <boost/filesystem.hpp> // VFALCO FIX: This include should not be here
|
||||
|
||||
@@ -124,8 +126,7 @@ public:
|
||||
// Entries from [ips_fixed] config stanza
|
||||
std::vector<std::string> IPS_FIXED;
|
||||
|
||||
enum StartUpType { FRESH, NORMAL, LOAD, LOAD_FILE, REPLAY, NETWORK };
|
||||
StartUpType START_UP = NORMAL;
|
||||
StartUpType START_UP = StartUpType::NORMAL;
|
||||
|
||||
bool START_VALID = false;
|
||||
|
||||
@@ -355,4 +356,7 @@ public:
|
||||
FeeSetup
|
||||
setup_FeeVote(Section const& section);
|
||||
|
||||
DatabaseCon::Setup
|
||||
setup_DatabaseCon(Config const& c, std::optional<beast::Journal> j = std::nullopt);
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -1039,4 +1039,150 @@ setup_FeeVote(Section const& section)
|
||||
return setup;
|
||||
}
|
||||
|
||||
DatabaseCon::Setup
|
||||
setup_DatabaseCon(Config const& c, std::optional<beast::Journal> j)
|
||||
{
|
||||
DatabaseCon::Setup setup;
|
||||
|
||||
setup.startUp = c.START_UP;
|
||||
setup.standAlone = c.standalone();
|
||||
setup.dataDir = c.legacy("database_path");
|
||||
if (!setup.standAlone && setup.dataDir.empty())
|
||||
{
|
||||
Throw<std::runtime_error>("database_path must be set.");
|
||||
}
|
||||
|
||||
if (!setup.globalPragma)
|
||||
{
|
||||
auto const& sqlite = c.section("sqlite");
|
||||
auto result = std::make_unique<std::vector<std::string>>();
|
||||
result->reserve(3);
|
||||
|
||||
// defaults
|
||||
std::string safety_level;
|
||||
std::string journal_mode = "wal";
|
||||
std::string synchronous = "normal";
|
||||
std::string temp_store = "file";
|
||||
bool showRiskWarning = false;
|
||||
|
||||
if (set(safety_level, "safety_level", sqlite))
|
||||
{
|
||||
if (boost::iequals(safety_level, "low"))
|
||||
{
|
||||
// low safety defaults
|
||||
journal_mode = "memory";
|
||||
synchronous = "off";
|
||||
temp_store = "memory";
|
||||
showRiskWarning = true;
|
||||
}
|
||||
else if (!boost::iequals(safety_level, "high"))
|
||||
{
|
||||
Throw<std::runtime_error>("Invalid safety_level value: " + safety_level);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// #journal_mode Valid values : delete, truncate, persist,
|
||||
// memory, wal, off
|
||||
if (set(journal_mode, "journal_mode", sqlite) && !safety_level.empty())
|
||||
{
|
||||
Throw<std::runtime_error>(
|
||||
"Configuration file may not define both "
|
||||
"\"safety_level\" and \"journal_mode\"");
|
||||
}
|
||||
bool higherRisk = boost::iequals(journal_mode, "memory") || boost::iequals(journal_mode, "off");
|
||||
showRiskWarning = showRiskWarning || higherRisk;
|
||||
if (higherRisk || boost::iequals(journal_mode, "delete") || boost::iequals(journal_mode, "truncate") ||
|
||||
boost::iequals(journal_mode, "persist") || boost::iequals(journal_mode, "wal"))
|
||||
{
|
||||
result->emplace_back(boost::str(boost::format(CommonDBPragmaJournal) % journal_mode));
|
||||
}
|
||||
else
|
||||
{
|
||||
Throw<std::runtime_error>("Invalid journal_mode value: " + journal_mode);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// #synchronous Valid values : off, normal, full, extra
|
||||
if (set(synchronous, "synchronous", sqlite) && !safety_level.empty())
|
||||
{
|
||||
Throw<std::runtime_error>(
|
||||
"Configuration file may not define both "
|
||||
"\"safety_level\" and \"synchronous\"");
|
||||
}
|
||||
bool higherRisk = boost::iequals(synchronous, "off");
|
||||
showRiskWarning = showRiskWarning || higherRisk;
|
||||
if (higherRisk || boost::iequals(synchronous, "normal") || boost::iequals(synchronous, "full") ||
|
||||
boost::iequals(synchronous, "extra"))
|
||||
{
|
||||
result->emplace_back(boost::str(boost::format(CommonDBPragmaSync) % synchronous));
|
||||
}
|
||||
else
|
||||
{
|
||||
Throw<std::runtime_error>("Invalid synchronous value: " + synchronous);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// #temp_store Valid values : default, file, memory
|
||||
if (set(temp_store, "temp_store", sqlite) && !safety_level.empty())
|
||||
{
|
||||
Throw<std::runtime_error>(
|
||||
"Configuration file may not define both "
|
||||
"\"safety_level\" and \"temp_store\"");
|
||||
}
|
||||
bool higherRisk = boost::iequals(temp_store, "memory");
|
||||
showRiskWarning = showRiskWarning || higherRisk;
|
||||
if (higherRisk || boost::iequals(temp_store, "default") || boost::iequals(temp_store, "file"))
|
||||
{
|
||||
result->emplace_back(boost::str(boost::format(CommonDBPragmaTemp) % temp_store));
|
||||
}
|
||||
else
|
||||
{
|
||||
Throw<std::runtime_error>("Invalid temp_store value: " + temp_store);
|
||||
}
|
||||
}
|
||||
|
||||
if (showRiskWarning && j && c.LEDGER_HISTORY > SQLITE_TUNING_CUTOFF)
|
||||
{
|
||||
JLOG(j->warn()) << "reducing the data integrity guarantees from the "
|
||||
"default [sqlite] behavior is not recommended for "
|
||||
"nodes storing large amounts of history, because of the "
|
||||
"difficulty inherent in rebuilding corrupted data.";
|
||||
}
|
||||
XRPL_ASSERT(result->size() == 3, "xrpl::setup_DatabaseCon::globalPragma : result size is 3");
|
||||
setup.globalPragma = std::move(result);
|
||||
}
|
||||
setup.useGlobalPragma = true;
|
||||
|
||||
auto setPragma = [](std::string& pragma, std::string const& key, int64_t value) {
|
||||
pragma = "PRAGMA " + key + "=" + std::to_string(value) + ";";
|
||||
};
|
||||
|
||||
// Lgr Pragma
|
||||
setPragma(setup.lgrPragma[0], "journal_size_limit", 1582080);
|
||||
|
||||
// TX Pragma
|
||||
int64_t page_size = 4096;
|
||||
int64_t journal_size_limit = 1582080;
|
||||
if (c.exists("sqlite"))
|
||||
{
|
||||
auto& s = c.section("sqlite");
|
||||
set(journal_size_limit, "journal_size_limit", s);
|
||||
set(page_size, "page_size", s);
|
||||
if (page_size < 512 || page_size > 65536)
|
||||
Throw<std::runtime_error>("Invalid page_size. Must be between 512 and 65536.");
|
||||
|
||||
if (page_size & (page_size - 1))
|
||||
Throw<std::runtime_error>("Invalid page_size. Must be a power of 2.");
|
||||
}
|
||||
|
||||
setPragma(setup.txPragma[0], "page_size", page_size);
|
||||
setPragma(setup.txPragma[1], "journal_size_limit", journal_size_limit);
|
||||
setPragma(setup.txPragma[2], "max_page_count", 4294967294);
|
||||
setPragma(setup.txPragma[3], "mmap_size", 17179869184);
|
||||
|
||||
return setup;
|
||||
}
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -1,242 +0,0 @@
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
#include <xrpld/core/SociDB.h>
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class CheckpointersCollection
|
||||
{
|
||||
std::uintptr_t nextId_{0};
|
||||
// Mutex protects the CheckpointersCollection
|
||||
std::mutex mutex_;
|
||||
// Each checkpointer is given a unique id. All the checkpointers that are
|
||||
// part of a DatabaseCon are part of this collection. When the DatabaseCon
|
||||
// is destroyed, its checkpointer is removed from the collection
|
||||
std::unordered_map<std::uintptr_t, std::shared_ptr<Checkpointer>> checkpointers_;
|
||||
|
||||
public:
|
||||
std::shared_ptr<Checkpointer>
|
||||
fromId(std::uintptr_t id)
|
||||
{
|
||||
std::lock_guard l{mutex_};
|
||||
auto it = checkpointers_.find(id);
|
||||
if (it != checkpointers_.end())
|
||||
return it->second;
|
||||
return {};
|
||||
}
|
||||
|
||||
void
|
||||
erase(std::uintptr_t id)
|
||||
{
|
||||
std::lock_guard lock{mutex_};
|
||||
checkpointers_.erase(id);
|
||||
}
|
||||
|
||||
std::shared_ptr<Checkpointer>
|
||||
create(std::shared_ptr<soci::session> const& session, JobQueue& jobQueue, Logs& logs)
|
||||
{
|
||||
std::lock_guard lock{mutex_};
|
||||
auto const id = nextId_++;
|
||||
auto const r = makeCheckpointer(id, session, jobQueue, logs);
|
||||
checkpointers_[id] = r;
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
CheckpointersCollection checkpointers;
|
||||
|
||||
std::shared_ptr<Checkpointer>
|
||||
checkpointerFromId(std::uintptr_t id)
|
||||
{
|
||||
return checkpointers.fromId(id);
|
||||
}
|
||||
|
||||
DatabaseCon::~DatabaseCon()
|
||||
{
|
||||
if (checkpointer_)
|
||||
{
|
||||
checkpointers.erase(checkpointer_->id());
|
||||
|
||||
std::weak_ptr<Checkpointer> wk(checkpointer_);
|
||||
checkpointer_.reset();
|
||||
|
||||
// The references to our Checkpointer held by 'checkpointer_' and
|
||||
// 'checkpointers' have been removed, so if the use count is nonzero, a
|
||||
// checkpoint is currently in progress. Wait for it to end, otherwise
|
||||
// creating a new DatabaseCon to the same database may fail due to the
|
||||
// database being locked by our (now old) Checkpointer.
|
||||
while (wk.use_count())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DatabaseCon::Setup
|
||||
setup_DatabaseCon(Config const& c, std::optional<beast::Journal> j)
|
||||
{
|
||||
DatabaseCon::Setup setup;
|
||||
|
||||
setup.startUp = c.START_UP;
|
||||
setup.standAlone = c.standalone();
|
||||
setup.dataDir = c.legacy("database_path");
|
||||
if (!setup.standAlone && setup.dataDir.empty())
|
||||
{
|
||||
Throw<std::runtime_error>("database_path must be set.");
|
||||
}
|
||||
|
||||
if (!setup.globalPragma)
|
||||
{
|
||||
setup.globalPragma = [&c, &j]() {
|
||||
auto const& sqlite = c.section("sqlite");
|
||||
auto result = std::make_unique<std::vector<std::string>>();
|
||||
result->reserve(3);
|
||||
|
||||
// defaults
|
||||
std::string safety_level;
|
||||
std::string journal_mode = "wal";
|
||||
std::string synchronous = "normal";
|
||||
std::string temp_store = "file";
|
||||
bool showRiskWarning = false;
|
||||
|
||||
if (set(safety_level, "safety_level", sqlite))
|
||||
{
|
||||
if (boost::iequals(safety_level, "low"))
|
||||
{
|
||||
// low safety defaults
|
||||
journal_mode = "memory";
|
||||
synchronous = "off";
|
||||
temp_store = "memory";
|
||||
showRiskWarning = true;
|
||||
}
|
||||
else if (!boost::iequals(safety_level, "high"))
|
||||
{
|
||||
Throw<std::runtime_error>("Invalid safety_level value: " + safety_level);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// #journal_mode Valid values : delete, truncate, persist,
|
||||
// memory, wal, off
|
||||
if (set(journal_mode, "journal_mode", sqlite) && !safety_level.empty())
|
||||
{
|
||||
Throw<std::runtime_error>(
|
||||
"Configuration file may not define both "
|
||||
"\"safety_level\" and \"journal_mode\"");
|
||||
}
|
||||
bool higherRisk = boost::iequals(journal_mode, "memory") || boost::iequals(journal_mode, "off");
|
||||
showRiskWarning = showRiskWarning || higherRisk;
|
||||
if (higherRisk || boost::iequals(journal_mode, "delete") || boost::iequals(journal_mode, "truncate") ||
|
||||
boost::iequals(journal_mode, "persist") || boost::iequals(journal_mode, "wal"))
|
||||
{
|
||||
result->emplace_back(boost::str(boost::format(CommonDBPragmaJournal) % journal_mode));
|
||||
}
|
||||
else
|
||||
{
|
||||
Throw<std::runtime_error>("Invalid journal_mode value: " + journal_mode);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// #synchronous Valid values : off, normal, full, extra
|
||||
if (set(synchronous, "synchronous", sqlite) && !safety_level.empty())
|
||||
{
|
||||
Throw<std::runtime_error>(
|
||||
"Configuration file may not define both "
|
||||
"\"safety_level\" and \"synchronous\"");
|
||||
}
|
||||
bool higherRisk = boost::iequals(synchronous, "off");
|
||||
showRiskWarning = showRiskWarning || higherRisk;
|
||||
if (higherRisk || boost::iequals(synchronous, "normal") || boost::iequals(synchronous, "full") ||
|
||||
boost::iequals(synchronous, "extra"))
|
||||
{
|
||||
result->emplace_back(boost::str(boost::format(CommonDBPragmaSync) % synchronous));
|
||||
}
|
||||
else
|
||||
{
|
||||
Throw<std::runtime_error>("Invalid synchronous value: " + synchronous);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// #temp_store Valid values : default, file, memory
|
||||
if (set(temp_store, "temp_store", sqlite) && !safety_level.empty())
|
||||
{
|
||||
Throw<std::runtime_error>(
|
||||
"Configuration file may not define both "
|
||||
"\"safety_level\" and \"temp_store\"");
|
||||
}
|
||||
bool higherRisk = boost::iequals(temp_store, "memory");
|
||||
showRiskWarning = showRiskWarning || higherRisk;
|
||||
if (higherRisk || boost::iequals(temp_store, "default") || boost::iequals(temp_store, "file"))
|
||||
{
|
||||
result->emplace_back(boost::str(boost::format(CommonDBPragmaTemp) % temp_store));
|
||||
}
|
||||
else
|
||||
{
|
||||
Throw<std::runtime_error>("Invalid temp_store value: " + temp_store);
|
||||
}
|
||||
}
|
||||
|
||||
if (showRiskWarning && j && c.LEDGER_HISTORY > SQLITE_TUNING_CUTOFF)
|
||||
{
|
||||
JLOG(j->warn()) << "reducing the data integrity guarantees from the "
|
||||
"default [sqlite] behavior is not recommended for "
|
||||
"nodes storing large amounts of history, because of the "
|
||||
"difficulty inherent in rebuilding corrupted data.";
|
||||
}
|
||||
XRPL_ASSERT(result->size() == 3, "xrpl::setup_DatabaseCon::globalPragma : result size is 3");
|
||||
return result;
|
||||
}();
|
||||
}
|
||||
setup.useGlobalPragma = true;
|
||||
|
||||
auto setPragma = [](std::string& pragma, std::string const& key, int64_t value) {
|
||||
pragma = "PRAGMA " + key + "=" + std::to_string(value) + ";";
|
||||
};
|
||||
|
||||
// Lgr Pragma
|
||||
setPragma(setup.lgrPragma[0], "journal_size_limit", 1582080);
|
||||
|
||||
// TX Pragma
|
||||
int64_t page_size = 4096;
|
||||
int64_t journal_size_limit = 1582080;
|
||||
if (c.exists("sqlite"))
|
||||
{
|
||||
auto& s = c.section("sqlite");
|
||||
set(journal_size_limit, "journal_size_limit", s);
|
||||
set(page_size, "page_size", s);
|
||||
if (page_size < 512 || page_size > 65536)
|
||||
Throw<std::runtime_error>("Invalid page_size. Must be between 512 and 65536.");
|
||||
|
||||
if (page_size & (page_size - 1))
|
||||
Throw<std::runtime_error>("Invalid page_size. Must be a power of 2.");
|
||||
}
|
||||
|
||||
setPragma(setup.txPragma[0], "page_size", page_size);
|
||||
setPragma(setup.txPragma[1], "journal_size_limit", journal_size_limit);
|
||||
setPragma(setup.txPragma[2], "max_page_count", 4294967294);
|
||||
setPragma(setup.txPragma[3], "mmap_size", 17179869184);
|
||||
|
||||
return setup;
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<std::string> const> DatabaseCon::Setup::globalPragma;
|
||||
|
||||
void
|
||||
DatabaseCon::setupCheckpointing(JobQueue* q, Logs& l)
|
||||
{
|
||||
if (!q)
|
||||
Throw<std::logic_error>("No JobQueue");
|
||||
checkpointer_ = checkpointers.create(session_, *q, l);
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <xrpld/app/misc/ValidatorList.h>
|
||||
#include <xrpld/app/misc/ValidatorSite.h>
|
||||
#include <xrpld/app/rdb/RelationalDatabase.h>
|
||||
#include <xrpld/app/rdb/Wallet.h>
|
||||
#include <xrpld/overlay/Cluster.h>
|
||||
#include <xrpld/overlay/detail/ConnectAttempt.h>
|
||||
#include <xrpld/overlay/detail/PeerImp.h>
|
||||
@@ -20,6 +19,7 @@
|
||||
#include <xrpl/beast/core/LexicalCast.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/server/SimpleWriter.h>
|
||||
#include <xrpl/server/Wallet.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/asio/executor_work_guard.hpp>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include <xrpld/app/rdb/RelationalDatabase.h>
|
||||
#include <xrpld/app/rdb/Wallet.h>
|
||||
#include <xrpld/overlay/PeerReservationTable.h>
|
||||
|
||||
#include <xrpl/core/PeerReservationTable.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/protocol/PublicKey.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/server/Wallet.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/rdb/PeerFinder.h>
|
||||
#include <xrpld/core/SociDB.h>
|
||||
#include <xrpld/peerfinder/detail/Store.h>
|
||||
|
||||
#include <xrpl/rdb/SociDB.h>
|
||||
|
||||
namespace xrpl {
|
||||
namespace PeerFinder {
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/misc/Manifest.h>
|
||||
|
||||
#include <xrpl/basics/CountedObject.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/protocol/Book.h>
|
||||
#include <xrpl/protocol/ErrorCodes.h>
|
||||
#include <xrpl/resource/Consumer.h>
|
||||
#include <xrpl/server/Manifest.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user