Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new command line option to make replaying transactions easier #5027

Merged
merged 8 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 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>
Bronek marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -1404,7 +1415,8 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline)
if (!loadOldLedger(
config_->START_LEDGER,
startUp == Config::REPLAY,
startUp == Config::LOAD_FILE))
startUp == Config::LOAD_FILE,
config_->TRAP_TX_HASH))
{
JLOG(m_journal.error())
<< "The specified ledger could not be loaded.";
Expand Down Expand Up @@ -2086,7 +2098,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 +2246,11 @@ ApplicationImp::loadOldLedger(
{
(void)_;
auto txID = tx->getTransactionID();
if (trapTxID && *trapTxID == txID)
Bronek marked this conversation as resolved.
Show resolved Hide resolved
{
trapTxID_ = txID;
JLOG(m_journal.debug()) << "Trap transaction set: " << txID;
}

auto s = std::make_shared<Serializer>();
tx->add(*s);
Expand All @@ -2247,6 +2265,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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we return false in this case or just log? The semantics of this call is to return false if the ledger fails to load.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's intentional - you only use this functionality when replaying a transaction, and failing a little earlier (still need several minutes to load that ledger) will save your time.

}
}
}
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
28 changes: 28 additions & 0 deletions src/ripple/app/main/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,9 @@
"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,25 @@
{
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 = {};

Check warning on line 689 in src/ripple/app/main/Main.cpp

View check run for this annotation

Codecov / codecov/patch

src/ripple/app/main/Main.cpp#L689

Added line #L689 was not covered by tests
auto hash = vm["trap_tx_hash"].as<std::string>();
if (tmp.parseHex(hash))
{
config->TRAP_TX_HASH = tmp;

Check warning on line 693 in src/ripple/app/main/Main.cpp

View check run for this annotation

Codecov / codecov/patch

src/ripple/app/main/Main.cpp#L693

Added line #L693 was not covered by tests
}
else
{
std::cerr << "Trap parameter was ill-formed, expected "
"valid transaction hash but received: "
<< hash << std::endl;
return -1;

Check warning on line 700 in src/ripple/app/main/Main.cpp

View check run for this annotation

Codecov / codecov/patch

src/ripple/app/main/Main.cpp#L700

Added line #L700 was not covered by tests
}
}
}
else
config->START_UP = Config::LOAD;
}
Expand All @@ -693,6 +714,13 @@
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;

Check warning on line 721 in src/ripple/app/main/Main.cpp

View check run for this annotation

Codecov / codecov/patch

src/ripple/app/main/Main.cpp#L721

Added line #L721 was not covered by tests
}

if (vm.count("net") && !config->FAST_LOAD)
{
if ((config->START_UP == Config::LOAD) ||
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;
}
Bronek marked this conversation as resolved.
Show resolved Hide resolved

auto result = ctx_.preclaimResult;
if (result == tesSUCCESS)
result = apply();
Expand Down
2 changes: 2 additions & 0 deletions src/ripple/core/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ class Config : public BasicConfig

std::string START_LEDGER;

std::optional<uint256> TRAP_TX_HASH = {};
Bronek marked this conversation as resolved.
Show resolved Hide resolved

// Network parameters
uint32_t NETWORK_ID = 0;

Expand Down
Loading
Loading