Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions src/rpc/RPCHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ toExpandedJson(
data::TransactionAndMetadata const& blobs,
std::uint32_t const apiVersion,
NFTokenjson nftEnabled,
std::optional<uint16_t> networkId
std::optional<uint32_t> networkId
)
{
auto [txn, meta] = deserializeTxPlusMeta(blobs, blobs.ledgerSequence);
Expand Down Expand Up @@ -269,7 +269,7 @@ toExpandedJson(
}

std::optional<std::string>
encodeCTID(uint32_t ledgerSeq, uint16_t txnIndex, uint16_t networkId) noexcept
encodeCTID(uint32_t ledgerSeq, uint16_t txnIndex, uint32_t networkId) noexcept
{
static constexpr uint32_t kMaxLedgerSeq = 0x0FFF'FFFF;
static constexpr uint32_t kMaxTxnIndex = 0xFFFF;
Expand Down
4 changes: 2 additions & 2 deletions src/rpc/RPCHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ toExpandedJson(
data::TransactionAndMetadata const& blobs,
std::uint32_t apiVersion,
NFTokenjson nftEnabled = NFTokenjson::DISABLE,
std::optional<uint16_t> networkId = std::nullopt
std::optional<uint32_t> networkId = std::nullopt
);

/**
Expand Down Expand Up @@ -779,7 +779,7 @@ getNFTID(boost::json::object const& request);
* @return The encoded CTID or std::nullopt if the input is invalid
*/
std::optional<std::string>
encodeCTID(uint32_t ledgerSeq, uint16_t txnIndex, uint16_t networkId) noexcept;
encodeCTID(uint32_t ledgerSeq, uint16_t txnIndex, uint32_t networkId) noexcept;

/**
* @brief Decode the CTID from a string or a uint64_t
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/rpc/RPCHelpersTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,12 @@ TEST_F(RPCHelpersTest, EncodeCTID)
EXPECT_FALSE(encodeCTID(0x1FFFFFFF, 0x67, 0x89));
}

TEST_F(RPCHelpersTest, EncodeCTIDRejectsNetworkIdAbove16Bits)
{
uint32_t networkId = 0x10000;
EXPECT_FALSE(encodeCTID(0x1234, 0x67, networkId));
}

TEST_F(RPCHelpersTest, DecodeCTIDString)
{
auto const ctid = decodeCTID("C000123400670089");
Expand Down
32 changes: 32 additions & 0 deletions tests/unit/rpc/handlers/TxTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,38 @@ TEST_F(RPCTxTest, ReturnCTIDForTxInput)
});
}

TEST_F(RPCTxTest, OmitCTIDWhenNetworkIdExceeds16Bits)
{
TransactionAndMetadata tx;
tx.metadata =
createMetaDataForCreateOffer(kCurrency, kAccount, 100, 200, 300).getSerializer().peekData();
tx.transaction =
createCreateOfferTransactionObject(kAccount, 2, 100, kCurrency, kAccount2, 200, 300)
.getSerializer()
.peekData();
tx.ledgerSequence = 100;

EXPECT_CALL(*backend_, fetchTransaction(xrpl::uint256{kTxnId}, _)).WillOnce(Return(tx));
EXPECT_CALL(*backend_, fetchLedgerBySequence(tx.ledgerSequence, _))
.WillOnce(Return(std::nullopt));

auto const rawETLPtr = dynamic_cast<MockETLService*>(mockETLServicePtr_.get());
ASSERT_NE(rawETLPtr, nullptr);
EXPECT_CALL(*rawETLPtr, getETLState).WillOnce(Return(etl::ETLState{.networkID = 0x10000}));

runSpawn([this](auto yield) {
auto const handler = AnyHandler{TestTxHandler{backend_, mockETLServicePtr_}};
auto const req = boost::json::parse(
fmt::format(R"JSON({{"command": "tx", "transaction": "{}"}})JSON", kTxnId)
);
auto const output = handler.process(req, Context{.yield = yield, .apiVersion = 2u});
ASSERT_TRUE(output);
auto const& result = output.result->as_object();
EXPECT_FALSE(result.contains("ctid"));
EXPECT_FALSE(result.at("tx_json").as_object().contains("ctid"));
});
}

TEST_F(RPCTxTest, NotReturnCTIDIfETLNotAvailable)
{
static constexpr auto kOut = R"JSON({
Expand Down
Loading