Compare commits

...

1 Commits

Author SHA1 Message Date
vjkhannaripple
5f4da531e1 fix(rpc): standardize error codes in doTransactionEntry (RIPD-7750)
Replace 4 ad-hoc jvResult[jss::error] string assignments with
rpc::injectError() calls using registered error codes. Responses
now include numeric error_code and error_message fields consistent
with all other RPC handlers.

Mapping:
  "fieldNotFoundTransaction" → RpcInvalidParams (missing tx_hash)
  "notYetImplemented"        → RpcNotImpl       (current ledger)
  "malformedRequest"         → RpcInvalidParams (bad hex)
  "transactionNotFound"      → RpcTxnNotFound   (tx absent)

Add <xrpl/protocol/ErrorCodes.h> include. Remove stale XXX comments.
Update TransactionEntry_test to assert error_code numerically.

Closes: https://github.com/XRPLF/rippled/issues/6798
RIPD-7750

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-25 15:11:32 -04:00
2 changed files with 22 additions and 14 deletions

View File

@@ -36,9 +36,10 @@ class TransactionEntry_test : public beast::unit_test::Suite
})};
{
// no params
// no params — AC-1: missing tx_hash → invalidParams
auto const result = env.client().invoke("transaction_entry", {})[jss::result];
BEAST_EXPECT(result[jss::error] == "fieldNotFoundTransaction");
BEAST_EXPECT(result[jss::error] == "invalidParams");
BEAST_EXPECT(result[jss::error_code] == RpcInvalidParams);
BEAST_EXPECT(result[jss::status] == "error");
}
@@ -51,21 +52,25 @@ class TransactionEntry_test : public beast::unit_test::Suite
}
{
// AC-2: current ledger (no closed ledger) → notImpl
json::Value params{json::ValueType::Object};
params[jss::ledger] = "current";
params[jss::tx_hash] = "DEADBEEF";
auto const result = env.client().invoke("transaction_entry", params)[jss::result];
BEAST_EXPECT(result[jss::error] == "notYetImplemented");
BEAST_EXPECT(result[jss::error] == "notImpl");
BEAST_EXPECT(result[jss::error_code] == RpcNotImpl);
BEAST_EXPECT(result[jss::status] == "error");
}
{
// AC-3: tx_hash is not valid hex → invalidParams
json::Value params{json::ValueType::Object};
params[jss::ledger] = "closed";
params[jss::tx_hash] = "DEADBEEF";
auto const result = env.client().invoke("transaction_entry", params)[jss::result];
BEAST_EXPECT(!result[jss::ledger_hash].asString().empty());
BEAST_EXPECT(result[jss::error] == "malformedRequest");
BEAST_EXPECT(result[jss::error] == "invalidParams");
BEAST_EXPECT(result[jss::error_code] == RpcInvalidParams);
BEAST_EXPECT(result[jss::status] == "error");
}
@@ -126,8 +131,10 @@ class TransactionEntry_test : public beast::unit_test::Suite
{
// Valid structure, but transaction not found.
json::Value const result{env.rpc("transaction_entry", txHash, "closed")};
// AC-4: valid hex but tx not in ledger → txnNotFound
BEAST_EXPECT(!result[jss::result][jss::ledger_hash].asString().empty());
BEAST_EXPECT(result[jss::result][jss::error] == "transactionNotFound");
BEAST_EXPECT(result[jss::result][jss::error] == "txnNotFound");
BEAST_EXPECT(result[jss::result][jss::error_code] == RpcTxnNotFound);
BEAST_EXPECT(result[jss::result][jss::status] == "error");
}
}

View File

@@ -7,6 +7,7 @@
#include <xrpl/basics/chrono.h>
#include <xrpl/json/json_value.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/ErrorCodes.h>
#include <xrpl/protocol/jss.h>
#include <memory>
@@ -18,7 +19,7 @@ namespace xrpl {
// ledger_index : <ledger_index>
// }
//
// XXX In this case, not specify either ledger does not mean ledger current. It
// Note: not specifying either ledger does not mean ledger current — it
// means any ledger.
json::Value
doTransactionEntry(rpc::JsonContext& context)
@@ -31,30 +32,30 @@ doTransactionEntry(rpc::JsonContext& context)
if (!context.params.isMember(jss::tx_hash))
{
jvResult[jss::error] = "fieldNotFoundTransaction";
// AC-1: missing tx_hash parameter
rpc::injectError(RpcInvalidParams, jvResult);
}
else if (jvResult.get(jss::ledger_hash, json::ValueType::Null).isNull())
{
// We don't work on ledger current.
// XXX We don't support any transaction yet.
jvResult[jss::error] = "notYetImplemented";
// AC-2: no closed ledger specified
rpc::injectError(RpcNotImpl, jvResult);
}
else
{
uint256 uTransID;
// XXX Relying on trusted WSS client. Would be better to have a strict
// routine, returning success or failure.
if (!uTransID.parseHex(context.params[jss::tx_hash].asString()))
{
jvResult[jss::error] = "malformedRequest";
// AC-3: tx_hash is not valid hex
rpc::injectError(RpcInvalidParams, jvResult);
return jvResult;
}
auto [sttx, stobj] = lpLedger->txRead(uTransID);
if (!sttx)
{
jvResult[jss::error] = "transactionNotFound";
// AC-4: transaction not found in ledger
rpc::injectError(RpcTxnNotFound, jvResult);
}
else
{