mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-04 10:45:50 +00:00
Augment "submit" command response:
If merged, this commit will report additional information in the response to the submit command; this will make it easier for developers to accurately track the status of transaction submission. Fixes #2851
This commit is contained in:
@@ -1070,9 +1070,15 @@ void NetworkOPsImp::apply (std::unique_lock<std::mutex>& batchLock)
|
||||
if (changed)
|
||||
reportFeeChange();
|
||||
|
||||
boost::optional<LedgerIndex> validatedLedgerIndex;
|
||||
if (auto const l = m_ledgerMaster.getValidatedLedger())
|
||||
validatedLedgerIndex = l->info().seq;
|
||||
|
||||
auto newOL = app_.openLedger().current();
|
||||
for (TransactionStatus& e : transactions)
|
||||
{
|
||||
e.transaction->clearSubmitResult();
|
||||
|
||||
if (e.applied)
|
||||
{
|
||||
pubProposedTransaction (newOL,
|
||||
@@ -1117,6 +1123,7 @@ void NetworkOPsImp::apply (std::unique_lock<std::mutex>& batchLock)
|
||||
t, false, false, FailHard::no);
|
||||
t->setApplying();
|
||||
}
|
||||
e.transaction->setApplied();
|
||||
}
|
||||
else if (e.result == tefPAST_SEQ)
|
||||
{
|
||||
@@ -1133,6 +1140,8 @@ void NetworkOPsImp::apply (std::unique_lock<std::mutex>& batchLock)
|
||||
// kicked out of the queue, and this will try to
|
||||
// put it back.
|
||||
m_ledgerMaster.addHeldTransaction(e.transaction);
|
||||
e.transaction->setQueued();
|
||||
e.transaction->setKept();
|
||||
}
|
||||
else if (isTerRetry (e.result))
|
||||
{
|
||||
@@ -1147,6 +1156,7 @@ void NetworkOPsImp::apply (std::unique_lock<std::mutex>& batchLock)
|
||||
<< "Transaction should be held: " << e.result;
|
||||
e.transaction->setStatus (HELD);
|
||||
m_ledgerMaster.addHeldTransaction (e.transaction);
|
||||
e.transaction->setKept();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1161,6 +1171,7 @@ void NetworkOPsImp::apply (std::unique_lock<std::mutex>& batchLock)
|
||||
m_localTX->push_back (
|
||||
m_ledgerMaster.getCurrentLedgerIndex(),
|
||||
e.transaction->getSTransaction());
|
||||
e.transaction->setKept();
|
||||
}
|
||||
|
||||
if (e.applied || ((mMode != OperatingMode::FULL) &&
|
||||
@@ -1184,8 +1195,18 @@ void NetworkOPsImp::apply (std::unique_lock<std::mutex>& batchLock)
|
||||
app_.overlay().foreach (send_if_not (
|
||||
std::make_shared<Message> (tx, protocol::mtTRANSACTION),
|
||||
peer_in_set(*toSkip)));
|
||||
e.transaction->setBroadcast();
|
||||
}
|
||||
}
|
||||
|
||||
if (validatedLedgerIndex)
|
||||
{
|
||||
auto [fee, accountSeq, availableSeq] =
|
||||
app_.getTxQ().getTxRequiredFeeAndSeq(
|
||||
*newOL, e.transaction->getSTransaction());
|
||||
e.transaction->setCurrentLedgerState(
|
||||
*validatedLedgerIndex, fee, accountSeq, availableSeq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,6 +148,133 @@ public:
|
||||
mApplying = false;
|
||||
}
|
||||
|
||||
struct SubmitResult
|
||||
{
|
||||
/**
|
||||
* @brief clear Clear all states
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
applied = false;
|
||||
broadcast = false;
|
||||
queued = false;
|
||||
kept = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief any Get true of any state is true
|
||||
* @return True if any state if true
|
||||
*/
|
||||
bool any() const
|
||||
{
|
||||
return applied || broadcast || queued || kept;
|
||||
}
|
||||
|
||||
bool applied = false;
|
||||
bool broadcast = false;
|
||||
bool queued = false;
|
||||
bool kept = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief getSubmitResult Return submit result
|
||||
* @return SubmitResult struct
|
||||
*/
|
||||
SubmitResult getSubmitResult() const
|
||||
{
|
||||
return submitResult_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief clearSubmitResult Clear all flags in SubmitResult
|
||||
*/
|
||||
void clearSubmitResult()
|
||||
{
|
||||
submitResult_.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief setApplied Set this flag once was applied to open ledger
|
||||
*/
|
||||
void setApplied()
|
||||
{
|
||||
submitResult_.applied = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief setQueued Set this flag once was put into heldtxns queue
|
||||
*/
|
||||
void setQueued()
|
||||
{
|
||||
submitResult_.queued = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief setBroadcast Set this flag once was broadcasted via network
|
||||
*/
|
||||
void setBroadcast()
|
||||
{
|
||||
submitResult_.broadcast = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief setKept Set this flag once was put to localtxns queue
|
||||
*/
|
||||
void setKept()
|
||||
{
|
||||
submitResult_.kept = true;
|
||||
}
|
||||
|
||||
struct CurrentLedgerState
|
||||
{
|
||||
CurrentLedgerState() = delete;
|
||||
|
||||
CurrentLedgerState(
|
||||
LedgerIndex li,
|
||||
XRPAmount fee,
|
||||
std::uint32_t accSeqNext,
|
||||
std::uint32_t accSeqAvail)
|
||||
: validatedLedger{li}
|
||||
, minFeeRequired{fee}
|
||||
, accountSeqNext{accSeqNext}
|
||||
, accountSeqAvail{accSeqAvail}
|
||||
{
|
||||
}
|
||||
|
||||
LedgerIndex validatedLedger;
|
||||
XRPAmount minFeeRequired;
|
||||
std::uint32_t accountSeqNext;
|
||||
std::uint32_t accountSeqAvail;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief getCurrentLedgerState Get current ledger state of transaction
|
||||
* @return Current ledger state
|
||||
*/
|
||||
boost::optional<CurrentLedgerState>
|
||||
getCurrentLedgerState() const
|
||||
{
|
||||
return currentLedgerState_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief setCurrentLedgerState Set current ledger state of transaction
|
||||
* @param validatedLedger Number of last validated ledger
|
||||
* @param fee minimum Fee required for the transaction
|
||||
* @param accountSeq First valid account sequence in current ledger
|
||||
* @param availableSeq First available sequence for the transaction
|
||||
*/
|
||||
void
|
||||
setCurrentLedgerState(
|
||||
LedgerIndex validatedLedger,
|
||||
XRPAmount fee,
|
||||
std::uint32_t accountSeq,
|
||||
std::uint32_t availableSeq)
|
||||
{
|
||||
currentLedgerState_.emplace(
|
||||
validatedLedger, fee, accountSeq, availableSeq);
|
||||
}
|
||||
|
||||
Json::Value getJson (JsonOptions options, bool binary = false) const;
|
||||
|
||||
static pointer
|
||||
@@ -169,6 +296,11 @@ private:
|
||||
TER mResult = temUNCERTAIN;
|
||||
bool mApplying = false;
|
||||
|
||||
/** different ways for transaction to be accepted */
|
||||
SubmitResult submitResult_;
|
||||
|
||||
boost::optional<CurrentLedgerState> currentLedgerState_;
|
||||
|
||||
std::shared_ptr<STTx const> mTransaction;
|
||||
Application& mApp;
|
||||
beast::Journal j_;
|
||||
|
||||
@@ -319,6 +319,26 @@ public:
|
||||
Metrics
|
||||
getMetrics(OpenView const& view) const;
|
||||
|
||||
struct FeeAndSeq
|
||||
{
|
||||
XRPAmount fee;
|
||||
std::uint32_t accountSeq;
|
||||
std::uint32_t availableSeq;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Returns minimum required fee for tx and two sequences:
|
||||
* first vaild sequence for this account in current ledger
|
||||
* and first available sequence for transaction
|
||||
* @param view current open ledger
|
||||
* @param tx the transaction
|
||||
* @return minimum required fee, first sequence in the ledger
|
||||
* and first available sequence
|
||||
*/
|
||||
FeeAndSeq
|
||||
getTxRequiredFeeAndSeq(OpenView const& view,
|
||||
std::shared_ptr<STTx const> const& tx) const;
|
||||
|
||||
/** Returns information about the transactions currently
|
||||
in the queue for the account.
|
||||
|
||||
|
||||
@@ -1393,6 +1393,41 @@ TxQ::getMetrics(OpenView const& view) const
|
||||
return result;
|
||||
}
|
||||
|
||||
TxQ::FeeAndSeq
|
||||
TxQ::getTxRequiredFeeAndSeq(OpenView const& view,
|
||||
std::shared_ptr<STTx const> const& tx) const
|
||||
{
|
||||
auto const account = (*tx)[sfAccount];
|
||||
|
||||
std::lock_guard lock(mutex_);
|
||||
|
||||
auto const snapshot = feeMetrics_.getSnapshot();
|
||||
auto const baseFee = calculateBaseFee(view, *tx);
|
||||
auto const fee = FeeMetrics::scaleFeeLevel(snapshot, view);
|
||||
|
||||
auto const accountSeq = [&view, &account]() -> std::uint32_t {
|
||||
auto const sle = view.read(keylet::account(account));
|
||||
if (sle)
|
||||
return (*sle)[sfSequence];
|
||||
return 0;
|
||||
}();
|
||||
|
||||
auto availableSeq = accountSeq;
|
||||
|
||||
if (auto iter {byAccount_.find(account)}; iter != byAccount_.end())
|
||||
{
|
||||
auto& txQAcct = iter->second;
|
||||
for (auto const& [seq, _] : txQAcct.transactions)
|
||||
{
|
||||
(void)_;
|
||||
if (seq >= availableSeq)
|
||||
availableSeq = seq + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return {fee * baseFee / baseLevel, accountSeq, availableSeq};
|
||||
}
|
||||
|
||||
auto
|
||||
TxQ::getAccountTxs(AccountID const& account, ReadView const& view) const
|
||||
-> std::map<TxSeq, AccountTxDetails const>
|
||||
|
||||
@@ -100,7 +100,7 @@ JSS ( TransactionType ); // in: TransactionSign.
|
||||
JSS ( TransferRate ); // in: TransferRate.
|
||||
JSS ( TrustSet ); // transaction type.
|
||||
JSS ( aborted ); // out: InboundLedger
|
||||
JSS ( accepted ); // out: LedgerToJson, OwnerInfo
|
||||
JSS ( accepted ); // out: LedgerToJson, OwnerInfo, SubmitTransaction
|
||||
JSS ( account ); // in/out: many
|
||||
JSS ( accountState ); // out: LedgerToJson
|
||||
JSS ( accountTreeHash ); // out: ledger/Ledger.cpp
|
||||
@@ -109,6 +109,8 @@ JSS ( account_hash ); // out: LedgerToJson
|
||||
JSS ( account_id ); // out: WalletPropose
|
||||
JSS ( account_objects ); // out: AccountObjects
|
||||
JSS ( account_root ); // in: LedgerEntry
|
||||
JSS ( account_sequence_next ); // out: SubmitTransaction
|
||||
JSS ( account_sequence_available ); // out: SubmitTransaction
|
||||
JSS ( accounts ); // in: LedgerEntry, Subscribe,
|
||||
// handlers/Ledger, Unsubscribe
|
||||
JSS ( accounts_proposed ); // in: Subscribe, Unsubscribe
|
||||
@@ -121,6 +123,7 @@ JSS ( alternatives ); // out: PathRequest, RipplePathFind
|
||||
JSS ( amendment_blocked ); // out: NetworkOPs
|
||||
JSS ( amendments ); // in: AccountObjects, out: NetworkOPs
|
||||
JSS ( amount ); // out: AccountChannels
|
||||
JSS ( applied ); // out: SubmitTransaction
|
||||
JSS ( asks ); // out: Subscribe
|
||||
JSS ( assets ); // out: GatewayBalances
|
||||
JSS ( authorized ); // out: AccountLines
|
||||
@@ -140,6 +143,7 @@ JSS ( binary ); // in: AccountTX, LedgerEntry,
|
||||
JSS ( books ); // in: Subscribe, Unsubscribe
|
||||
JSS ( both ); // in: Subscribe, Unsubscribe
|
||||
JSS ( both_sides ); // in: Subscribe, Unsubscribe
|
||||
JSS ( broadcast ); // out: SubmitTransaction
|
||||
JSS ( build_path ); // in: TransactionSign
|
||||
JSS ( build_version ); // out: NetworkOPs
|
||||
JSS ( cancel_after ); // out: AccountChannels
|
||||
@@ -271,6 +275,7 @@ JSS ( job_queue );
|
||||
JSS ( jobs );
|
||||
JSS ( jsonrpc ); // json version
|
||||
JSS ( jq_trans_overflow ); // JobQueue transaction limit overflow.
|
||||
JSS ( kept ); // out: SubmitTransaction
|
||||
JSS ( key ); // out
|
||||
JSS ( key_type ); // in/out: WalletPropose, TransactionSign
|
||||
JSS ( latency ); // out: PeerImp
|
||||
@@ -371,6 +376,7 @@ JSS ( offers ); // out: NetworkOPs, AccountOffers, Subscribe
|
||||
JSS ( offline ); // in: TransactionSign
|
||||
JSS ( offset ); // in/out: AccountTxOld
|
||||
JSS ( open ); // out: handlers/Ledger
|
||||
JSS ( open_ledger_cost ); // out: SubmitTransaction
|
||||
JSS ( open_ledger_fee ); // out: TxQ
|
||||
JSS ( open_ledger_level ); // out: TxQ
|
||||
JSS ( owner ); // in: LedgerEntry, out: NetworkOPs
|
||||
@@ -412,7 +418,7 @@ JSS ( quality_in ); // out: AccountLines
|
||||
JSS ( quality_out ); // out: AccountLines
|
||||
JSS ( queue ); // in: AccountInfo
|
||||
JSS ( queue_data ); // out: AccountInfo
|
||||
JSS ( queued );
|
||||
JSS ( queued ); // out: SubmitTransaction
|
||||
JSS ( queued_duration_us );
|
||||
JSS ( random ); // out: Random
|
||||
JSS ( raw_meta ); // out: AcceptedLedgerTx
|
||||
@@ -540,6 +546,7 @@ JSS ( validator_list_expires ); // out: NetworkOps, ValidatorList
|
||||
JSS ( validator_list ); // out: NetworkOps, ValidatorList
|
||||
JSS ( validators );
|
||||
JSS ( validated_ledger ); // out: NetworkOPs
|
||||
JSS ( validated_ledger_index ); // out: SubmitTransaction
|
||||
JSS ( validated_ledgers ); // out: NetworkOPs
|
||||
JSS ( validation_key ); // out: ValidationCreate, ValidationSeed
|
||||
JSS ( validation_private_key ); // out: ValidationCreate
|
||||
|
||||
@@ -148,6 +148,26 @@ Json::Value doSubmit (RPC::Context& context)
|
||||
jvResult[jss::engine_result] = sToken;
|
||||
jvResult[jss::engine_result_code] = tpTrans->getResult ();
|
||||
jvResult[jss::engine_result_message] = sHuman;
|
||||
|
||||
auto const submitResult = tpTrans->getSubmitResult();
|
||||
|
||||
jvResult[jss::accepted] = submitResult.any();
|
||||
jvResult[jss::applied] = submitResult.applied;
|
||||
jvResult[jss::broadcast] = submitResult.broadcast;
|
||||
jvResult[jss::queued] = submitResult.queued;
|
||||
jvResult[jss::kept] = submitResult.kept;
|
||||
|
||||
if (auto currentLedgerState = tpTrans->getCurrentLedgerState())
|
||||
{
|
||||
jvResult[jss::account_sequence_next]
|
||||
= safe_cast<Json::Value::UInt>(currentLedgerState->accountSeqNext);
|
||||
jvResult[jss::account_sequence_available]
|
||||
= safe_cast<Json::Value::UInt>(currentLedgerState->accountSeqAvail);
|
||||
jvResult[jss::open_ledger_cost]
|
||||
= to_string(currentLedgerState->minFeeRequired);
|
||||
jvResult[jss::validated_ledger_index]
|
||||
= safe_cast<Json::Value::UInt>(currentLedgerState->validatedLedger);
|
||||
}
|
||||
}
|
||||
|
||||
return jvResult;
|
||||
|
||||
Reference in New Issue
Block a user