Skip to content

Commit

Permalink
Add trap_tx_hash command line option
Browse files Browse the repository at this point in the history
This new option can be used only if replay is also enabled. It takes a transaction hash from the ledger loaded for replay, and will cause a specific line to be hit in Transactor.cpp, right before the selected transaction is applied.
  • Loading branch information
Bronek committed May 23, 2024
1 parent 40b4adc commit 297bc96
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 13 deletions.
42 changes: 36 additions & 6 deletions src/ripple/app/main/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ class ApplicationImp : public Application, public BasicApp
std::unique_ptr<RelationalDatabase> mRelationalDatabase;
std::unique_ptr<DatabaseCon> mWalletDB;
std::unique_ptr<Overlay> overlay_;
std::optional<uint256> trapTxID_;

boost::asio::signal_set m_signals;

Expand Down Expand Up @@ -1254,6 +1255,12 @@ class ApplicationImp : public Application, public BasicApp
return maxDisallowedLedger_;
}

virtual std::optional<uint256>
trapTxID() const override
{
return trapTxID_;
}

private:
// For a newly-started validator, this is the greatest persisted ledger
// and new validations must be greater than this.
Expand All @@ -1272,7 +1279,11 @@ class ApplicationImp : public Application, public BasicApp
loadLedgerFromFile(std::string const& ledgerID);

bool
loadOldLedger(std::string const& ledgerID, bool replay, bool isFilename);
loadOldLedger(
std::string const& ledgerID,
bool replay,
bool isFilename,
std::optional<uint256> trapTxID);

void
setMaxDisallowedLedger();
Expand Down Expand Up @@ -1396,15 +1407,20 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline)
startGenesisLedger();
}
else if (
startUp == Config::LOAD || startUp == Config::LOAD_FILE ||
startUp == Config::REPLAY)
startUp == Config::LOAD || //
startUp == Config::LOAD_FILE || startUp == Config::REPLAY ||
startUp == Config::REPLAY_TRAP)
{
JLOG(m_journal.info()) << "Loading specified Ledger";

if (!loadOldLedger(
config_->START_LEDGER,
startUp == Config::REPLAY,
startUp == Config::LOAD_FILE))
(startUp == Config::REPLAY ||
startUp == Config::REPLAY_TRAP),
startUp == Config::LOAD_FILE,
(startUp == Config::REPLAY_TRAP
? std::optional<uint256>(config_->TRAP_TX_HASH)
: std::nullopt)))
{
JLOG(m_journal.error())
<< "The specified ledger could not be loaded.";
Expand Down Expand Up @@ -2086,7 +2102,8 @@ bool
ApplicationImp::loadOldLedger(
std::string const& ledgerID,
bool replay,
bool isFileName)
bool isFileName,
std::optional<uint256> trapTxID)
{
try
{
Expand Down Expand Up @@ -2233,6 +2250,11 @@ ApplicationImp::loadOldLedger(
{
(void)_;
auto txID = tx->getTransactionID();
if (trapTxID && *trapTxID == txID)
{
trapTxID_ = txID;
JLOG(m_journal.debug()) << "Trap transaction set: " << txID;
}

auto s = std::make_shared<Serializer>();
tx->add(*s);
Expand All @@ -2247,6 +2269,14 @@ ApplicationImp::loadOldLedger(
}

m_ledgerMaster->takeReplay(std::move(replayData));

if (trapTxID && !trapTxID_)
{
JLOG(m_journal.fatal())
<< "Ledger " << replayLedger->info().seq
<< " does not contain the transaction hash " << *trapTxID;
return false;
}
}
}
catch (SHAMapMissingNode const& mn)
Expand Down
3 changes: 3 additions & 0 deletions src/ripple/app/main/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,9 @@ class Application : public beast::PropertyStream::Source
* than the last ledger it persisted. */
virtual LedgerIndex
getMaxDisallowedLedger() = 0;

virtual std::optional<uint256>
trapTxID() const = 0;
};

std::unique_ptr<Application>
Expand Down
35 changes: 33 additions & 2 deletions src/ripple/app/main/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,9 @@ run(int argc, char** argv)
"net", "Get the initial ledger from the network.")(
"nodetoshard", "Import node store into shards")(
"replay", "Replay a ledger close.")(
"trap_tx_hash",
po::value<std::string>(),
"Trap a specific transaction during replay.")(
"start", "Start from a fresh Ledger.")(
"startReporting",
po::value<std::string>(),
Expand Down Expand Up @@ -679,7 +682,27 @@ run(int argc, char** argv)
{
config->START_LEDGER = vm["ledger"].as<std::string>();
if (vm.count("replay"))
config->START_UP = Config::REPLAY;
{
if (vm.count("trap_tx_hash"))
{
uint256 tmp = {};
auto hash = vm["trap_tx_hash"].as<std::string>();
if (tmp.parseHex(hash))
{
config->START_UP = Config::REPLAY_TRAP;
config->TRAP_TX_HASH = tmp;
}
else
{
std::cerr << "Trap parameter was ill-formed, expected "
"valid transaction hash but received: "
<< hash << std::endl;
return -1;
}
}
else
config->START_UP = Config::REPLAY;
}
else
config->START_UP = Config::LOAD;
}
Expand All @@ -693,10 +716,18 @@ run(int argc, char** argv)
config->START_UP = Config::LOAD;
}

