Skip to content

Commit 34a9c10

Browse files
committed
rpc: add getorphantxs
Adds an rpc to obtain data about the transactions currently in the orphanage. Hidden and marked as experimental
1 parent f511ff3 commit 34a9c10

File tree

3 files changed

+105
-0
lines changed

3 files changed

+105
-0
lines changed

src/rpc/client.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
254254
{ "keypoolrefill", 0, "newsize" },
255255
{ "getrawmempool", 0, "verbose" },
256256
{ "getrawmempool", 1, "mempool_sequence" },
257+
{ "getorphantxs", 0, "verbosity" },
258+
{ "getorphantxs", 0, "verbose" },
257259
{ "estimatesmartfee", 0, "conf_target" },
258260
{ "estimaterawfee", 0, "conf_target" },
259261
{ "estimaterawfee", 1, "threshold" },

src/rpc/mempool.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
#include <node/mempool_persist.h>
99

1010
#include <chainparams.h>
11+
#include <consensus/validation.h>
1112
#include <core_io.h>
1213
#include <kernel/mempool_entry.h>
14+
#include <net_processing.h>
1315
#include <node/mempool_persist_args.h>
1416
#include <node/types.h>
1517
#include <policy/rbf.h>
@@ -24,6 +26,7 @@
2426
#include <util/moneystr.h>
2527
#include <util/strencodings.h>
2628
#include <util/time.h>
29+
#include <util/vector.h>
2730

2831
#include <utility>
2932

@@ -812,6 +815,104 @@ static RPCHelpMan savemempool()
812815
};
813816
}
814817

818+
static std::vector<RPCResult> OrphanDescription()
819+
{
820+
return {
821+
RPCResult{RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
822+
RPCResult{RPCResult::Type::STR_HEX, "wtxid", "The transaction witness hash in hex"},
823+
RPCResult{RPCResult::Type::NUM, "bytes", "The serialized transaction size in bytes"},
824+
RPCResult{RPCResult::Type::NUM, "vsize", "The virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted."},
825+
RPCResult{RPCResult::Type::NUM, "weight", "The transaction weight as defined in BIP 141."},
826+
RPCResult{RPCResult::Type::NUM_TIME, "expiration", "The orphan expiration time expressed in " + UNIX_EPOCH_TIME},
827+
RPCResult{RPCResult::Type::ARR, "from", "",
828+
{
829+
RPCResult{RPCResult::Type::NUM, "peer_id", "Peer ID"},
830+
}},
831+
};
832+
}
833+
834+
static UniValue OrphanToJSON(const TxOrphanage::OrphanTxBase& orphan)
835+
{
836+
UniValue o(UniValue::VOBJ);
837+
o.pushKV("txid", orphan.tx->GetHash().ToString());
838+
o.pushKV("wtxid", orphan.tx->GetWitnessHash().ToString());
839+
o.pushKV("bytes", orphan.tx->GetTotalSize());
840+
o.pushKV("vsize", GetVirtualTransactionSize(*orphan.tx));
841+
o.pushKV("weight", GetTransactionWeight(*orphan.tx));
842+
o.pushKV("expiration", int64_t{TicksSinceEpoch<std::chrono::seconds>(orphan.nTimeExpire)});
843+
UniValue from(UniValue::VARR);
844+
from.push_back(orphan.fromPeer); // only one fromPeer for now
845+
o.pushKV("from", from);
846+
return o;
847+
}
848+
849+
static RPCHelpMan getorphantxs()
850+
{
851+
return RPCHelpMan{"getorphantxs",
852+
"\nShows transactions in the tx orphanage.\n"
853+
"\nEXPERIMENTAL warning: this call may be changed in future releases.\n",
854+
{
855+
{"verbosity|verbose", RPCArg::Type::NUM, RPCArg::Default{0}, "0 for an array of txids (may contain duplicates), 1 for an array of objects with tx details, and 2 for details from (1) and tx hex",
856+
RPCArgOptions{.skip_type_check = true}},
857+
},
858+
{
859+
RPCResult{"for verbose = 0",
860+
RPCResult::Type::ARR, "", "",
861+
{
862+
{RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
863+
}},
864+
RPCResult{"for verbose = 1",
865+
RPCResult::Type::ARR, "", "",
866+
{
867+
{RPCResult::Type::OBJ, "", "", OrphanDescription()},
868+
}},
869+
RPCResult{"for verbose = 2",
870+
RPCResult::Type::ARR, "", "",
871+
{
872+
{RPCResult::Type::OBJ, "", "",
873+
Cat<std::vector<RPCResult>>(
874+
OrphanDescription(),
875+
{{RPCResult::Type::STR_HEX, "hex", "The serialized, hex-encoded transaction data"}}
876+
)
877+
},
878+
}},
879+
},
880+
RPCExamples{
881+
HelpExampleCli("getorphantxs", "2")
882+
+ HelpExampleRpc("getorphantxs", "2")
883+
},
884+
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
885+
{
886+
const NodeContext& node = EnsureAnyNodeContext(request.context);
887+
PeerManager& peerman = EnsurePeerman(node);
888+
std::vector<TxOrphanage::OrphanTxBase> orphanage = peerman.GetOrphanTransactions();
889+
890+
int verbosity{ParseVerbosity(request.params[0], /*default_verbosity=*/0)};
891+
892+
UniValue ret(UniValue::VARR);
893+
894+
if (verbosity <= 0) {
895+
for (auto const& orphan : orphanage) {
896+
ret.push_back(orphan.tx->GetHash().ToString());
897+
}
898+
} else if (verbosity == 1) {
899+
for (auto const& orphan : orphanage) {
900+
ret.push_back(OrphanToJSON(orphan));
901+
}
902+
} else {
903+
// >= 2
904+
for (auto const& orphan : orphanage) {
905+
UniValue o{OrphanToJSON(orphan)};
906+
o.pushKV("hex", EncodeHexTx(*orphan.tx));
907+
ret.push_back(o);
908+
}
909+
}
910+
911+
return ret;
912+
},
913+
};
914+
}
915+
815916
static RPCHelpMan submitpackage()
816917
{
817918
return RPCHelpMan{"submitpackage",
@@ -1027,6 +1128,7 @@ void RegisterMempoolRPCCommands(CRPCTable& t)
10271128
{"blockchain", &getrawmempool},
10281129
{"blockchain", &importmempool},
10291130
{"blockchain", &savemempool},
1131+
{"hidden", &getorphantxs},
10301132
{"rawtransactions", &submitpackage},
10311133
};
10321134
for (const auto& c : commands) {

src/test/fuzz/rpc.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
143143
"getnetworkhashps",
144144
"getnetworkinfo",
145145
"getnodeaddresses",
146+
"getorphantxs",
146147
"getpeerinfo",
147148
"getprioritisedtransactions",
148149
"getrawaddrman",

0 commit comments

Comments
 (0)