Skip to content

Commit

Permalink
Add RPC Tests (#295)
Browse files Browse the repository at this point in the history
Co-authored-by: RichardAH <richard.holland@starstone.co.nz>
  • Loading branch information
dangell7 and RichardAH committed Apr 18, 2024
1 parent 3c5f118 commit 6636e3b
Show file tree
Hide file tree
Showing 19 changed files with 607 additions and 81 deletions.
1 change: 1 addition & 0 deletions Builds/CMake/RippledCore.cmake
Expand Up @@ -983,6 +983,7 @@ if (tests)
src/test/rpc/AccountLinesRPC_test.cpp
src/test/rpc/AccountObjects_test.cpp
src/test/rpc/AccountOffers_test.cpp
src/test/rpc/AccountNamespace_test.cpp
src/test/rpc/AccountSet_test.cpp
src/test/rpc/AccountTx_test.cpp
src/test/rpc/AmendmentBlocked_test.cpp
Expand Down
3 changes: 3 additions & 0 deletions Builds/levelization/results/loops.txt
Expand Up @@ -52,6 +52,9 @@ Loop: ripple.overlay ripple.rpc
Loop: test.app test.jtx
test.app > test.jtx

Loop: test.app test.rpc
test.rpc == test.app

Loop: test.jtx test.toplevel
test.toplevel > test.jtx

Expand Down
1 change: 0 additions & 1 deletion Builds/levelization/results/ordering.txt
Expand Up @@ -90,7 +90,6 @@ test.app > ripple.overlay
test.app > ripple.protocol
test.app > ripple.resource
test.app > ripple.rpc
test.app > test.rpc
test.app > test.toplevel
test.app > test.unit_test
test.basics > ripple.basics
Expand Down
1 change: 1 addition & 0 deletions src/ripple/protocol/impl/ErrorCodes.cpp
Expand Up @@ -108,6 +108,7 @@ constexpr static ErrorInfo unorderedErrorInfos[]{
{rpcSTREAM_MALFORMED, "malformedStream", "Stream malformed.", 400},
{rpcTOO_BUSY, "tooBusy", "The server is too busy to help you now.", 503},
{rpcTXN_NOT_FOUND, "txnNotFound", "Transaction not found.", 404},
{rpcNAMESPACE_NOT_FOUND, "namespaceNotFound", "Namespace not found.", 404},
{rpcUNKNOWN_COMMAND, "unknownCmd", "Unknown method.", 405}};
// clang-format on

Expand Down
3 changes: 3 additions & 0 deletions src/ripple/protocol/jss.h
Expand Up @@ -161,6 +161,7 @@ JSS(account_data); // out: AccountInfo
JSS(account_flags); // out: AccountInfo
JSS(account_hash); // out: LedgerToJson
JSS(account_id); // out: WalletPropose
JSS(account_namespace); // out: AccountNamespace
JSS(account_nfts); // out: AccountNFTs
JSS(account_objects); // out: AccountObjects
JSS(account_root); // in: LedgerEntry
Expand Down Expand Up @@ -353,6 +354,7 @@ JSS(id); // websocket.
JSS(ident); // in: AccountCurrencies, AccountInfo,
// OwnerInfo
JSS(ignore_default); // in: AccountLines
JSS(import_vlseq); // in: LedgerEntry
JSS(inLedger); // out: tx/Transaction
JSS(in_queue);
JSS(inbound); // out: PeerImp
Expand Down Expand Up @@ -699,6 +701,7 @@ JSS(TRANSACTION_FLAGS_INDICIES); // out: RPC server_definitions
JSS(type_hex); // out: STPathSet
JSS(unl); // out: UnlList
JSS(unlimited); // out: Connection.h
JSS(unl_report); // in: LedgerEntry
JSS(uptime); // out: GetCounts
JSS(uri); // out: ValidatorSites
JSS(uri_token); // in: LedgerEntry
Expand Down
3 changes: 2 additions & 1 deletion src/ripple/rpc/handlers/AccountInfo.cpp
Expand Up @@ -78,7 +78,7 @@ doAccountInfo(RPC::JsonContext& context)
return jvAccepted;

static constexpr std::
array<std::pair<std::string_view, LedgerSpecificFlags>, 9>
array<std::pair<std::string_view, LedgerSpecificFlags>, 10>
lsFlags{
{{"defaultRipple", lsfDefaultRipple},
{"depositAuth", lsfDepositAuth},
Expand All @@ -88,6 +88,7 @@ doAccountInfo(RPC::JsonContext& context)
{"noFreeze", lsfNoFreeze},
{"passwordSpent", lsfPasswordSpent},
{"requireAuthorization", lsfRequireAuth},
{"tshCollect", lsfTshCollect},
{"requireDestinationTag", lsfRequireDestTag}}};

static constexpr std::
Expand Down
1 change: 0 additions & 1 deletion src/ripple/rpc/handlers/AccountNamespace.cpp
Expand Up @@ -42,7 +42,6 @@ namespace ripple {
namespace_id: <namespace hex>
ledger_hash: <string> // optional
ledger_index: <string | unsigned integer> // optional
type: <string> // optional, defaults to all account objects types
limit: <integer> // optional
marker: <opaque> // optional, resume previous query
}
Expand Down
61 changes: 59 additions & 2 deletions src/ripple/rpc/handlers/LedgerEntry.cpp
Expand Up @@ -24,6 +24,7 @@
#include <ripple/net/RPCErr.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/PublicKey.h>
#include <ripple/protocol/jss.h>
#include <ripple/rpc/Context.h>
#include <ripple/rpc/GRPCHandlers.h>
Expand Down Expand Up @@ -231,6 +232,41 @@ doLedgerEntry(RPC::JsonContext& context)
uNodeIndex = keylet::emittedTxn(uNodeIndex).key;
}
}
else if (context.params.isMember(jss::import_vlseq))
{
expectedType = ltIMPORT_VLSEQ;
if (!context.params[jss::import_vlseq].isObject())
{
if (!uNodeIndex.parseHex(
context.params[jss::import_vlseq].asString()))
{
uNodeIndex = beast::zero;
jvResult[jss::error] = "malformedRequest";
}
}
else if (
!context.params[jss::import_vlseq].isMember(jss::public_key) ||
!context.params[jss::import_vlseq][jss::public_key].isString())
{
jvResult[jss::error] = "malformedRequest";
}
else
{
auto const pkHex = strUnHex(
context.params[jss::import_vlseq][jss::public_key].asString());
auto const pkSlice = makeSlice(*pkHex);
if (!publicKeyType(pkSlice))
{
uNodeIndex = beast::zero;
jvResult[jss::error] = "malformedRequest";
}
else
{
auto const pk = PublicKey(pkSlice);
uNodeIndex = keylet::import_vlseq(pk).key;
}
}
}
else if (context.params.isMember(jss::offer))
{
expectedType = ltOFFER;
Expand Down Expand Up @@ -277,11 +313,32 @@ doLedgerEntry(RPC::JsonContext& context)
{
expectedType = ltURI_TOKEN;

if (!uNodeIndex.parseHex(context.params[jss::uri_token].asString()))
if (!context.params[jss::uri_token].isObject())
{
if (!uNodeIndex.parseHex(context.params[jss::uri_token].asString()))
{
uNodeIndex = beast::zero;
jvResult[jss::error] = "malformedRequest";
}
}
else if (
!context.params[jss::uri_token].isMember(jss::account) ||
!context.params[jss::uri_token].isMember(jss::uri))
{
uNodeIndex = beast::zero;
jvResult[jss::error] = "malformedRequest";
}
else
{
auto const id = parseBase58<AccountID>(
context.params[jss::uri_token][jss::account].asString());
auto const strUri =
context.params[jss::uri_token][jss::uri].asString();
Blob raw = Blob(strUri.begin(), strUri.end());
if (!id)
jvResult[jss::error] = "malformedAddress";
else
uNodeIndex = keylet::uritoken(*id, raw).key;
}
}
else if (context.params.isMember(jss::ripple_state))
{
Expand Down
7 changes: 5 additions & 2 deletions src/ripple/rpc/impl/RPCHelpers.cpp
Expand Up @@ -1067,27 +1067,30 @@ chooseLedgerEntryType(Json::Value const& params)
std::pair<RPC::Status, LedgerEntryType> result{RPC::Status::OK, ltANY};
if (params.isMember(jss::type))
{
static constexpr std::array<std::pair<char const*, LedgerEntryType>, 19>
static constexpr std::array<std::pair<char const*, LedgerEntryType>, 22>
types{
{{jss::account, ltACCOUNT_ROOT},
{jss::amendments, ltAMENDMENTS},
{jss::check, ltCHECK},
{jss::deposit_preauth, ltDEPOSIT_PREAUTH},
{jss::directory, ltDIR_NODE},
{jss::escrow, ltESCROW},
{jss::emitted_txn, ltEMITTED_TXN},
{jss::hook, ltHOOK},
{jss::hook_definition, ltHOOK_DEFINITION},
{jss::hook_state, ltHOOK_STATE},
{jss::fee, ltFEE_SETTINGS},
{jss::hashes, ltLEDGER_HASHES},
{jss::import_vlseq, ltIMPORT_VLSEQ},
{jss::offer, ltOFFER},
{jss::payment_channel, ltPAYCHAN},
{jss::uri_token, ltURI_TOKEN},
{jss::signer_list, ltSIGNER_LIST},
{jss::state, ltRIPPLE_STATE},
{jss::ticket, ltTICKET},
{jss::nft_offer, ltNFTOKEN_OFFER},
{jss::nft_page, ltNFTOKEN_PAGE}}};
{jss::nft_page, ltNFTOKEN_PAGE},
{jss::unl_report, ltUNL_REPORT}}};

auto const& p = params[jss::type];
if (!p.isString())
Expand Down
24 changes: 1 addition & 23 deletions src/test/app/Import_test.cpp
Expand Up @@ -84,28 +84,6 @@ class Import_test : public beast::unit_test::suite
return 0;
}

