Skip to content

Commit

Permalink
Move signer_list in JSON response for api_version 2
Browse files Browse the repository at this point in the history
See XRPLF/xrpl-dev-portal#938 for context.
  • Loading branch information
Frassle committed Feb 13, 2021
1 parent 735b8b7 commit 1e9b00f
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 3 deletions.
4 changes: 3 additions & 1 deletion RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ Have new ideas? Need help with setting up your node? Come visit us [here](https:

# Change Log

- Work on a version 2 of the XRP Network API has begun. The new API returns the code `notSynced` in place of `noClosed`, `noCurrent`, and `noNetwork`. And `invalidLgrRange` is returned in place of `lgrIdxInvalid`.
- Work on a version 2 of the XRP Network API has begun.
- The new API returns the code `notSynced` in place of `noClosed`, `noCurrent`, and `noNetwork`. And `invalidLgrRange` is returned in place of `lgrIdxInvalid`.
- `signer_lists` is returned in the root of the `account_lines` response, no longer nested under `account_data`.
- The version 2 API can be specified by adding "api_version" : 2 to your json request. The default version remains 1 (if unspecified), except for the command line interface which always uses the latest verison.

# Releases
Expand Down
10 changes: 8 additions & 2 deletions src/ripple/rpc/handlers/AccountInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,14 @@ doAccountInfo(RPC::JsonContext& context)
if (sleSigners)
jvSignerList.append(sleSigners->getJson(JsonOptions::none));

result[jss::account_data][jss::signer_lists] =
std::move(jvSignerList);
// Documentation states this is returned as part of the account_info response,
// but previously the code put it under account_data. We can move this to the
// documentated location from apiVersion 2 onwards.
if (context.apiVersion == 1) {
result[jss::account_data][jss::signer_lists] = std::move(jvSignerList);
} else {
result[jss::signer_lists] = std::move(jvSignerList);
}
}
// Return queue info if that is requested
if (queue)
Expand Down
121 changes: 121 additions & 0 deletions src/test/rpc/AccountInfo_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,127 @@ class AccountInfo_test : public beast::unit_test::suite
}
}

// Test the "signer_lists" argument in account_info, with api_version 2.
void
testSignerListsApiVersion2()
{
using namespace jtx;
Env env(*this);
Account const alice{"alice"};
env.fund(XRP(1000), alice);

auto const withoutSigners =
std::string("{ ") + "\"api_version\": 2, \"account\": \"" + alice.human() + "\"}";

auto const withSigners = std::string("{ ") + "\"api_version\": 2, \"account\": \"" +
alice.human() + "\", " + "\"signer_lists\": true }";

// Alice has no SignerList yet.
{
// account_info without the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withoutSigners);
BEAST_EXPECT(
info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data));
BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
jss::signer_lists));
}
{
// account_info with the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withSigners);
BEAST_EXPECT(
info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data));
auto const& data = info[jss::result][jss::account_data];
BEAST_EXPECT(data.isMember(jss::signer_lists));
auto const& signerLists = data[jss::signer_lists];
BEAST_EXPECT(signerLists.isArray());
BEAST_EXPECT(signerLists.size() == 0);
}

// Give alice a SignerList.
Account const bogie{"bogie"};

Json::Value const smallSigners = signers(alice, 2, {{bogie, 3}});
env(smallSigners);
{
// account_info without the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withoutSigners);
BEAST_EXPECT(
info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data));
BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
jss::signer_lists));
}
{
// account_info with the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withSigners);
BEAST_EXPECT(
info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data));
auto const& data = info[jss::result][jss::account_data];
BEAST_EXPECT(data.isMember(jss::signer_lists));
auto const& signerLists = data[jss::signer_lists];
BEAST_EXPECT(signerLists.isArray());
BEAST_EXPECT(signerLists.size() == 1);
auto const& signers = signerLists[0u];
BEAST_EXPECT(signers.isObject());
BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 2);
auto const& signerEntries = signers[sfSignerEntries.jsonName];
BEAST_EXPECT(signerEntries.size() == 1);
auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName];
BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
}

// Give alice a big signer list
Account const demon{"demon"};
Account const ghost{"ghost"};
Account const haunt{"haunt"};
Account const jinni{"jinni"};
Account const phase{"phase"};
Account const shade{"shade"};
Account const spook{"spook"};

Json::Value const bigSigners = signers(
alice,
4,
{
{bogie, 1},
{demon, 1},
{ghost, 1},
{haunt, 1},
{jinni, 1},
{phase, 1},
{shade, 1},
{spook, 1},
});
env(bigSigners);
{
// account_info with the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withSigners);
BEAST_EXPECT(
info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data));
auto const& data = info[jss::result][jss::account_data];
BEAST_EXPECT(data.isMember(jss::signer_lists));
auto const& signerLists = data[jss::signer_lists];
BEAST_EXPECT(signerLists.isArray());
BEAST_EXPECT(signerLists.size() == 1);
auto const& signers = signerLists[0u];
BEAST_EXPECT(signers.isObject());
BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 4);
auto const& signerEntries = signers[sfSignerEntries.jsonName];
BEAST_EXPECT(signerEntries.size() == 8);
for (unsigned i = 0u; i < 8; ++i)
{
auto const& entry = signerEntries[i][sfSignerEntry.jsonName];
BEAST_EXPECT(entry.size() == 2);
BEAST_EXPECT(entry.isMember(sfAccount.jsonName));
BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1);
}
}
}

// Test the "signer_lists" argument in account_info, version 2 API.
void
testSignerListsV2()
Expand Down

0 comments on commit 1e9b00f

Please sign in to comment.