Skip to content

Commit 89eb962

Browse files
fix: CTID issue (#2001)
fixes #1998
1 parent 4a5fee7 commit 89eb962

File tree

8 files changed

+35
-30
lines changed

8 files changed

+35
-30
lines changed

src/etl/ETLState.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ tag_invoke(boost::json::value_to_tag<ETLState>, boost::json::value const& jv)
4040
if (jsonObject.contains(JS(result)) && jsonObject.at(JS(result)).as_object().contains(JS(info))) {
4141
auto const rippledInfo = jsonObject.at(JS(result)).as_object().at(JS(info)).as_object();
4242
if (rippledInfo.contains(JS(network_id)))
43-
state.networkID.emplace(boost::json::value_to<int64_t>(rippledInfo.at(JS(network_id))));
43+
state.networkID = boost::json::value_to<int64_t>(rippledInfo.at(JS(network_id)));
4444
}
4545

4646
return state;

src/etl/ETLState.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,12 @@ namespace etl {
3838
* @brief This class is responsible for fetching and storing the state of the ETL information, such as the network id
3939
*/
4040
struct ETLState {
41-
std::optional<uint32_t> networkID;
41+
/*
42+
* NOTE: Rippled NetworkID: Mainnet = 0; Testnet = 1; Devnet = 2
43+
* However, if rippled is running on neither of these (ie. standalone mode) rippled will default to 0, but
44+
* is not included in the stateOpt response. Must manually add it here.
45+
*/
46+
uint32_t networkID{0};
4247

4348
/**
4449
* @brief Fetch the ETL state from the rippled server

src/etl/LoadBalancer.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,11 @@ LoadBalancer::LoadBalancer(
142142
if (!stateOpt) {
143143
LOG(log_.warn()) << "Failed to fetch ETL state from source = " << source->toString()
144144
<< " Please check the configuration and network";
145-
} else if (etlState_ && etlState_->networkID && stateOpt->networkID &&
146-
etlState_->networkID != stateOpt->networkID) {
145+
} else if (etlState_ && etlState_->networkID != stateOpt->networkID) {
147146
checkOnETLFailure(fmt::format(
148147
"ETL sources must be on the same network. Source network id = {} does not match others network id = {}",
149-
*(stateOpt->networkID),
150-
*(etlState_->networkID)
148+
stateOpt->networkID,
149+
etlState_->networkID
151150
));
152151
} else {
153152
etlState_ = stateOpt;

src/etlng/LoadBalancer.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,11 @@ LoadBalancer::LoadBalancer(
142142
if (!stateOpt) {
143143
LOG(log_.warn()) << "Failed to fetch ETL state from source = " << source->toString()
144144
<< " Please check the configuration and network";
145-
} else if (etlState_ && etlState_->networkID && stateOpt->networkID &&
146-
etlState_->networkID != stateOpt->networkID) {
145+
} else if (etlState_ && etlState_->networkID != stateOpt->networkID) {
147146
checkOnETLFailure(fmt::format(
148147
"ETL sources must be on the same network. Source network id = {} does not match others network id = {}",
149-
*(stateOpt->networkID),
150-
*(etlState_->networkID)
148+
stateOpt->networkID,
149+
etlState_->networkID
151150
));
152151
} else {
153152
etlState_ = stateOpt;

src/rpc/handlers/Tx.hpp

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
#include "data/BackendInterface.hpp"
2323
#include "data/Types.hpp"
24-
#include "etl/ETLService.hpp"
2524
#include "etlng/ETLServiceInterface.hpp"
2625
#include "rpc/Errors.hpp"
2726
#include "rpc/JS.hpp"
@@ -39,6 +38,7 @@
3938
#include <boost/json/value.hpp>
4039
#include <boost/json/value_to.hpp>
4140
#include <xrpl/basics/base_uint.h>
41+
#include <xrpl/basics/chrono.h>
4242
#include <xrpl/basics/strHex.h>
4343
#include <xrpl/protocol/ErrorCodes.h>
4444
#include <xrpl/protocol/LedgerHeader.h>
@@ -214,17 +214,15 @@ class TxHandler {
214214
// input.transaction might be not available, get hash via tx object
215215
if (txn.contains(JS(hash)))
216216
output.hash = txn.at(JS(hash)).as_string();
217+
}
217218

218-
// append ctid here to mimic rippled 1.12 behavior: return ctid even binary=true
219-
// rippled will change it in the future, ctid should be part of tx json which not available in binary
220-
// mode
221-
auto const txnIdx = boost::json::value_to<uint64_t>(meta.at("TransactionIndex"));
222-
if (txnIdx <= 0xFFFFU && dbResponse->ledgerSequence < 0x0FFF'FFFFUL && currentNetId &&
223-
*currentNetId <= 0xFFFFU) {
224-
output.ctid = rpc::encodeCTID(
225-
dbResponse->ledgerSequence, static_cast<uint16_t>(txnIdx), static_cast<uint16_t>(*currentNetId)
226-
);
227-
}
219+
// append ctid here to mimic rippled behavior
220+
auto const txnIdx = boost::json::value_to<uint64_t>(meta.at("TransactionIndex"));
221+
if (txnIdx <= 0xFFFFU && dbResponse->ledgerSequence < 0x0FFF'FFFFUL && currentNetId &&
222+
*currentNetId <= 0xFFFFU) {
223+
output.ctid = rpc::encodeCTID(
224+
dbResponse->ledgerSequence, static_cast<uint16_t>(txnIdx), static_cast<uint16_t>(*currentNetId)
225+
);
228226
}
229227

230228
output.date = dbResponse->date;
@@ -281,12 +279,10 @@ class TxHandler {
281279
if (output.tx) {
282280
obj[JS(tx_json)] = *output.tx;
283281
obj[JS(tx_json)].as_object()[JS(date)] = output.date;
282+
if (output.ctid)
283+
obj[JS(tx_json)].as_object()[JS(ctid)] = *output.ctid;
284+
284285
obj[JS(tx_json)].as_object()[JS(ledger_index)] = output.ledgerIndex;
285-
// move ctid from tx_json to root
286-
if (obj[JS(tx_json)].as_object().contains(JS(ctid))) {
287-
obj[JS(ctid)] = obj[JS(tx_json)].as_object()[JS(ctid)];
288-
obj[JS(tx_json)].as_object().erase(JS(ctid));
289-
}
290286
// move hash from tx_json to root
291287
if (obj[JS(tx_json)].as_object().contains(JS(hash))) {
292288
obj[JS(hash)] = obj[JS(tx_json)].as_object()[JS(hash)];

tests/unit/etl/ETLStateTests.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ TEST_F(ETLStateTest, NetworkIdValid)
5757
EXPECT_CALL(source, forwardToRippled).WillOnce(Return(json.as_object()));
5858
auto const state = etl::ETLState::fetchETLStateFromSource(source);
5959
ASSERT_TRUE(state.has_value());
60-
ASSERT_TRUE(state->networkID.has_value());
61-
EXPECT_EQ(state->networkID.value(), 12);
60+
EXPECT_EQ(state->networkID, 12);
6261
}
6362

6463
TEST_F(ETLStateTest, NetworkIdInvalid)
@@ -75,7 +74,7 @@ TEST_F(ETLStateTest, NetworkIdInvalid)
7574
EXPECT_CALL(source, forwardToRippled).WillOnce(Return(json.as_object()));
7675
auto const state = etl::ETLState::fetchETLStateFromSource(source);
7776
ASSERT_TRUE(state.has_value());
78-
EXPECT_FALSE(state->networkID.has_value());
77+
EXPECT_NE(state->networkID, 12);
7978
}
8079

8180
TEST_F(ETLStateTest, ResponseHasError)

tests/unit/rpc/ErrorTests.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ TEST(RPCErrorsTest, StatusAsBool)
6767
RippledError::rpcUNKNOWN_COMMAND,
6868
RippledError::rpcTOO_BUSY,
6969
RippledError::rpcNO_NETWORK,
70+
RippledError::rpcWRONG_NETWORK,
7071
RippledError::rpcACT_MALFORMED,
7172
RippledError::rpcBAD_MARKET,
7273
ClioError::RpcMalformedCurrency,

tests/unit/rpc/handlers/TxTests.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ constexpr auto kDEFAULT_OUT1 = R"({
7171
"TakerPays": "300",
7272
"TransactionType": "OfferCreate",
7373
"hash": "2E2FBAAFF767227FE4381C4BE9855986A6B9F96C62F6E443731AB36F7BBB8A08",
74+
"ctid": "C000006400640000",
7475
"meta": {
7576
"AffectedNodes": [
7677
{
@@ -119,8 +120,10 @@ constexpr auto kDEFAULT_OUT2 = R"({
119120
"TransactionIndex": 100,
120121
"TransactionResult": "tesSUCCESS"
121122
},
123+
"ctid": "C000006400640000",
122124
"tx_json": {
123125
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
126+
"ctid": "C000006400640000",
124127
"date": 123456,
125128
"Fee": "2",
126129
"ledger_index": 100,
@@ -492,7 +495,8 @@ TEST_F(RPCTxTest, ReturnBinary)
492495
"date": 123456,
493496
"ledger_index": 100,
494497
"inLedger": 100,
495-
"validated": true
498+
"validated": true,
499+
"ctid": "C000006400640000"
496500
})";
497501

498502
TransactionAndMetadata tx;
@@ -578,6 +582,7 @@ TEST_F(RPCTxTest, MintNFT)
578582
"SigningPubKey": "74657374",
579583
"TransactionType": "NFTokenMint",
580584
"hash": "C74463F49CFDCBEF3E9902672719918CDE5042DC7E7660BEBD1D1105C4B6DFF4",
585+
"ctid": "C000006400000000",
581586
"meta": {{
582587
"AffectedNodes": [
583588
{{
@@ -829,6 +834,7 @@ TEST_F(RPCTxTest, CTIDNotMatch)
829834
ASSERT_FALSE(output);
830835

831836
auto const err = rpc::makeError(output.result.error());
837+
// TODO: https://github.com/XRPLF/clio/issues/2002
832838
EXPECT_EQ(err.at("error_code").as_uint64(), 4);
833839
EXPECT_EQ(
834840
err.at("error_message").as_string(),

0 commit comments

Comments
 (0)