STTx
createUNLReportTx(
LedgerIndex seq,
PublicKey const& importKey,
PublicKey const& valKey)
{
auto fill = [&](auto& obj) {
obj.setFieldU32(sfLedgerSequence, seq);
obj.set(([&]() {
auto inner = std::make_unique<STObject>(sfActiveValidator);
inner->setFieldVL(sfPublicKey, valKey);
return inner;
})());
obj.set(([&]() {
auto inner = std::make_unique<STObject>(sfImportVLKey);
inner->setFieldVL(sfPublicKey, importKey);
return inner;
})());
};
return STTx(ttUNL_REPORT, fill);
}

bool
hasUNLReport(jtx::Env const& env)
{
Expand Down Expand Up @@ -5320,7 +5298,7 @@ class Import_test : public beast::unit_test::suite
// insert a ttUNL_REPORT pseudo into the open ledger
env.app().openLedger().modify(
[&](OpenView& view, beast::Journal j) -> bool {
STTx tx = createUNLReportTx(
STTx tx = unl::createUNLReportTx(
env.current()->seq() + 1, ivlKeys[0], vlKeys[0]);
uint256 txID = tx.getTransactionID();
auto s = std::make_shared<ripple::Serializer>();
Expand Down
24 changes: 1 addition & 23 deletions src/test/app/XahauGenesis_test.cpp
Expand Up @@ -3598,28 +3598,6 @@ struct XahauGenesis_test : public beast::unit_test::suite
return slep != nullptr;
}

STTx
createUNLReportTx(
LedgerIndex seq,
PublicKey const& importKey,
PublicKey const& valKey)
{
auto fill = [&](auto& obj) {
obj.setFieldU32(sfLedgerSequence, seq);
obj.set(([&]() {
auto inner = std::make_unique<STObject>(sfActiveValidator);
inner->setFieldVL(sfPublicKey, valKey);
return inner;
})());
obj.set(([&]() {
auto inner = std::make_unique<STObject>(sfImportVLKey);
inner->setFieldVL(sfPublicKey, importKey);
return inner;
})());
};
return STTx(ttUNL_REPORT, fill);
}

void
activateUNLReport(
jtx::Env& env,
Expand All @@ -3631,7 +3609,7 @@ struct XahauGenesis_test : public beast::unit_test::suite
{
env.app().openLedger().modify(
[&](OpenView& view, beast::Journal j) -> bool {
STTx tx = createUNLReportTx(
STTx tx = unl::createUNLReportTx(
env.current()->seq() + 1, ivlKeys[0], vlKey);
uint256 txID = tx.getTransactionID();
auto s = std::make_shared<ripple::Serializer>();
Expand Down
22 changes: 22 additions & 0 deletions src/test/jtx/impl/unl.cpp
Expand Up @@ -90,6 +90,28 @@ createTx(bool disabling, LedgerIndex seq, PublicKey const& txKey)
return STTx(ttUNL_MODIFY, fill);
}

STTx
createUNLReportTx(
LedgerIndex seq,
PublicKey const& importKey,
PublicKey const& valKey)
{
auto fill = [&](auto& obj) {
obj.setFieldU32(sfLedgerSequence, seq);
obj.set(([&]() {
auto inner = std::make_unique<STObject>(sfActiveValidator);
inner->setFieldVL(sfPublicKey, valKey);
return inner;
})());
obj.set(([&]() {
auto inner = std::make_unique<STObject>(sfImportVLKey);
inner->setFieldVL(sfPublicKey, importKey);
return inner;
})());
};
return STTx(ttUNL_REPORT, fill);
}

} // namespace unl
} // namespace test
} // namespace ripple
14 changes: 14 additions & 0 deletions src/test/jtx/unl.h
Expand Up @@ -78,6 +78,20 @@ countTx(std::shared_ptr<SHAMap> const& txSet);
STTx
createTx(bool disabling, LedgerIndex seq, PublicKey const& txKey);

/**
* Create ttUNL_REPORT Tx
*
* @param seq current ledger seq
* @param importKey the public key of the import network
* @param txKey the public key of the validator
* @return the ttUNL_REPORT Tx
*/
STTx
createUNLReportTx(
LedgerIndex seq,
PublicKey const& importKey,
PublicKey const& valKey);

} // namespace unl

} // namespace test
Expand Down
3 changes: 2 additions & 1 deletion src/test/rpc/AccountInfo_test.cpp
Expand Up @@ -516,14 +516,15 @@ class AccountInfo_test : public beast::unit_test::suite
};

static constexpr std::
array<std::pair<std::string_view, std::uint32_t>, 7>
array<std::pair<std::string_view, std::uint32_t>, 8>
asFlags{
{{"defaultRipple", asfDefaultRipple},
{"depositAuth", asfDepositAuth},
{"disallowIncomingXRP", asfDisallowXRP},
{"globalFreeze", asfGlobalFreeze},
{"noFreeze", asfNoFreeze},
{"requireAuthorization", asfRequireAuth},
{"tshCollect", asfTshCollect},
{"requireDestinationTag", asfRequireDest}}};

for (auto& asf : asFlags)
Expand Down

0 comments on commit 6636e3b

Please sign in to comment.