mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-19 10:05:48 +00:00
Compare commits
3 Commits
sync-2.2.0
...
sync-2.2.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
068cea41b6 | ||
|
|
4cf97ad212 | ||
|
|
a0e19f9dcd |
@@ -1171,7 +1171,7 @@ if (tests)
|
||||
#]===============================]
|
||||
src/test/rpc/AccountCurrencies_test.cpp
|
||||
src/test/rpc/AccountInfo_test.cpp
|
||||
src/test/rpc/AccountLinesRPC_test.cpp
|
||||
src/test/rpc/AccountLines_test.cpp
|
||||
src/test/rpc/AccountObjects_test.cpp
|
||||
src/test/rpc/AccountOffers_test.cpp
|
||||
src/test/rpc/AccountNamespace_test.cpp
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <ripple/app/misc/NetworkOPs.h>
|
||||
#include <ripple/app/misc/ValidatorList.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/PerfLog.h>
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/basics/chrono.h>
|
||||
#include <ripple/consensus/LedgerTiming.h>
|
||||
@@ -126,7 +127,13 @@ RCLValidationsAdaptor::now() const
|
||||
std::optional<RCLValidatedLedger>
|
||||
RCLValidationsAdaptor::acquire(LedgerHash const& hash)
|
||||
{
|
||||
auto ledger = app_.getLedgerMaster().getLedgerByHash(hash);
|
||||
using namespace std::chrono_literals;
|
||||
auto ledger = perf::measureDurationAndLog(
|
||||
[&]() { return app_.getLedgerMaster().getLedgerByHash(hash); },
|
||||
"getLedgerByHash",
|
||||
10ms,
|
||||
j_);
|
||||
|
||||
if (!ledger)
|
||||
{
|
||||
JLOG(j_.debug())
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <ripple/app/misc/NetworkOPs.h>
|
||||
#include <ripple/basics/DecayingSample.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/PerfLog.h>
|
||||
#include <ripple/beast/container/aged_map.h>
|
||||
#include <ripple/beast/core/LexicalCast.h>
|
||||
#include <ripple/core/JobQueue.h>
|
||||
@@ -70,76 +71,83 @@ public:
|
||||
std::uint32_t seq,
|
||||
InboundLedger::Reason reason) override
|
||||
{
|
||||
assert(hash.isNonZero());
|
||||
assert(
|
||||
reason != InboundLedger::Reason::SHARD ||
|
||||
(seq != 0 && app_.getShardStore()));
|
||||
auto doAcquire = [&, seq, reason]() -> std::shared_ptr<Ledger const> {
|
||||
assert(hash.isNonZero());
|
||||
assert(
|
||||
reason != InboundLedger::Reason::SHARD ||
|
||||
(seq != 0 && app_.getShardStore()));
|
||||
|
||||
// probably not the right rule
|
||||
if (app_.getOPs().isNeedNetworkLedger() &&
|
||||
(reason != InboundLedger::Reason::GENERIC) &&
|
||||
(reason != InboundLedger::Reason::CONSENSUS))
|
||||
return {};
|
||||
|
||||
bool isNew = true;
|
||||
std::shared_ptr<InboundLedger> inbound;
|
||||
{
|
||||
ScopedLockType sl(mLock);
|
||||
if (stopping_)
|
||||
{
|
||||
// probably not the right rule
|
||||
if (app_.getOPs().isNeedNetworkLedger() &&
|
||||
(reason != InboundLedger::Reason::GENERIC) &&
|
||||
(reason != InboundLedger::Reason::CONSENSUS))
|
||||
return {};
|
||||
|
||||
bool isNew = true;
|
||||
std::shared_ptr<InboundLedger> inbound;
|
||||
{
|
||||
ScopedLockType sl(mLock);
|
||||
if (stopping_)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto it = mLedgers.find(hash);
|
||||
if (it != mLedgers.end())
|
||||
{
|
||||
isNew = false;
|
||||
inbound = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
inbound = std::make_shared<InboundLedger>(
|
||||
app_,
|
||||
hash,
|
||||
seq,
|
||||
reason,
|
||||
std::ref(m_clock),
|
||||
mPeerSetBuilder->build());
|
||||
mLedgers.emplace(hash, inbound);
|
||||
inbound->init(sl);
|
||||
++mCounter;
|
||||
}
|
||||
}
|
||||
|
||||
auto it = mLedgers.find(hash);
|
||||
if (it != mLedgers.end())
|
||||
{
|
||||
isNew = false;
|
||||
inbound = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
inbound = std::make_shared<InboundLedger>(
|
||||
app_,
|
||||
hash,
|
||||
seq,
|
||||
reason,
|
||||
std::ref(m_clock),
|
||||
mPeerSetBuilder->build());
|
||||
mLedgers.emplace(hash, inbound);
|
||||
inbound->init(sl);
|
||||
++mCounter;
|
||||
}
|
||||
}
|
||||
|
||||
if (inbound->isFailed())
|
||||
return {};
|
||||
|
||||
if (!isNew)
|
||||
inbound->update(seq);
|
||||
|
||||
if (!inbound->isComplete())
|
||||
return {};
|
||||
|
||||
if (reason == InboundLedger::Reason::HISTORY)
|
||||
{
|
||||
if (inbound->getLedger()->stateMap().family().isShardBacked())
|
||||
app_.getNodeStore().storeLedger(inbound->getLedger());
|
||||
}
|
||||
else if (reason == InboundLedger::Reason::SHARD)
|
||||
{
|
||||
auto shardStore = app_.getShardStore();
|
||||
if (!shardStore)
|
||||
{
|
||||
JLOG(j_.error())
|
||||
<< "Acquiring shard with no shard store available";
|
||||
if (inbound->isFailed())
|
||||
return {};
|
||||
|
||||
if (!isNew)
|
||||
inbound->update(seq);
|
||||
|
||||
if (!inbound->isComplete())
|
||||
return {};
|
||||
|
||||
if (reason == InboundLedger::Reason::HISTORY)
|
||||
{
|
||||
if (inbound->getLedger()->stateMap().family().isShardBacked())
|
||||
app_.getNodeStore().storeLedger(inbound->getLedger());
|
||||
}
|
||||
if (inbound->getLedger()->stateMap().family().isShardBacked())
|
||||
shardStore->setStored(inbound->getLedger());
|
||||
else
|
||||
shardStore->storeLedger(inbound->getLedger());
|
||||
}
|
||||
return inbound->getLedger();
|
||||
else if (reason == InboundLedger::Reason::SHARD)
|
||||
{
|
||||
auto shardStore = app_.getShardStore();
|
||||
if (!shardStore)
|
||||
{
|
||||
JLOG(j_.error())
|
||||
<< "Acquiring shard with no shard store available";
|
||||
return {};
|
||||
}
|
||||
if (inbound->getLedger()->stateMap().family().isShardBacked())
|
||||
shardStore->setStored(inbound->getLedger());
|
||||
else
|
||||
shardStore->storeLedger(inbound->getLedger());
|
||||
}
|
||||
return inbound->getLedger();
|
||||
};
|
||||
using namespace std::chrono_literals;
|
||||
std::shared_ptr<Ledger const> ledger = perf::measureDurationAndLog(
|
||||
doAcquire, "InboundLedgersImp::acquire", 500ms, j_);
|
||||
|
||||
return ledger;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -945,7 +945,7 @@ public:
|
||||
auto setup = setup_DatabaseCon(*config_, m_journal);
|
||||
setup.useGlobalPragma = false;
|
||||
|
||||
mWalletDB = makeWalletDB(setup);
|
||||
mWalletDB = makeWalletDB(setup, m_journal);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
|
||||
@@ -594,7 +594,7 @@ run(int argc, char** argv)
|
||||
try
|
||||
{
|
||||
auto setup = setup_DatabaseCon(*config);
|
||||
if (!doVacuumDB(setup))
|
||||
if (!doVacuumDB(setup, config->journal()))
|
||||
return -1;
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
|
||||
@@ -36,13 +36,15 @@ namespace ripple {
|
||||
* download process or continues an existing one.
|
||||
* @param setup Path to the database and other opening parameters.
|
||||
* @param path Path of the new file to download.
|
||||
* @param j Journal.
|
||||
* @return Pair containing a unique pointer to the database and the amount of
|
||||
* bytes already downloaded if a download is being continued.
|
||||
*/
|
||||
std::pair<std::unique_ptr<DatabaseCon>, std::optional<std::uint64_t>>
|
||||
openDatabaseBodyDb(
|
||||
DatabaseCon::Setup const& setup,
|
||||
boost::filesystem::path const& path);
|
||||
boost::filesystem::path const& path,
|
||||
beast::Journal j);
|
||||
|
||||
/**
|
||||
* @brief databaseBodyDoPut Saves a new fragment of a downloaded file.
|
||||
|
||||
@@ -30,10 +30,14 @@ namespace ripple {
|
||||
* descriptor.
|
||||
* @param dir Path to the database to open.
|
||||
* @param dbName Name of the database.
|
||||
* @param j Journal.
|
||||
* @return Unique pointer to the opened database.
|
||||
*/
|
||||
std::unique_ptr<DatabaseCon>
|
||||
makeArchiveDB(boost::filesystem::path const& dir, std::string const& dbName);
|
||||
makeArchiveDB(
|
||||
boost::filesystem::path const& dir,
|
||||
std::string const& dbName,
|
||||
beast::Journal j);
|
||||
|
||||
/**
|
||||
* @brief readArchiveDB Reads entries from the shard archive database and
|
||||
|
||||
@@ -39,13 +39,15 @@ struct DatabasePair
|
||||
* and returns their descriptors.
|
||||
* @param config Config object.
|
||||
* @param setup Path to the databases and other opening parameters.
|
||||
* @param j Journal.
|
||||
* @return Pair of unique pointers to the opened ledger and transaction
|
||||
* databases.
|
||||
*/
|
||||
DatabasePair
|
||||
makeShardCompleteLedgerDBs(
|
||||
Config const& config,
|
||||
DatabaseCon::Setup const& setup);
|
||||
DatabaseCon::Setup const& setup,
|
||||
beast::Journal j);
|
||||
|
||||
/**
|
||||
* @brief makeShardIncompleteLedgerDBs Opens shard databases for partially
|
||||
@@ -53,6 +55,7 @@ makeShardCompleteLedgerDBs(
|
||||
* @param config Config object.
|
||||
* @param setup Path to the databases and other opening parameters.
|
||||
* @param checkpointerSetup Checkpointer parameters.
|
||||
* @param j Journal.
|
||||
* @return Pair of unique pointers to the opened ledger and transaction
|
||||
* databases.
|
||||
*/
|
||||
@@ -60,7 +63,8 @@ DatabasePair
|
||||
makeShardIncompleteLedgerDBs(
|
||||
Config const& config,
|
||||
DatabaseCon::Setup const& setup,
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup);
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup,
|
||||
beast::Journal j);
|
||||
|
||||
/**
|
||||
* @brief updateLedgerDBs Saves the given ledger to shard databases.
|
||||
@@ -86,12 +90,14 @@ updateLedgerDBs(
|
||||
* descriptor.
|
||||
* @param setup Path to the database and other opening parameters.
|
||||
* @param checkpointerSetup Checkpointer parameters.
|
||||
* @param j Journal.
|
||||
* @return Unique pointer to the opened database.
|
||||
*/
|
||||
std::unique_ptr<DatabaseCon>
|
||||
makeAcquireDB(
|
||||
DatabaseCon::Setup const& setup,
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup);
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup,
|
||||
beast::Journal j);
|
||||
|
||||
/**
|
||||
* @brief insertAcquireDBIndex Adds a new shard index to the shard acquire
|
||||
|
||||
@@ -27,10 +27,11 @@ namespace ripple {
|
||||
/**
|
||||
* @brief doVacuumDB Creates, initialises, and performs cleanup on a database.
|
||||
* @param setup Path to the database and other opening parameters.
|
||||
* @param j Journal.
|
||||
* @return True if the vacuum process completed successfully.
|
||||
*/
|
||||
bool
|
||||
doVacuumDB(DatabaseCon::Setup const& setup);
|
||||
doVacuumDB(DatabaseCon::Setup const& setup, beast::Journal j);
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
|
||||
@@ -32,19 +32,24 @@ namespace ripple {
|
||||
/**
|
||||
* @brief makeWalletDB Opens the wallet database and returns it.
|
||||
* @param setup Path to the database and other opening parameters.
|
||||
* @param j Journal.
|
||||
* @return Unique pointer to the database descriptor.
|
||||
*/
|
||||
std::unique_ptr<DatabaseCon>
|
||||
makeWalletDB(DatabaseCon::Setup const& setup);
|
||||
makeWalletDB(DatabaseCon::Setup const& setup, beast::Journal j);
|
||||
|
||||
/**
|
||||
* @brief makeTestWalletDB Opens a test wallet database with an arbitrary name.
|
||||
* @param setup Path to the database and other opening parameters.
|
||||
* @param dbname Name of the database.
|
||||
* @param j Journal.
|
||||
* @return Unique pointer to the database descriptor.
|
||||
*/
|
||||
std::unique_ptr<DatabaseCon>
|
||||
makeTestWalletDB(DatabaseCon::Setup const& setup, std::string const& dbname);
|
||||
makeTestWalletDB(
|
||||
DatabaseCon::Setup const& setup,
|
||||
std::string const& dbname,
|
||||
beast::Journal j);
|
||||
|
||||
/**
|
||||
* @brief getManifests Loads a manifest from the wallet database and stores it
|
||||
|
||||
@@ -47,6 +47,7 @@ struct DatabasePairValid
|
||||
* @param config Config object.
|
||||
* @param setup Path to database and opening parameters.
|
||||
* @param checkpointerSetup Database checkpointer setup.
|
||||
* @param j Journal.
|
||||
* @return Struct DatabasePairValid which contain unique pointers to ledger
|
||||
* and transaction databases and flag if opening was successfull.
|
||||
*/
|
||||
@@ -54,7 +55,8 @@ DatabasePairValid
|
||||
makeLedgerDBs(
|
||||
Config const& config,
|
||||
DatabaseCon::Setup const& setup,
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup);
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup,
|
||||
beast::Journal j);
|
||||
|
||||
/**
|
||||
* @brief getMinLedgerSeq Returns minimum ledger sequence in given table.
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace detail {
|
||||
* @param config Config object.
|
||||
* @param setup Path to database and opening parameters.
|
||||
* @param checkpointerSetup Database checkpointer setup.
|
||||
* @param j Journal.
|
||||
* @return Struct DatabasePair which contains unique pointers to the ledger
|
||||
* and transaction databases.
|
||||
*/
|
||||
@@ -44,7 +45,8 @@ DatabasePair
|
||||
makeMetaDBs(
|
||||
Config const& config,
|
||||
DatabaseCon::Setup const& setup,
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup);
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup,
|
||||
beast::Journal j);
|
||||
|
||||
/**
|
||||
* @brief saveLedgerMeta Stores (transaction ID -> shard index) and
|
||||
|
||||
@@ -67,11 +67,12 @@ DatabasePairValid
|
||||
makeLedgerDBs(
|
||||
Config const& config,
|
||||
DatabaseCon::Setup const& setup,
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup)
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup,
|
||||
beast::Journal j)
|
||||
{
|
||||
// ledger database
|
||||
auto lgr{std::make_unique<DatabaseCon>(
|
||||
setup, LgrDBName, LgrDBPragma, LgrDBInit, checkpointerSetup)};
|
||||
setup, LgrDBName, LgrDBPragma, LgrDBInit, checkpointerSetup, j)};
|
||||
lgr->getSession() << boost::str(
|
||||
boost::format("PRAGMA cache_size=-%d;") %
|
||||
kilobytes(config.getValueFor(SizedItem::lgrDBCache)));
|
||||
@@ -80,7 +81,7 @@ makeLedgerDBs(
|
||||
{
|
||||
// transaction database
|
||||
auto tx{std::make_unique<DatabaseCon>(
|
||||
setup, TxDBName, TxDBPragma, TxDBInit, checkpointerSetup)};
|
||||
setup, TxDBName, TxDBPragma, TxDBInit, checkpointerSetup, j)};
|
||||
tx->getSession() << boost::str(
|
||||
boost::format("PRAGMA cache_size=-%d;") %
|
||||
kilobytes(config.getValueFor(SizedItem::txnDBCache)));
|
||||
|
||||
@@ -32,7 +32,8 @@ DatabasePair
|
||||
makeMetaDBs(
|
||||
Config const& config,
|
||||
DatabaseCon::Setup const& setup,
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup)
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup,
|
||||
beast::Journal j)
|
||||
{
|
||||
// ledger meta database
|
||||
auto lgrMetaDB{std::make_unique<DatabaseCon>(
|
||||
@@ -40,14 +41,20 @@ makeMetaDBs(
|
||||
LgrMetaDBName,
|
||||
LgrMetaDBPragma,
|
||||
LgrMetaDBInit,
|
||||
checkpointerSetup)};
|
||||
checkpointerSetup,
|
||||
j)};
|
||||
|
||||
if (!config.useTxTables())
|
||||
return {std::move(lgrMetaDB), nullptr};
|
||||
|
||||
// transaction meta database
|
||||
auto txMetaDB{std::make_unique<DatabaseCon>(
|
||||
setup, TxMetaDBName, TxMetaDBPragma, TxMetaDBInit, checkpointerSetup)};
|
||||
setup,
|
||||
TxMetaDBName,
|
||||
TxMetaDBPragma,
|
||||
TxMetaDBInit,
|
||||
checkpointerSetup,
|
||||
j)};
|
||||
|
||||
return {std::move(lgrMetaDB), std::move(txMetaDB)};
|
||||
}
|
||||
|
||||
@@ -447,7 +447,7 @@ SQLiteDatabaseImp::makeLedgerDBs(
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup)
|
||||
{
|
||||
auto [lgr, tx, res] =
|
||||
detail::makeLedgerDBs(config, setup, checkpointerSetup);
|
||||
detail::makeLedgerDBs(config, setup, checkpointerSetup, j_);
|
||||
txdb_ = std::move(tx);
|
||||
lgrdb_ = std::move(lgr);
|
||||
return res;
|
||||
@@ -460,7 +460,7 @@ SQLiteDatabaseImp::makeMetaDBs(
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup)
|
||||
{
|
||||
auto [lgrMetaDB, txMetaDB] =
|
||||
detail::makeMetaDBs(config, setup, checkpointerSetup);
|
||||
detail::makeMetaDBs(config, setup, checkpointerSetup, j_);
|
||||
|
||||
txMetaDB_ = std::move(txMetaDB);
|
||||
lgrMetaDB_ = std::move(lgrMetaDB);
|
||||
|
||||
@@ -25,14 +25,15 @@ namespace ripple {
|
||||
std::pair<std::unique_ptr<DatabaseCon>, std::optional<std::uint64_t>>
|
||||
openDatabaseBodyDb(
|
||||
DatabaseCon::Setup const& setup,
|
||||
boost::filesystem::path const& path)
|
||||
boost::filesystem::path const& path,
|
||||
beast::Journal j)
|
||||
{
|
||||
// SOCI requires boost::optional (not std::optional) as the parameter.
|
||||
boost::optional<std::string> pathFromDb;
|
||||
boost::optional<std::uint64_t> size;
|
||||
|
||||
auto conn = std::make_unique<DatabaseCon>(
|
||||
setup, "Download", DownloaderDBPragma, DatabaseBodyDBInit);
|
||||
setup, "Download", DownloaderDBPragma, DatabaseBodyDBInit, j);
|
||||
|
||||
auto& session = *conn->checkoutDb();
|
||||
|
||||
|
||||
@@ -22,10 +22,13 @@
|
||||
namespace ripple {
|
||||
|
||||
std::unique_ptr<DatabaseCon>
|
||||
makeArchiveDB(boost::filesystem::path const& dir, std::string const& dbName)
|
||||
makeArchiveDB(
|
||||
boost::filesystem::path const& dir,
|
||||
std::string const& dbName,
|
||||
beast::Journal j)
|
||||
{
|
||||
return std::make_unique<DatabaseCon>(
|
||||
dir, dbName, DownloaderDBPragma, ShardArchiveHandlerDBInit);
|
||||
dir, dbName, DownloaderDBPragma, ShardArchiveHandlerDBInit, j);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -27,16 +27,17 @@ namespace ripple {
|
||||
DatabasePair
|
||||
makeShardCompleteLedgerDBs(
|
||||
Config const& config,
|
||||
DatabaseCon::Setup const& setup)
|
||||
DatabaseCon::Setup const& setup,
|
||||
beast::Journal j)
|
||||
{
|
||||
auto tx{std::make_unique<DatabaseCon>(
|
||||
setup, TxDBName, FinalShardDBPragma, TxDBInit)};
|
||||
setup, TxDBName, FinalShardDBPragma, TxDBInit, j)};
|
||||
tx->getSession() << boost::str(
|
||||
boost::format("PRAGMA cache_size=-%d;") %
|
||||
kilobytes(config.getValueFor(SizedItem::txnDBCache, std::nullopt)));
|
||||
|
||||
auto lgr{std::make_unique<DatabaseCon>(
|
||||
setup, LgrDBName, FinalShardDBPragma, LgrDBInit)};
|
||||
setup, LgrDBName, FinalShardDBPragma, LgrDBInit, j)};
|
||||
lgr->getSession() << boost::str(
|
||||
boost::format("PRAGMA cache_size=-%d;") %
|
||||
kilobytes(config.getValueFor(SizedItem::lgrDBCache, std::nullopt)));
|
||||
@@ -48,18 +49,19 @@ DatabasePair
|
||||
makeShardIncompleteLedgerDBs(
|
||||
Config const& config,
|
||||
DatabaseCon::Setup const& setup,
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup)
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup,
|
||||
beast::Journal j)
|
||||
{
|
||||
// transaction database
|
||||
auto tx{std::make_unique<DatabaseCon>(
|
||||
setup, TxDBName, TxDBPragma, TxDBInit, checkpointerSetup)};
|
||||
setup, TxDBName, TxDBPragma, TxDBInit, checkpointerSetup, j)};
|
||||
tx->getSession() << boost::str(
|
||||
boost::format("PRAGMA cache_size=-%d;") %
|
||||
kilobytes(config.getValueFor(SizedItem::txnDBCache)));
|
||||
|
||||
// ledger database
|
||||
auto lgr{std::make_unique<DatabaseCon>(
|
||||
setup, LgrDBName, LgrDBPragma, LgrDBInit, checkpointerSetup)};
|
||||
setup, LgrDBName, LgrDBPragma, LgrDBInit, checkpointerSetup, j)};
|
||||
lgr->getSession() << boost::str(
|
||||
boost::format("PRAGMA cache_size=-%d;") %
|
||||
kilobytes(config.getValueFor(SizedItem::lgrDBCache)));
|
||||
@@ -209,14 +211,16 @@ updateLedgerDBs(
|
||||
std::unique_ptr<DatabaseCon>
|
||||
makeAcquireDB(
|
||||
DatabaseCon::Setup const& setup,
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup)
|
||||
DatabaseCon::CheckpointerSetup const& checkpointerSetup,
|
||||
beast::Journal j)
|
||||
{
|
||||
return std::make_unique<DatabaseCon>(
|
||||
setup,
|
||||
AcquireShardDBName,
|
||||
AcquireShardDBPragma,
|
||||
AcquireShardDBInit,
|
||||
checkpointerSetup);
|
||||
checkpointerSetup,
|
||||
j);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
namespace ripple {
|
||||
|
||||
bool
|
||||
doVacuumDB(DatabaseCon::Setup const& setup)
|
||||
doVacuumDB(DatabaseCon::Setup const& setup, beast::Journal j)
|
||||
{
|
||||
boost::filesystem::path dbPath = setup.dataDir / TxDBName;
|
||||
|
||||
@@ -41,7 +41,7 @@ doVacuumDB(DatabaseCon::Setup const& setup)
|
||||
}
|
||||
|
||||
auto txnDB =
|
||||
std::make_unique<DatabaseCon>(setup, TxDBName, TxDBPragma, TxDBInit);
|
||||
std::make_unique<DatabaseCon>(setup, TxDBName, TxDBPragma, TxDBInit, j);
|
||||
auto& session = txnDB->getSession();
|
||||
std::uint32_t pageSize;
|
||||
|
||||
|
||||
@@ -23,19 +23,22 @@
|
||||
namespace ripple {
|
||||
|
||||
std::unique_ptr<DatabaseCon>
|
||||
makeWalletDB(DatabaseCon::Setup const& setup)
|
||||
makeWalletDB(DatabaseCon::Setup const& setup, beast::Journal j)
|
||||
{
|
||||
// wallet database
|
||||
return std::make_unique<DatabaseCon>(
|
||||
setup, WalletDBName, std::array<char const*, 0>(), WalletDBInit);
|
||||
setup, WalletDBName, std::array<char const*, 0>(), WalletDBInit, j);
|
||||
}
|
||||
|
||||
std::unique_ptr<DatabaseCon>
|
||||
makeTestWalletDB(DatabaseCon::Setup const& setup, std::string const& dbname)
|
||||
makeTestWalletDB(
|
||||
DatabaseCon::Setup const& setup,
|
||||
std::string const& dbname,
|
||||
beast::Journal j)
|
||||
{
|
||||
// wallet database
|
||||
return std::make_unique<DatabaseCon>(
|
||||
setup, dbname.data(), std::array<char const*, 0>(), WalletDBInit);
|
||||
setup, dbname.data(), std::array<char const*, 0>(), WalletDBInit, j);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -179,6 +179,30 @@ make_PerfLog(
|
||||
beast::Journal journal,
|
||||
std::function<void()>&& signalStop);
|
||||
|
||||
template <typename Func, class Rep, class Period>
|
||||
auto
|
||||
measureDurationAndLog(
|
||||
Func&& func,
|
||||
const std::string& actionDescription,
|
||||
std::chrono::duration<Rep, Period> maxDelay,
|
||||
const beast::Journal& journal)
|
||||
{
|
||||
auto start_time = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto result = func();
|
||||
|
||||
auto end_time = std::chrono::high_resolution_clock::now();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
end_time - start_time);
|
||||
if (duration > maxDelay)
|
||||
{
|
||||
JLOG(journal.warn())
|
||||
<< actionDescription << " took " << duration.count() << " ms";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace perf
|
||||
} // namespace ripple
|
||||
|
||||
|
||||
@@ -426,6 +426,12 @@ public:
|
||||
int
|
||||
getValueFor(SizedItem item, std::optional<std::size_t> node = std::nullopt)
|
||||
const;
|
||||
|
||||
beast::Journal
|
||||
journal() const
|
||||
{
|
||||
return j_;
|
||||
}
|
||||
};
|
||||
|
||||
FeeSetup
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define RIPPLE_APP_DATA_DATABASECON_H_INCLUDED
|
||||
|
||||
#include <ripple/app/main/DBInit.h>
|
||||
#include <ripple/basics/PerfLog.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/core/SociDB.h>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
@@ -115,7 +116,8 @@ public:
|
||||
Setup const& setup,
|
||||
std::string const& dbName,
|
||||
std::array<char const*, N> const& pragma,
|
||||
std::array<char const*, M> const& initSQL)
|
||||
std::array<char const*, M> const& initSQL,
|
||||
beast::Journal journal)
|
||||
// Use temporary files or regular DB files?
|
||||
: DatabaseCon(
|
||||
setup.standAlone && !setup.reporting &&
|
||||
@@ -126,7 +128,8 @@ public:
|
||||
: (setup.dataDir / dbName),
|
||||
setup.commonPragma(),
|
||||
pragma,
|
||||
initSQL)
|
||||
initSQL,
|
||||
journal)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -137,8 +140,9 @@ public:
|
||||
std::string const& dbName,
|
||||
std::array<char const*, N> const& pragma,
|
||||
std::array<char const*, M> const& initSQL,
|
||||
CheckpointerSetup const& checkpointerSetup)
|
||||
: DatabaseCon(setup, dbName, pragma, initSQL)
|
||||
CheckpointerSetup const& checkpointerSetup,
|
||||
beast::Journal journal)
|
||||
: DatabaseCon(setup, dbName, pragma, initSQL, journal)
|
||||
{
|
||||
setupCheckpointing(checkpointerSetup.jobQueue, *checkpointerSetup.logs);
|
||||
}
|
||||
@@ -148,8 +152,9 @@ public:
|
||||
boost::filesystem::path const& dataDir,
|
||||
std::string const& dbName,
|
||||
std::array<char const*, N> const& pragma,
|
||||
std::array<char const*, M> const& initSQL)
|
||||
: DatabaseCon(dataDir / dbName, nullptr, pragma, initSQL)
|
||||
std::array<char const*, M> const& initSQL,
|
||||
beast::Journal journal)
|
||||
: DatabaseCon(dataDir / dbName, nullptr, pragma, initSQL, journal)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -160,8 +165,9 @@ public:
|
||||
std::string const& dbName,
|
||||
std::array<char const*, N> const& pragma,
|
||||
std::array<char const*, M> const& initSQL,
|
||||
CheckpointerSetup const& checkpointerSetup)
|
||||
: DatabaseCon(dataDir, dbName, pragma, initSQL)
|
||||
CheckpointerSetup const& checkpointerSetup,
|
||||
beast::Journal journal)
|
||||
: DatabaseCon(dataDir, dbName, pragma, initSQL, journal)
|
||||
{
|
||||
setupCheckpointing(checkpointerSetup.jobQueue, *checkpointerSetup.logs);
|
||||
}
|
||||
@@ -177,7 +183,14 @@ public:
|
||||
LockedSociSession
|
||||
checkoutDb()
|
||||
{
|
||||
return LockedSociSession(session_, lock_);
|
||||
using namespace std::chrono_literals;
|
||||
LockedSociSession session = perf::measureDurationAndLog(
|
||||
[&]() { return LockedSociSession(session_, lock_); },
|
||||
"checkoutDb",
|
||||
10ms,
|
||||
j_);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -189,8 +202,9 @@ private:
|
||||
boost::filesystem::path const& pPath,
|
||||
std::vector<std::string> const* commonPragma,
|
||||
std::array<char const*, N> const& pragma,
|
||||
std::array<char const*, M> const& initSQL)
|
||||
: session_(std::make_shared<soci::session>())
|
||||
std::array<char const*, M> const& initSQL,
|
||||
beast::Journal journal)
|
||||
: session_(std::make_shared<soci::session>()), j_(journal)
|
||||
{
|
||||
open(*session_, "sqlite", pPath.string());
|
||||
|
||||
@@ -224,6 +238,8 @@ private:
|
||||
// shared_ptr in this class. session_ will never be null.
|
||||
std::shared_ptr<soci::session> const session_;
|
||||
std::shared_ptr<Checkpointer> checkpointer_;
|
||||
|
||||
beast::Journal const j_;
|
||||
};
|
||||
|
||||
// Return the checkpointer from its id. If the checkpointer no longer exists, an
|
||||
|
||||
@@ -102,13 +102,16 @@ public:
|
||||
@param io_service The asio context for running a strand.
|
||||
|
||||
@param ec Set to the error, if any occurred
|
||||
|
||||
@param j Journal.
|
||||
*/
|
||||
void
|
||||
open(
|
||||
boost::filesystem::path const& path,
|
||||
Config const& config,
|
||||
boost::asio::io_service& io_service,
|
||||
boost::system::error_code& ec);
|
||||
boost::system::error_code& ec,
|
||||
beast::Journal j);
|
||||
};
|
||||
|
||||
/** Algorithm for storing buffers when parsing.
|
||||
|
||||
@@ -43,7 +43,8 @@ private:
|
||||
getParser(
|
||||
boost::filesystem::path dstPath,
|
||||
std::function<void(boost::filesystem::path)> complete,
|
||||
boost::system::error_code& ec) override;
|
||||
boost::system::error_code& ec,
|
||||
beast::Journal j) override;
|
||||
|
||||
bool
|
||||
checkPath(boost::filesystem::path const& dstPath) override;
|
||||
|
||||
@@ -113,7 +113,8 @@ private:
|
||||
getParser(
|
||||
boost::filesystem::path dstPath,
|
||||
std::function<void(boost::filesystem::path)> complete,
|
||||
boost::system::error_code& ec) = 0;
|
||||
boost::system::error_code& ec,
|
||||
beast::Journal j) = 0;
|
||||
|
||||
virtual bool
|
||||
checkPath(boost::filesystem::path const& dstPath) = 0;
|
||||
|
||||
@@ -47,7 +47,8 @@ DatabaseBody::value_type::open(
|
||||
boost::filesystem::path const& path,
|
||||
Config const& config,
|
||||
boost::asio::io_service& io_service,
|
||||
boost::system::error_code& ec)
|
||||
boost::system::error_code& ec,
|
||||
beast::Journal j)
|
||||
{
|
||||
strand_.reset(new boost::asio::io_service::strand(io_service));
|
||||
path_ = path;
|
||||
@@ -56,7 +57,7 @@ DatabaseBody::value_type::open(
|
||||
setup.dataDir = path.parent_path();
|
||||
setup.useGlobalPragma = false;
|
||||
|
||||
auto [conn, size] = openDatabaseBodyDb(setup, path);
|
||||
auto [conn, size] = openDatabaseBodyDb(setup, path, j);
|
||||
conn_ = std::move(conn);
|
||||
if (size)
|
||||
fileSize_ = *size;
|
||||
|
||||
@@ -45,13 +45,14 @@ auto
|
||||
DatabaseDownloader::getParser(
|
||||
boost::filesystem::path dstPath,
|
||||
std::function<void(boost::filesystem::path)> complete,
|
||||
boost::system::error_code& ec) -> std::shared_ptr<parser>
|
||||
boost::system::error_code& ec,
|
||||
beast::Journal j) -> std::shared_ptr<parser>
|
||||
{
|
||||
using namespace boost::beast;
|
||||
|
||||
auto p = std::make_shared<http::response_parser<DatabaseBody>>();
|
||||
p->body_limit(std::numeric_limits<std::uint64_t>::max());
|
||||
p->get().body().open(dstPath, config_, io_service_, ec);
|
||||
p->get().body().open(dstPath, config_, io_service_, ec, j);
|
||||
|
||||
if (ec)
|
||||
p->get().body().close();
|
||||
|
||||
@@ -146,7 +146,7 @@ HTTPDownloader::do_session(
|
||||
if (stop_.load())
|
||||
return exit();
|
||||
|
||||
auto p = this->getParser(dstPath, complete, ec);
|
||||
auto p = this->getParser(dstPath, complete, ec, j_);
|
||||
if (ec)
|
||||
return failAndExit("getParser", p);
|
||||
|
||||
|
||||
@@ -859,7 +859,8 @@ Shard::open(std::lock_guard<std::mutex> const& lock)
|
||||
acquireInfo_ = std::make_unique<AcquireInfo>();
|
||||
acquireInfo_->SQLiteDB = makeAcquireDB(
|
||||
setup,
|
||||
DatabaseCon::CheckpointerSetup{&app_.getJobQueue(), &app_.logs()});
|
||||
DatabaseCon::CheckpointerSetup{&app_.getJobQueue(), &app_.logs()},
|
||||
j_);
|
||||
|
||||
state_ = ShardState::acquire;
|
||||
progress_ = 0;
|
||||
@@ -978,7 +979,7 @@ Shard::initSQLite(std::lock_guard<std::mutex> const&)
|
||||
case ShardState::complete:
|
||||
case ShardState::finalizing:
|
||||
case ShardState::finalized: {
|
||||
auto [lgr, tx] = makeShardCompleteLedgerDBs(config, setup);
|
||||
auto [lgr, tx] = makeShardCompleteLedgerDBs(config, setup, j_);
|
||||
|
||||
lgrSQLiteDB_ = std::move(lgr);
|
||||
lgrSQLiteDB_->getSession() << boost::str(
|
||||
@@ -1002,7 +1003,8 @@ Shard::initSQLite(std::lock_guard<std::mutex> const&)
|
||||
config,
|
||||
setup,
|
||||
DatabaseCon::CheckpointerSetup{
|
||||
&app_.getJobQueue(), &app_.logs()});
|
||||
&app_.getJobQueue(), &app_.logs()},
|
||||
j_);
|
||||
|
||||
lgrSQLiteDB_ = std::move(lgr);
|
||||
lgrSQLiteDB_->getSession() << boost::str(
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <ripple/app/misc/Transaction.h>
|
||||
#include <ripple/app/misc/ValidatorList.h>
|
||||
#include <ripple/app/tx/apply.h>
|
||||
#include <ripple/basics/PerfLog.h>
|
||||
#include <ripple/basics/UptimeClock.h>
|
||||
#include <ripple/basics/base64.h>
|
||||
#include <ripple/basics/random.h>
|
||||
@@ -920,8 +921,16 @@ PeerImp::onReadMessage(error_code ec, std::size_t bytes_transferred)
|
||||
while (read_buffer_.size() > 0)
|
||||
{
|
||||
std::size_t bytes_consumed;
|
||||
std::tie(bytes_consumed, ec) =
|
||||
invokeProtocolMessage(read_buffer_.data(), *this, hint);
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
std::tie(bytes_consumed, ec) = perf::measureDurationAndLog(
|
||||
[&]() {
|
||||
return invokeProtocolMessage(read_buffer_.data(), *this, hint);
|
||||
},
|
||||
"invokeProtocolMessage",
|
||||
350ms,
|
||||
journal_);
|
||||
|
||||
if (ec)
|
||||
return fail("onReadMessage", ec);
|
||||
if (!socket_.is_open())
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define RIPPLE_PROTOCOL_B58_UTILS_H_INCLUDED
|
||||
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/protocol/impl/token_errors.h>
|
||||
|
||||
#include <boost/outcome.hpp>
|
||||
#include <boost/outcome/result.hpp>
|
||||
@@ -71,12 +72,12 @@ carrying_add(std::uint64_t a, std::uint64_t b)
|
||||
// (i.e a[0] is the 2^0 coefficient, a[n] is the 2^(64*n) coefficient)
|
||||
// panics if overflows (this is a specialized adder for b58 decoding.
|
||||
// it should never overflow).
|
||||
inline void
|
||||
[[nodiscard]] inline TokenCodecErrc
|
||||
inplace_bigint_add(std::span<std::uint64_t> a, std::uint64_t b)
|
||||
{
|
||||
if (a.size() <= 1)
|
||||
{
|
||||
ripple::LogicError("Input span too small for inplace_bigint_add");
|
||||
return TokenCodecErrc::inputTooSmall;
|
||||
}
|
||||
|
||||
std::uint64_t carry;
|
||||
@@ -86,28 +87,29 @@ inplace_bigint_add(std::span<std::uint64_t> a, std::uint64_t b)
|
||||
{
|
||||
if (!carry)
|
||||
{
|
||||
return;
|
||||
return TokenCodecErrc::success;
|
||||
}
|
||||
std::tie(v, carry) = carrying_add(v, 1);
|
||||
}
|
||||
if (carry)
|
||||
{
|
||||
LogicError("Overflow in inplace_bigint_add");
|
||||
return TokenCodecErrc::overflowAdd;
|
||||
}
|
||||
return TokenCodecErrc::success;
|
||||
}
|
||||
|
||||
inline void
|
||||
[[nodiscard]] inline TokenCodecErrc
|
||||
inplace_bigint_mul(std::span<std::uint64_t> a, std::uint64_t b)
|
||||
{
|
||||
if (a.empty())
|
||||
{
|
||||
LogicError("Empty span passed to inplace_bigint_mul");
|
||||
return TokenCodecErrc::inputTooSmall;
|
||||
}
|
||||
|
||||
auto const last_index = a.size() - 1;
|
||||
if (a[last_index] != 0)
|
||||
{
|
||||
LogicError("Non-zero element in inplace_bigint_mul last index");
|
||||
return TokenCodecErrc::inputTooLarge;
|
||||
}
|
||||
|
||||
std::uint64_t carry = 0;
|
||||
@@ -116,7 +118,9 @@ inplace_bigint_mul(std::span<std::uint64_t> a, std::uint64_t b)
|
||||
std::tie(coeff, carry) = carrying_mul(coeff, b, carry);
|
||||
}
|
||||
a[last_index] = carry;
|
||||
return TokenCodecErrc::success;
|
||||
}
|
||||
|
||||
// divide a "big uint" value inplace and return the mod
|
||||
// numerator is stored so smallest coefficients come first
|
||||
[[nodiscard]] inline std::uint64_t
|
||||
@@ -166,11 +170,7 @@ inplace_bigint_div_rem(std::span<uint64_t> numerator, std::uint64_t divisor)
|
||||
b58_10_to_b58_be(std::uint64_t input)
|
||||
{
|
||||
constexpr std::uint64_t B_58_10 = 430804206899405824; // 58^10;
|
||||
if (input >= B_58_10)
|
||||
{
|
||||
LogicError("Input to b58_10_to_b58_be equals or exceeds 58^10.");
|
||||
}
|
||||
|
||||
assert(input < B_58_10);
|
||||
constexpr std::size_t resultSize = 10;
|
||||
std::array<std::uint8_t, resultSize> result{};
|
||||
int i = 0;
|
||||
|
||||
@@ -32,6 +32,7 @@ enum class TokenCodecErrc {
|
||||
mismatchedTokenType,
|
||||
mismatchedChecksum,
|
||||
invalidEncodingChar,
|
||||
overflowAdd,
|
||||
unknown,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -472,6 +472,11 @@ b256_to_b58_be(std::span<std::uint8_t const> input, std::span<std::uint8_t> out)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
static constexpr std::uint64_t B_58_10 = 430804206899405824; // 58^10;
|
||||
if (base_58_10_coeff[i] >= B_58_10)
|
||||
{
|
||||
return Unexpected(TokenCodecErrc::inputTooLarge);
|
||||
}
|
||||
std::array<std::uint8_t, 10> const b58_be =
|
||||
ripple::b58_fast::detail::b58_10_to_b58_be(base_58_10_coeff[i]);
|
||||
std::size_t to_skip = 0;
|
||||
@@ -570,10 +575,23 @@ b58_to_b256_be(std::string_view input, std::span<std::uint8_t> out)
|
||||
for (int i = 1; i < num_b_58_10_coeffs; ++i)
|
||||
{
|
||||
std::uint64_t const c = b_58_10_coeff[i];
|
||||
ripple::b58_fast::detail::inplace_bigint_mul(
|
||||
std::span(&result[0], cur_result_size + 1), B_58_10);
|
||||
ripple::b58_fast::detail::inplace_bigint_add(
|
||||
std::span(&result[0], cur_result_size + 1), c);
|
||||
|
||||
{
|
||||
auto code = ripple::b58_fast::detail::inplace_bigint_mul(
|
||||
std::span(&result[0], cur_result_size + 1), B_58_10);
|
||||
if (code != TokenCodecErrc::success)
|
||||
{
|
||||
return Unexpected(code);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto code = ripple::b58_fast::detail::inplace_bigint_add(
|
||||
std::span(&result[0], cur_result_size + 1), c);
|
||||
if (code != TokenCodecErrc::success)
|
||||
{
|
||||
return Unexpected(code);
|
||||
}
|
||||
}
|
||||
if (result[cur_result_size] != 0)
|
||||
{
|
||||
cur_result_size += 1;
|
||||
|
||||
@@ -71,6 +71,9 @@ doAccountChannels(RPC::JsonContext& context)
|
||||
if (!params.isMember(jss::account))
|
||||
return RPC::missing_field_error(jss::account);
|
||||
|
||||
if (!params[jss::account].isString())
|
||||
return RPC::invalid_field_error(jss::account);
|
||||
|
||||
std::shared_ptr<ReadView const> ledger;
|
||||
auto result = RPC::lookupLedger(ledger, context);
|
||||
if (!ledger)
|
||||
|
||||
@@ -33,19 +33,29 @@ doAccountCurrencies(RPC::JsonContext& context)
|
||||
{
|
||||
auto& params = context.params;
|
||||
|
||||
if (!(params.isMember(jss::account) || params.isMember(jss::ident)))
|
||||
return RPC::missing_field_error(jss::account);
|
||||
|
||||
std::string strIdent;
|
||||
if (params.isMember(jss::account))
|
||||
{
|
||||
if (!params[jss::account].isString())
|
||||
return RPC::invalid_field_error(jss::account);
|
||||
strIdent = params[jss::account].asString();
|
||||
}
|
||||
else if (params.isMember(jss::ident))
|
||||
{
|
||||
if (!params[jss::ident].isString())
|
||||
return RPC::invalid_field_error(jss::ident);
|
||||
strIdent = params[jss::ident].asString();
|
||||
}
|
||||
|
||||
// Get the current ledger
|
||||
std::shared_ptr<ReadView const> ledger;
|
||||
auto result = RPC::lookupLedger(ledger, context);
|
||||
if (!ledger)
|
||||
return result;
|
||||
|
||||
if (!(params.isMember(jss::account) || params.isMember(jss::ident)))
|
||||
return RPC::missing_field_error(jss::account);
|
||||
|
||||
std::string const strIdent(
|
||||
params.isMember(jss::account) ? params[jss::account].asString()
|
||||
: params[jss::ident].asString());
|
||||
|
||||
// Get info on account.
|
||||
auto id = parseBase58<AccountID>(strIdent);
|
||||
if (!id)
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/RPCErr.h>
|
||||
#include <ripple/protocol/UintTypes.h>
|
||||
#include <ripple/protocol/jss.h>
|
||||
#include <ripple/rpc/Context.h>
|
||||
@@ -53,9 +54,17 @@ doAccountInfo(RPC::JsonContext& context)
|
||||
|
||||
std::string strIdent;
|
||||
if (params.isMember(jss::account))
|
||||
{
|
||||
if (!params[jss::account].isString())
|
||||
return RPC::invalid_field_error(jss::account);
|
||||
strIdent = params[jss::account].asString();
|
||||
}
|
||||
else if (params.isMember(jss::ident))
|
||||
{
|
||||
if (!params[jss::ident].isString())
|
||||
return RPC::invalid_field_error(jss::ident);
|
||||
strIdent = params[jss::ident].asString();
|
||||
}
|
||||
else
|
||||
return RPC::missing_field_error(jss::account);
|
||||
|
||||
|
||||
@@ -92,6 +92,9 @@ doAccountLines(RPC::JsonContext& context)
|
||||
if (!params.isMember(jss::account))
|
||||
return RPC::missing_field_error(jss::account);
|
||||
|
||||
if (!params[jss::account].isString())
|
||||
return RPC::invalid_field_error(jss::account);
|
||||
|
||||
std::shared_ptr<ReadView const> ledger;
|
||||
auto result = RPC::lookupLedger(ledger, context);
|
||||
if (!ledger)
|
||||
|
||||
@@ -54,17 +54,19 @@ doAccountNFTs(RPC::JsonContext& context)
|
||||
if (!params.isMember(jss::account))
|
||||
return RPC::missing_field_error(jss::account);
|
||||
|
||||
std::shared_ptr<ReadView const> ledger;
|
||||
auto result = RPC::lookupLedger(ledger, context);
|
||||
if (ledger == nullptr)
|
||||
return result;
|
||||
if (!params[jss::account].isString())
|
||||
return RPC::invalid_field_error(jss::account);
|
||||
|
||||
auto id = parseBase58<AccountID>(params[jss::account].asString());
|
||||
if (!id)
|
||||
{
|
||||
RPC::inject_error(rpcACT_MALFORMED, result);
|
||||
return result;
|
||||
return rpcError(rpcACT_MALFORMED);
|
||||
}
|
||||
|
||||
std::shared_ptr<ReadView const> ledger;
|
||||
auto result = RPC::lookupLedger(ledger, context);
|
||||
if (ledger == nullptr)
|
||||
return result;
|
||||
auto const accountID{id.value()};
|
||||
|
||||
if (!ledger->exists(keylet::account(accountID)))
|
||||
@@ -167,6 +169,9 @@ doAccountObjects(RPC::JsonContext& context)
|
||||
if (!params.isMember(jss::account))
|
||||
return RPC::missing_field_error(jss::account);
|
||||
|
||||
if (!params[jss::account].isString())
|
||||
return RPC::invalid_field_error(jss::account);
|
||||
|
||||
std::shared_ptr<ReadView const> ledger;
|
||||
auto result = RPC::lookupLedger(ledger, context);
|
||||
if (ledger == nullptr)
|
||||
|
||||
@@ -60,6 +60,9 @@ doAccountOffers(RPC::JsonContext& context)
|
||||
if (!params.isMember(jss::account))
|
||||
return RPC::missing_field_error(jss::account);
|
||||
|
||||
if (!params[jss::account].isString())
|
||||
return RPC::invalid_field_error(jss::account);
|
||||
|
||||
std::shared_ptr<ReadView const> ledger;
|
||||
auto result = RPC::lookupLedger(ledger, context);
|
||||
if (!ledger)
|
||||
@@ -84,7 +87,7 @@ doAccountOffers(RPC::JsonContext& context)
|
||||
return *err;
|
||||
|
||||
if (limit == 0)
|
||||
return rpcError(rpcINVALID_PARAMS);
|
||||
return RPC::invalid_field_error(jss::limit);
|
||||
|
||||
Json::Value& jsonOffers(result[jss::offers] = Json::arrayValue);
|
||||
std::vector<std::shared_ptr<SLE const>> offers;
|
||||
@@ -101,13 +104,13 @@ doAccountOffers(RPC::JsonContext& context)
|
||||
std::stringstream marker(params[jss::marker].asString());
|
||||
std::string value;
|
||||
if (!std::getline(marker, value, ','))
|
||||
return rpcError(rpcINVALID_PARAMS);
|
||||
return RPC::invalid_field_error(jss::marker);
|
||||
|
||||
if (!startAfter.parseHex(value))
|
||||
return rpcError(rpcINVALID_PARAMS);
|
||||
return RPC::invalid_field_error(jss::marker);
|
||||
|
||||
if (!std::getline(marker, value, ','))
|
||||
return rpcError(rpcINVALID_PARAMS);
|
||||
return RPC::invalid_field_error(jss::marker);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -115,7 +118,7 @@ doAccountOffers(RPC::JsonContext& context)
|
||||
}
|
||||
catch (boost::bad_lexical_cast&)
|
||||
{
|
||||
return rpcError(rpcINVALID_PARAMS);
|
||||
return RPC::invalid_field_error(jss::marker);
|
||||
}
|
||||
|
||||
// We then must check if the object pointed to by the marker is actually
|
||||
|
||||
@@ -426,12 +426,12 @@ doAccountTxJson(RPC::JsonContext& context)
|
||||
if (context.apiVersion > 1u && params.isMember(jss::binary) &&
|
||||
!params[jss::binary].isBool())
|
||||
{
|
||||
return rpcError(rpcINVALID_PARAMS);
|
||||
return RPC::invalid_field_error(jss::binary);
|
||||
}
|
||||
if (context.apiVersion > 1u && params.isMember(jss::forward) &&
|
||||
!params[jss::forward].isBool())
|
||||
{
|
||||
return rpcError(rpcINVALID_PARAMS);
|
||||
return RPC::invalid_field_error(jss::forward);
|
||||
}
|
||||
|
||||
args.limit = params.isMember(jss::limit) ? params[jss::limit].asUInt() : 0;
|
||||
@@ -440,7 +440,10 @@ doAccountTxJson(RPC::JsonContext& context)
|
||||
params.isMember(jss::forward) && params[jss::forward].asBool();
|
||||
|
||||
if (!params.isMember(jss::account))
|
||||
return rpcError(rpcINVALID_PARAMS);
|
||||
return RPC::missing_field_error(jss::account);
|
||||
|
||||
if (!params[jss::account].isString())
|
||||
return RPC::invalid_field_error(jss::account);
|
||||
|
||||
auto const account =
|
||||
parseBase58<AccountID>(params[jss::account].asString());
|
||||
|
||||
@@ -66,6 +66,10 @@ doNoRippleCheck(RPC::JsonContext& context)
|
||||
|
||||
if (!params.isMember("role"))
|
||||
return RPC::missing_field_error("role");
|
||||
|
||||
if (!params[jss::account].isString())
|
||||
return RPC::invalid_field_error(jss::account);
|
||||
|
||||
bool roleGateway = false;
|
||||
{
|
||||
std::string const role = params["role"].asString();
|
||||
@@ -90,7 +94,7 @@ doNoRippleCheck(RPC::JsonContext& context)
|
||||
if (context.apiVersion > 1u && params.isMember(jss::transactions) &&
|
||||
!params[jss::transactions].isBool())
|
||||
{
|
||||
return rpcError(rpcINVALID_PARAMS);
|
||||
return RPC::invalid_field_error(jss::transactions);
|
||||
}
|
||||
|
||||
std::shared_ptr<ReadView const> ledger;
|
||||
|
||||
@@ -114,7 +114,7 @@ ShardArchiveHandler::init()
|
||||
{
|
||||
create_directories(downloadDir_);
|
||||
|
||||
sqlDB_ = makeArchiveDB(downloadDir_, stateDBName);
|
||||
sqlDB_ = makeArchiveDB(downloadDir_, stateDBName, j_);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
@@ -139,7 +139,7 @@ ShardArchiveHandler::initFromDB(std::lock_guard<std::mutex> const& lock)
|
||||
exists(downloadDir_ / stateDBName) &&
|
||||
is_regular_file(downloadDir_ / stateDBName));
|
||||
|
||||
sqlDB_ = makeArchiveDB(downloadDir_, stateDBName);
|
||||
sqlDB_ = makeArchiveDB(downloadDir_, stateDBName, j_);
|
||||
|
||||
readArchiveDB(*sqlDB_, [&](std::string const& url_, int state) {
|
||||
parsedURL url;
|
||||
|
||||
@@ -255,7 +255,7 @@ public:
|
||||
setup.dataDir = getDatabasePath();
|
||||
assert(!setup.useGlobalPragma);
|
||||
|
||||
auto dbCon = makeTestWalletDB(setup, dbName);
|
||||
auto dbCon = makeTestWalletDB(setup, dbName, env.journal);
|
||||
|
||||
auto getPopulatedManifests =
|
||||
[](ManifestCache const& cache) -> std::vector<Manifest const*> {
|
||||
|
||||
@@ -953,6 +953,25 @@ struct PayChan_test : public beast::unit_test::suite
|
||||
auto const chan1Str = to_string(channel(alice, bob, env.seq(alice)));
|
||||
env(paychan::create(alice, bob, channelFunds, settleDelay, pk));
|
||||
env.close();
|
||||
{
|
||||
// test account non-string
|
||||
auto testInvalidAccountParam = [&](auto const& param) {
|
||||
Json::Value params;
|
||||
params[jss::account] = param;
|
||||
auto jrr = env.rpc(
|
||||
"json", "account_channels", to_string(params))[jss::result];
|
||||
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::error_message] == "Invalid field 'account'.");
|
||||
};
|
||||
|
||||
testInvalidAccountParam(1);
|
||||
testInvalidAccountParam(1.1);
|
||||
testInvalidAccountParam(true);
|
||||
testInvalidAccountParam(Json::Value(Json::nullValue));
|
||||
testInvalidAccountParam(Json::Value(Json::objectValue));
|
||||
testInvalidAccountParam(Json::Value(Json::arrayValue));
|
||||
}
|
||||
{
|
||||
auto const r =
|
||||
env.rpc("account_channels", alice.human(), bob.human());
|
||||
|
||||
@@ -177,6 +177,7 @@ class base58_test : public beast::unit_test::suite
|
||||
constexpr std::size_t iters = 100000;
|
||||
auto eng = randEngine();
|
||||
std::uniform_int_distribution<std::uint64_t> dist;
|
||||
std::uniform_int_distribution<std::uint64_t> dist1(1);
|
||||
for (int i = 0; i < iters; ++i)
|
||||
{
|
||||
std::uint64_t const d = dist(eng);
|
||||
@@ -209,12 +210,31 @@ class base58_test : public beast::unit_test::suite
|
||||
|
||||
auto const refAdd = boostBigInt + d;
|
||||
|
||||
b58_fast::detail::inplace_bigint_add(
|
||||
auto const result = b58_fast::detail::inplace_bigint_add(
|
||||
std::span<uint64_t>(bigInt.data(), bigInt.size()), d);
|
||||
BEAST_EXPECT(result == TokenCodecErrc::success);
|
||||
auto const foundAdd = multiprecision_utils::toBoostMP(bigInt);
|
||||
BEAST_EXPECT(refAdd == foundAdd);
|
||||
}
|
||||
for (int i = 0; i < iters; ++i)
|
||||
{
|
||||
std::uint64_t const d = dist1(eng);
|
||||
// Force overflow
|
||||
std::vector<std::uint64_t> bigInt(
|
||||
5, std::numeric_limits<std::uint64_t>::max());
|
||||
|
||||
auto const boostBigInt = multiprecision_utils::toBoostMP(
|
||||
std::span<std::uint64_t>(bigInt.data(), bigInt.size()));
|
||||
|
||||
auto const refAdd = boostBigInt + d;
|
||||
|
||||
auto const result = b58_fast::detail::inplace_bigint_add(
|
||||
std::span<uint64_t>(bigInt.data(), bigInt.size()), d);
|
||||
BEAST_EXPECT(result == TokenCodecErrc::overflowAdd);
|
||||
auto const foundAdd = multiprecision_utils::toBoostMP(bigInt);
|
||||
BEAST_EXPECT(refAdd != foundAdd);
|
||||
}
|
||||
for (int i = 0; i < iters; ++i)
|
||||
{
|
||||
std::uint64_t const d = dist(eng);
|
||||
auto bigInt = multiprecision_utils::randomBigInt(/* minSize */ 2);
|
||||
@@ -226,11 +246,29 @@ class base58_test : public beast::unit_test::suite
|
||||
|
||||
auto const refMul = boostBigInt * d;
|
||||
|
||||
b58_fast::detail::inplace_bigint_mul(
|
||||
auto const result = b58_fast::detail::inplace_bigint_mul(
|
||||
std::span<uint64_t>(bigInt.data(), bigInt.size()), d);
|
||||
BEAST_EXPECT(result == TokenCodecErrc::success);
|
||||
auto const foundMul = multiprecision_utils::toBoostMP(bigInt);
|
||||
BEAST_EXPECT(refMul == foundMul);
|
||||
}
|
||||
for (int i = 0; i < iters; ++i)
|
||||
{
|
||||
std::uint64_t const d = dist1(eng);
|
||||
// Force overflow
|
||||
std::vector<std::uint64_t> bigInt(
|
||||
5, std::numeric_limits<std::uint64_t>::max());
|
||||
auto const boostBigInt = multiprecision_utils::toBoostMP(
|
||||
std::span<std::uint64_t>(bigInt.data(), bigInt.size()));
|
||||
|
||||
auto const refMul = boostBigInt * d;
|
||||
|
||||
auto const result = b58_fast::detail::inplace_bigint_mul(
|
||||
std::span<uint64_t>(bigInt.data(), bigInt.size()), d);
|
||||
BEAST_EXPECT(result == TokenCodecErrc::inputTooLarge);
|
||||
auto const foundMul = multiprecision_utils::toBoostMP(bigInt);
|
||||
BEAST_EXPECT(refMul != foundMul);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -39,6 +39,7 @@ class AccountCurrencies_test : public beast::unit_test::suite
|
||||
|
||||
{ // invalid ledger (hash)
|
||||
Json::Value params;
|
||||
params[jss::account] = Account{"bob"}.human();
|
||||
params[jss::ledger_hash] = 1;
|
||||
auto const result = env.rpc(
|
||||
"json",
|
||||
@@ -56,6 +57,50 @@ class AccountCurrencies_test : public beast::unit_test::suite
|
||||
result[jss::error_message] == "Missing field 'account'.");
|
||||
}
|
||||
|
||||
{
|
||||
// test account non-string
|
||||
auto testInvalidAccountParam = [&](auto const& param) {
|
||||
Json::Value params;
|
||||
params[jss::account] = param;
|
||||
auto jrr = env.rpc(
|
||||
"json",
|
||||
"account_currencies",
|
||||
to_string(params))[jss::result];
|
||||
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::error_message] == "Invalid field 'account'.");
|
||||
};
|
||||
|
||||
testInvalidAccountParam(1);
|
||||
testInvalidAccountParam(1.1);
|
||||
testInvalidAccountParam(true);
|
||||
testInvalidAccountParam(Json::Value(Json::nullValue));
|
||||
testInvalidAccountParam(Json::Value(Json::objectValue));
|
||||
testInvalidAccountParam(Json::Value(Json::arrayValue));
|
||||
}
|
||||
|
||||
{
|
||||
// test ident non-string
|
||||
auto testInvalidIdentParam = [&](auto const& param) {
|
||||
Json::Value params;
|
||||
params[jss::ident] = param;
|
||||
auto jrr = env.rpc(
|
||||
"json",
|
||||
"account_currencies",
|
||||
to_string(params))[jss::result];
|
||||
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::error_message] == "Invalid field 'ident'.");
|
||||
};
|
||||
|
||||
testInvalidIdentParam(1);
|
||||
testInvalidIdentParam(1.1);
|
||||
testInvalidIdentParam(true);
|
||||
testInvalidIdentParam(Json::Value(Json::nullValue));
|
||||
testInvalidIdentParam(Json::Value(Json::objectValue));
|
||||
testInvalidIdentParam(Json::Value(Json::arrayValue));
|
||||
}
|
||||
|
||||
{
|
||||
Json::Value params;
|
||||
params[jss::account] =
|
||||
@@ -198,6 +243,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(AccountCurrencies, app, ripple);
|
||||
BEAST_DEFINE_TESTSUITE(AccountCurrencies, rpc, ripple);
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -36,6 +36,7 @@ public:
|
||||
void
|
||||
testErrors()
|
||||
{
|
||||
testcase("Errors");
|
||||
using namespace jtx;
|
||||
Env env(*this);
|
||||
{
|
||||
@@ -78,12 +79,53 @@ public:
|
||||
BEAST_EXPECT(
|
||||
info[jss::result][jss::error_message] == "Account malformed.");
|
||||
}
|
||||
{
|
||||
// Cannot pass a non-string into the `account` param
|
||||
|
||||
auto testInvalidAccountParam = [&](auto const& param) {
|
||||
Json::Value params;
|
||||
params[jss::account] = param;
|
||||
auto jrr = env.rpc(
|
||||
"json", "account_info", to_string(params))[jss::result];
|
||||
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::error_message] == "Invalid field 'account'.");
|
||||
};
|
||||
|
||||
testInvalidAccountParam(1);
|
||||
testInvalidAccountParam(1.1);
|
||||
testInvalidAccountParam(true);
|
||||
testInvalidAccountParam(Json::Value(Json::nullValue));
|
||||
testInvalidAccountParam(Json::Value(Json::objectValue));
|
||||
testInvalidAccountParam(Json::Value(Json::arrayValue));
|
||||
}
|
||||
{
|
||||
// Cannot pass a non-string into the `ident` param
|
||||
|
||||
auto testInvalidIdentParam = [&](auto const& param) {
|
||||
Json::Value params;
|
||||
params[jss::ident] = param;
|
||||
auto jrr = env.rpc(
|
||||
"json", "account_info", to_string(params))[jss::result];
|
||||
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::error_message] == "Invalid field 'ident'.");
|
||||
};
|
||||
|
||||
testInvalidIdentParam(1);
|
||||
testInvalidIdentParam(1.1);
|
||||
testInvalidIdentParam(true);
|
||||
testInvalidIdentParam(Json::Value(Json::nullValue));
|
||||
testInvalidIdentParam(Json::Value(Json::objectValue));
|
||||
testInvalidIdentParam(Json::Value(Json::arrayValue));
|
||||
}
|
||||
}
|
||||
|
||||
// Test the "signer_lists" argument in account_info.
|
||||
void
|
||||
testSignerLists()
|
||||
{
|
||||
testcase("Signer lists");
|
||||
using namespace jtx;
|
||||
Env env(*this);
|
||||
Account const alice{"alice"};
|
||||
@@ -205,6 +247,7 @@ public:
|
||||
void
|
||||
testSignerListsApiVersion2()
|
||||
{
|
||||
testcase("Signer lists APIv2");
|
||||
using namespace jtx;
|
||||
Env env{*this};
|
||||
Account const alice{"alice"};
|
||||
@@ -326,6 +369,7 @@ public:
|
||||
void
|
||||
testSignerListsV2()
|
||||
{
|
||||
testcase("Signer lists v2");
|
||||
using namespace jtx;
|
||||
Env env(*this);
|
||||
Account const alice{"alice"};
|
||||
@@ -515,6 +559,7 @@ public:
|
||||
void
|
||||
testAccountFlags(FeatureBitset const& features)
|
||||
{
|
||||
testcase("Account flags");
|
||||
using namespace jtx;
|
||||
|
||||
Env env(*this, features);
|
||||
@@ -654,7 +699,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(AccountInfo, app, ripple);
|
||||
BEAST_DEFINE_TESTSUITE(AccountInfo, rpc, ripple);
|
||||
|
||||
} // namespace test
|
||||
} // namespace ripple
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace ripple {
|
||||
|
||||
namespace RPC {
|
||||
|
||||
class AccountLinesRPC_test : public beast::unit_test::suite
|
||||
class AccountLines_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
@@ -55,6 +55,25 @@ public:
|
||||
lines[jss::result][jss::error_message] ==
|
||||
RPC::make_error(rpcACT_MALFORMED)[jss::error_message]);
|
||||
}
|
||||
{
|
||||
// test account non-string
|
||||
auto testInvalidAccountParam = [&](auto const& param) {
|
||||
Json::Value params;
|
||||
params[jss::account] = param;
|
||||
auto jrr = env.rpc(
|
||||
"json", "account_lines", to_string(params))[jss::result];
|
||||
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::error_message] == "Invalid field 'account'.");
|
||||
};
|
||||
|
||||
testInvalidAccountParam(1);
|
||||
testInvalidAccountParam(1.1);
|
||||
testInvalidAccountParam(true);
|
||||
testInvalidAccountParam(Json::Value(Json::nullValue));
|
||||
testInvalidAccountParam(Json::Value(Json::objectValue));
|
||||
testInvalidAccountParam(Json::Value(Json::arrayValue));
|
||||
}
|
||||
Account const alice{"alice"};
|
||||
{
|
||||
// account_lines on an unfunded account.
|
||||
@@ -1474,7 +1493,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(AccountLinesRPC, app, ripple);
|
||||
BEAST_DEFINE_TESTSUITE(AccountLines, rpc, ripple);
|
||||
|
||||
} // namespace RPC
|
||||
} // namespace ripple
|
||||
@@ -125,8 +125,30 @@ public:
|
||||
|
||||
// test error on no account
|
||||
{
|
||||
auto resp = env.rpc("json", "account_objects");
|
||||
BEAST_EXPECT(resp[jss::error_message] == "Syntax error.");
|
||||
Json::Value params;
|
||||
auto resp = env.rpc("json", "account_objects", to_string(params));
|
||||
BEAST_EXPECT(
|
||||
resp[jss::result][jss::error_message] ==
|
||||
"Missing field 'account'.");
|
||||
}
|
||||
// test account non-string
|
||||
{
|
||||
auto testInvalidAccountParam = [&](auto const& param) {
|
||||
Json::Value params;
|
||||
params[jss::account] = param;
|
||||
auto jrr = env.rpc(
|
||||
"json", "account_objects", to_string(params))[jss::result];
|
||||
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::error_message] == "Invalid field 'account'.");
|
||||
};
|
||||
|
||||
testInvalidAccountParam(1);
|
||||
testInvalidAccountParam(1.1);
|
||||
testInvalidAccountParam(true);
|
||||
testInvalidAccountParam(Json::Value(Json::nullValue));
|
||||
testInvalidAccountParam(Json::Value(Json::objectValue));
|
||||
testInvalidAccountParam(Json::Value(Json::arrayValue));
|
||||
}
|
||||
// test error on malformed account string.
|
||||
{
|
||||
@@ -1090,6 +1112,35 @@ public:
|
||||
BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::hashes), 0));
|
||||
}
|
||||
|
||||
void
|
||||
testAccountNFTs()
|
||||
{
|
||||
testcase("account_nfts");
|
||||
|
||||
using namespace jtx;
|
||||
Env env(*this);
|
||||
|
||||
// test validation
|
||||
{
|
||||
auto testInvalidAccountParam = [&](auto const& param) {
|
||||
Json::Value params;
|
||||
params[jss::account] = param;
|
||||
auto jrr = env.rpc(
|
||||
"json", "account_nfts", to_string(params))[jss::result];
|
||||
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::error_message] == "Invalid field 'account'.");
|
||||
};
|
||||
|
||||
testInvalidAccountParam(1);
|
||||
testInvalidAccountParam(1.1);
|
||||
testInvalidAccountParam(true);
|
||||
testInvalidAccountParam(Json::Value(Json::nullValue));
|
||||
testInvalidAccountParam(Json::Value(Json::objectValue));
|
||||
testInvalidAccountParam(Json::Value(Json::arrayValue));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
@@ -1099,10 +1150,11 @@ public:
|
||||
testUnsteppedThenStepped(all);
|
||||
testUnsteppedThenSteppedWithNFTs(all);
|
||||
testObjectTypes(all);
|
||||
testAccountNFTs();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(AccountObjects, app, ripple);
|
||||
BEAST_DEFINE_TESTSUITE(AccountObjects, rpc, ripple);
|
||||
|
||||
} // namespace test
|
||||
} // namespace ripple
|
||||
|
||||
@@ -37,6 +37,8 @@ public:
|
||||
void
|
||||
testNonAdminMinLimit(FeatureBitset features)
|
||||
{
|
||||
testcase("Non-Admin Min Limit");
|
||||
|
||||
using namespace jtx;
|
||||
Env env{*this, envconfig(no_admin), features};
|
||||
Account const gw("G1");
|
||||
@@ -81,6 +83,9 @@ public:
|
||||
void
|
||||
testSequential(FeatureBitset features, bool asAdmin)
|
||||
{
|
||||
testcase(
|
||||
std::string("Sequential - ") + (asAdmin ? "admin" : "non-admin"));
|
||||
|
||||
using namespace jtx;
|
||||
Env env{*this, asAdmin ? envconfig() : envconfig(no_admin), features};
|
||||
Account const gw("G1");
|
||||
@@ -215,6 +220,8 @@ public:
|
||||
void
|
||||
testBadInput(FeatureBitset features)
|
||||
{
|
||||
testcase("Bad input");
|
||||
|
||||
using namespace jtx;
|
||||
Env env(*this, features);
|
||||
Account const gw("G1");
|
||||
@@ -233,6 +240,26 @@ public:
|
||||
BEAST_EXPECT(jrr[jss::error_message] == "Syntax error.");
|
||||
}
|
||||
|
||||
{
|
||||
// test account non-string
|
||||
auto testInvalidAccountParam = [&](auto const& param) {
|
||||
Json::Value params;
|
||||
params[jss::account] = param;
|
||||
auto jrr = env.rpc(
|
||||
"json", "account_offers", to_string(params))[jss::result];
|
||||
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::error_message] == "Invalid field 'account'.");
|
||||
};
|
||||
|
||||
testInvalidAccountParam(1);
|
||||
testInvalidAccountParam(1.1);
|
||||
testInvalidAccountParam(true);
|
||||
testInvalidAccountParam(Json::Value(Json::nullValue));
|
||||
testInvalidAccountParam(Json::Value(Json::objectValue));
|
||||
testInvalidAccountParam(Json::Value(Json::arrayValue));
|
||||
}
|
||||
|
||||
{
|
||||
// empty string account
|
||||
Json::Value jvParams;
|
||||
@@ -282,7 +309,9 @@ public:
|
||||
jvParams.toStyledString())[jss::result];
|
||||
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(jrr[jss::status] == "error");
|
||||
BEAST_EXPECT(jrr[jss::error_message] == "Invalid parameters.");
|
||||
BEAST_EXPECTS(
|
||||
jrr[jss::error_message] == "Invalid field 'marker'.",
|
||||
jrr.toStyledString());
|
||||
}
|
||||
|
||||
{
|
||||
@@ -328,7 +357,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(AccountOffers, app, ripple);
|
||||
BEAST_DEFINE_TESTSUITE(AccountOffers, rpc, ripple);
|
||||
|
||||
} // namespace test
|
||||
} // namespace ripple
|
||||
|
||||
@@ -112,6 +112,7 @@ class AccountTx_test : public beast::unit_test::suite
|
||||
void
|
||||
testParameters(unsigned int apiVersion)
|
||||
{
|
||||
testcase("Parameters APIv" + std::to_string(apiVersion));
|
||||
using namespace test::jtx;
|
||||
|
||||
Env env(*this, supported_amendments() - featureXahauGenesis);
|
||||
@@ -356,6 +357,25 @@ class AccountTx_test : public beast::unit_test::suite
|
||||
env.rpc("json", "account_tx", to_string(p)),
|
||||
rpcLGR_IDX_MALFORMED));
|
||||
}
|
||||
// test account non-string
|
||||
{
|
||||
auto testInvalidAccountParam = [&](auto const& param) {
|
||||
Json::Value params;
|
||||
params[jss::account] = param;
|
||||
auto jrr = env.rpc(
|
||||
"json", "account_tx", to_string(params))[jss::result];
|
||||
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::error_message] == "Invalid field 'account'.");
|
||||
};
|
||||
|
||||
testInvalidAccountParam(1);
|
||||
testInvalidAccountParam(1.1);
|
||||
testInvalidAccountParam(true);
|
||||
testInvalidAccountParam(Json::Value(Json::nullValue));
|
||||
testInvalidAccountParam(Json::Value(Json::objectValue));
|
||||
testInvalidAccountParam(Json::Value(Json::arrayValue));
|
||||
}
|
||||
// test binary and forward for bool/non bool values
|
||||
{
|
||||
Json::Value p{jParms};
|
||||
@@ -391,6 +411,8 @@ class AccountTx_test : public beast::unit_test::suite
|
||||
void
|
||||
testContents()
|
||||
{
|
||||
testcase("Contents");
|
||||
|
||||
// Get results for all transaction types that can be associated
|
||||
// with an account. Start by generating all transaction types.
|
||||
using namespace test::jtx;
|
||||
@@ -787,6 +809,8 @@ class AccountTx_test : public beast::unit_test::suite
|
||||
void
|
||||
testAccountDelete()
|
||||
{
|
||||
testcase("AccountDelete");
|
||||
|
||||
// Verify that if an account is resurrected then the account_tx RPC
|
||||
// command still recovers all transactions on that account before
|
||||
// and after resurrection.
|
||||
@@ -927,7 +951,7 @@ public:
|
||||
testAccountDelete();
|
||||
}
|
||||
};
|
||||
BEAST_DEFINE_TESTSUITE(AccountTx, app, ripple);
|
||||
BEAST_DEFINE_TESTSUITE(AccountTx, rpc, ripple);
|
||||
|
||||
} // namespace test
|
||||
} // namespace ripple
|
||||
|
||||
@@ -64,6 +64,27 @@ class NoRippleCheck_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(result[jss::error_message] == "Missing field 'role'.");
|
||||
}
|
||||
|
||||
// test account non-string
|
||||
{
|
||||
auto testInvalidAccountParam = [&](auto const& param) {
|
||||
Json::Value params;
|
||||
params[jss::account] = param;
|
||||
params[jss::role] = "user";
|
||||
auto jrr = env.rpc(
|
||||
"json", "noripple_check", to_string(params))[jss::result];
|
||||
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::error_message] == "Invalid field 'account'.");
|
||||
};
|
||||
|
||||
testInvalidAccountParam(1);
|
||||
testInvalidAccountParam(1.1);
|
||||
testInvalidAccountParam(true);
|
||||
testInvalidAccountParam(Json::Value(Json::nullValue));
|
||||
testInvalidAccountParam(Json::Value(Json::objectValue));
|
||||
testInvalidAccountParam(Json::Value(Json::arrayValue));
|
||||
}
|
||||
|
||||
{ // invalid role field
|
||||
Json::Value params;
|
||||
params[jss::account] = alice.human();
|
||||
@@ -369,12 +390,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(NoRippleCheck, app, ripple);
|
||||
BEAST_DEFINE_TESTSUITE(NoRippleCheck, rpc, ripple);
|
||||
|
||||
// These tests that deal with limit amounts are slow because of the
|
||||
// offer/account setup, so making them manual -- the additional coverage
|
||||
// provided by them is minimal
|
||||
|
||||
BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(NoRippleCheckLimits, app, ripple, 1);
|
||||
BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(NoRippleCheckLimits, rpc, ripple, 1);
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
Reference in New Issue
Block a user