diff --git a/src/ripple/app/misc/TxQ.h b/src/ripple/app/misc/TxQ.h index ae35dd1f6..cccb4bd2a 100644 --- a/src/ripple/app/misc/TxQ.h +++ b/src/ripple/app/misc/TxQ.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace ripple { @@ -56,7 +57,14 @@ class Config; */ class TxQ { +private: + std::mutex debugTxInjectMutex; + std::vector debugTxInjectQueue; public: + + void + debugTxInject(STTx const& txn); + /// Fee level for single-signed reference transaction. static constexpr FeeLevel64 baseLevel{256}; diff --git a/src/ripple/app/misc/impl/TxQ.cpp b/src/ripple/app/misc/impl/TxQ.cpp index 08157c292..c49716fd7 100644 --- a/src/ripple/app/misc/impl/TxQ.cpp +++ b/src/ripple/app/misc/impl/TxQ.cpp @@ -93,6 +93,14 @@ increase(FeeLevel64 level, std::uint32_t increasePercent) ////////////////////////////////////////////////////////////////////////// +void +TxQ::debugTxInject(STTx const& txn) +{ + const std::lock_guard _(debugTxInjectMutex); + debugTxInjectQueue.push_back(txn); +} + + std::size_t TxQ::FeeMetrics::update( Application& app, @@ -1444,6 +1452,35 @@ TxQ::accept(Application& app, OpenView& view) auto const metricsSnapshot = feeMetrics_.getSnapshot(); + // try to inject any debug txns waiting in the debug queue + { + std::unique_lock trylock (TxQ::debugTxInjectMutex, std::try_to_lock); + if(trylock.owns_lock() && !debugTxInjectQueue.empty()) + { + // pop everything + for (STTx const& txn : debugTxInjectQueue) + { + auto txnHash = txn.getTransactionID(); + app.getHashRouter().setFlags(txnHash, SF_EMITTED | SF_PRIVATE2); + + auto const& emitted = + const_cast(txn) + .downcast(); + + auto s = std::make_shared(); + emitted.add(*s); + + view.rawTxInsert( + txnHash, + std::move(s), + nullptr); + ledgerChanged = true; + } + + debugTxInjectQueue.clear(); + } + } + // Inject emitted transactions if any if (view.rules().enabled(featureHooks)) do diff --git a/src/ripple/protocol/jss.h b/src/ripple/protocol/jss.h index 699928f7e..dd853203b 100644 --- a/src/ripple/protocol/jss.h +++ b/src/ripple/protocol/jss.h @@ -353,6 +353,7 @@ JSS(ident); // in: AccountCurrencies, AccountInfo, // OwnerInfo JSS(ignore_default); // in: AccountLines JSS(inLedger); // out: tx/Transaction +JSS(in_queue); JSS(inbound); // out: PeerImp JSS(index); // in: LedgerEntry, DownloadShard // out: STLedgerEntry, diff --git a/src/ripple/rpc/handlers/Handlers.h b/src/ripple/rpc/handlers/Handlers.h index bb7c6d581..739c069f3 100644 --- a/src/ripple/rpc/handlers/Handlers.h +++ b/src/ripple/rpc/handlers/Handlers.h @@ -141,6 +141,8 @@ doCrawlShards(RPC::JsonContext&); Json::Value doStop(RPC::JsonContext&); Json::Value +doInject(RPC::JsonContext&); +Json::Value doSubmit(RPC::JsonContext&); Json::Value doSubmitMultiSigned(RPC::JsonContext&); diff --git a/src/ripple/rpc/handlers/Submit.cpp b/src/ripple/rpc/handlers/Submit.cpp index 2b5c8bba9..d3f4b329f 100644 --- a/src/ripple/rpc/handlers/Submit.cpp +++ b/src/ripple/rpc/handlers/Submit.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,51 @@ getFailHard(RPC::JsonContext const& context) context.params["fail_hard"].asBool()); } + +// { +// tx_blob: serialized tx +// } +// Only for debug use!!!! +Json::Value +doInject(RPC::JsonContext& context) +{ + if (!context.params.isMember(jss::tx_blob)) + return RPC::make_error( + rpcINVALID_PARAMS, "Need tx_blob"); + + Json::Value jvResult; + + auto ret = strUnHex(context.params[jss::tx_blob].asString()); + + if (!ret || !ret->size()) + return rpcError(rpcINVALID_PARAMS); + + SerialIter sitTrans(makeSlice(*ret)); + + std::shared_ptr stpTrans; + + try + { + stpTrans = std::make_shared(std::ref(sitTrans)); + } + catch (std::exception& e) + { + jvResult[jss::error] = "invalidTransaction"; + jvResult[jss::error_exception] = e.what(); + jvResult[jss::in_queue] = false; + + return jvResult; + } + + context.app.getTxQ().debugTxInject(*stpTrans); + + + jvResult[jss::tx_json] = stpTrans->getJson(JsonOptions::none); + jvResult[jss::in_queue] = true; + + return jvResult; +} + // { // tx_json: , // secret: diff --git a/src/ripple/rpc/impl/Handler.cpp b/src/ripple/rpc/impl/Handler.cpp index 9b06e9c46..473ecd769 100644 --- a/src/ripple/rpc/impl/Handler.cpp +++ b/src/ripple/rpc/impl/Handler.cpp @@ -141,6 +141,7 @@ Handler const handlerArray[]{ {"ripple_path_find", byRef(&doRipplePathFind), Role::USER, NO_CONDITION}, {"sign", byRef(&doSign), Role::USER, NO_CONDITION}, {"sign_for", byRef(&doSignFor), Role::USER, NO_CONDITION}, + {"inject", byRef(&doInject), Role::USER, NEEDS_CURRENT_LEDGER}, {"submit", byRef(&doSubmit), Role::USER, NEEDS_CURRENT_LEDGER}, {"submit_multisigned", byRef(&doSubmitMultiSigned),