if (vm.count("trap_tx_hash") && vm.count("replay") == 0)
{
std::cerr << "Cannot use trap option without replay option"
<< std::endl;
return -1;
}

if (vm.count("net") && !config->FAST_LOAD)
{
if ((config->START_UP == Config::LOAD) ||
(config->START_UP == Config::REPLAY))
(config->START_UP == Config::REPLAY) ||
(config->START_UP == Config::REPLAY_TRAP))
{
std::cerr << "Net and load/replay options are incompatible"
<< std::endl;
Expand Down
6 changes: 4 additions & 2 deletions src/ripple/app/rdb/backend/detail/impl/Node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,11 @@ makeLedgerDBs(
boost::format("PRAGMA cache_size=-%d;") %
kilobytes(config.getValueFor(SizedItem::txnDBCache)));

if (!setup.standAlone || setup.startUp == Config::LOAD ||
if (!setup.standAlone || //
setup.startUp == Config::LOAD ||
setup.startUp == Config::LOAD_FILE ||
setup.startUp == Config::REPLAY)
setup.startUp == Config::REPLAY ||
setup.startUp == Config::REPLAY_TRAP)
{
// Check if AccountTransactions has primary key
std::string cid, name, type;
Expand Down
6 changes: 6 additions & 0 deletions src/ripple/app/tx/impl/Transactor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,12 @@ Transactor::operator()()
}
#endif

if (auto trap = ctx_.app.trapTxID();
trap && ctx_.tx.getTransactionID() == *trap)
{
JLOG(j_.debug()) << "Transaction trapped: " << *trap;
}

auto result = ctx_.preclaimResult;
if (result == tesSUCCESS)
result = apply();
Expand Down
12 changes: 11 additions & 1 deletion src/ripple/core/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,23 @@ class Config : public BasicConfig
// Entries from [ips_fixed] config stanza
std::vector<std::string> IPS_FIXED;

enum StartUpType { FRESH, NORMAL, LOAD, LOAD_FILE, REPLAY, NETWORK };
enum StartUpType {
FRESH,
NORMAL,
LOAD,
LOAD_FILE,
REPLAY,
NETWORK,
REPLAY_TRAP
};
StartUpType START_UP = NORMAL;

bool START_VALID = false;

std::string START_LEDGER;

uint256 TRAP_TX_HASH = {};

// Network parameters
uint32_t NETWORK_ID = 0;

Expand Down
6 changes: 4 additions & 2 deletions src/ripple/core/DatabaseCon.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,12 @@ class DatabaseCon
std::array<char const*, M> const& initSQL)
// Use temporary files or regular DB files?
: DatabaseCon(
setup.standAlone && !setup.reporting &&
setup.standAlone && //
!setup.reporting && //
setup.startUp != Config::LOAD &&
setup.startUp != Config::LOAD_FILE &&
setup.startUp != Config::REPLAY
setup.startUp != Config::REPLAY &&
setup.startUp != Config::REPLAY_TRAP
? ""
: (setup.dataDir / dbName),
setup.commonPragma(),
Expand Down

0 comments on commit 297bc96

Please sign in to comment.