mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-05 08:48:03 +00:00
Add "seed" to JSONRPC unit tests (RIPD-1099):
There was a bug in version 0.30.1 where signing with an ed25519 key and a corrupt seed would cause the "sign" and "sign_for" commands to return an unexpected error. That bug was fixed in the 0.31.0 release. These unit tests verify the fix. The error message for a corrupt seed is also slightly improved.
This commit is contained in:
committed by
Nik Bougalis
parent
1cf518e82c
commit
3a1fa4a552
@@ -71,17 +71,17 @@ enum CommentPlacement
|
||||
class StaticString
|
||||
{
|
||||
public:
|
||||
explicit StaticString ( const char* czstring )
|
||||
constexpr explicit StaticString ( const char* czstring )
|
||||
: str_ ( czstring )
|
||||
{
|
||||
}
|
||||
|
||||
operator const char* () const
|
||||
constexpr operator const char* () const
|
||||
{
|
||||
return str_;
|
||||
}
|
||||
|
||||
const char* c_str () const
|
||||
constexpr const char* c_str () const
|
||||
{
|
||||
return str_;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace jss {
|
||||
|
||||
// JSON static strings
|
||||
|
||||
#define JSS(x) const ::Json::StaticString x ( #x )
|
||||
#define JSS(x) constexpr ::Json::StaticString x ( #x )
|
||||
|
||||
/* The "StaticString" field names are used instead of string literals to
|
||||
optimize the performance of accessing members of Json::Value objects.
|
||||
|
||||
@@ -65,31 +65,43 @@ std::pair<PublicKey, SecretKey>
|
||||
keypairForSignature (Json::Value const& params, Json::Value& error)
|
||||
{
|
||||
bool const has_key_type = params.isMember (jss::key_type);
|
||||
bool const hasPassphrase = params.isMember (jss::passphrase);
|
||||
bool const hasSecret = params.isMember (jss::secret);
|
||||
bool const hasSeed = params.isMember (jss::seed);
|
||||
bool const hasSeedHex = params.isMember (jss::seed_hex);
|
||||
|
||||
int const n_secrets =
|
||||
(hasPassphrase ? 1 : 0) +
|
||||
(hasSecret ? 1 : 0) +
|
||||
(hasSeed ? 1 : 0) +
|
||||
(hasSeedHex ? 1 : 0);
|
||||
// All of the secret types we allow, but only one at a time.
|
||||
// The array should be constexpr, but that makes Visual Studio unhappy.
|
||||
static char const* const secretTypes[]
|
||||
{
|
||||
jss::passphrase.c_str(),
|
||||
jss::secret.c_str(),
|
||||
jss::seed.c_str(),
|
||||
jss::seed_hex.c_str()
|
||||
};
|
||||
|
||||
if (n_secrets == 0)
|
||||
// Identify which secret type is in use.
|
||||
char const* secretType = nullptr;
|
||||
int secretCount = 0;
|
||||
for (auto t : secretTypes)
|
||||
{
|
||||
if (params.isMember (t))
|
||||
{
|
||||
++secretCount;
|
||||
secretType = t;
|
||||
}
|
||||
}
|
||||
|
||||
if (secretCount == 0 || secretType == nullptr)
|
||||
{
|
||||
error = RPC::missing_field_error (jss::secret);
|
||||
return { };
|
||||
}
|
||||
|
||||
if (n_secrets > 1)
|
||||
if (secretCount > 1)
|
||||
{
|
||||
// `passphrase`, `secret`, `seed`, and `seed_hex` are mutually exclusive.
|
||||
error = rpcError (rpcBAD_SECRET);
|
||||
return { };
|
||||
}
|
||||
|
||||
if (has_key_type && hasSecret)
|
||||
if (has_key_type && (secretType == jss::secret.c_str()))
|
||||
{
|
||||
// `secret` is deprecated.
|
||||
error = rpcError (rpcBAD_SECRET);
|
||||
@@ -121,7 +133,7 @@ keypairForSignature (Json::Value const& params, Json::Value& error)
|
||||
if (!seed)
|
||||
{
|
||||
error = RPC::make_error (rpcBAD_SEED,
|
||||
RPC::invalid_field_message (jss::secret));
|
||||
RPC::invalid_field_message (secretType));
|
||||
return { };
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,15 @@ struct TxnTestData
|
||||
{
|
||||
char const* const description;
|
||||
char const* const json;
|
||||
// The JSON is applied to four different interfaces:
|
||||
// 1. sign,
|
||||
// 2. submit,
|
||||
// 3. sign_for, and
|
||||
// 4. submit_multisigned.
|
||||
// The JSON is not valid for all of these interfaces, but it should
|
||||
// crash none of them, and should provide reliable error messages.
|
||||
//
|
||||
// The expMsg array contains the expected error string for the above cases.
|
||||
char const* const expMsg[4];
|
||||
|
||||
// Default and copy ctors should be deleted, but that displeases gcc 4.6.3.
|
||||
@@ -533,6 +542,44 @@ R"({
|
||||
"Missing field 'tx_json.Sequence'.",
|
||||
"Missing field 'tx_json.Sequence'."}},
|
||||
|
||||
{ "Use 'seed' instead of 'secret'.",
|
||||
R"({
|
||||
"command": "doesnt_matter",
|
||||
"account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
|
||||
"key_type": "ed25519",
|
||||
"seed": "sh1yJfwoi98zCygwijUzuHmJDeVKd",
|
||||
"tx_json": {
|
||||
"Account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
|
||||
"Amount": "1000000000",
|
||||
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
|
||||
"TransactionType": "Payment"
|
||||
}
|
||||
})",
|
||||
{
|
||||
"",
|
||||
"",
|
||||
"Missing field 'tx_json.Sequence'.",
|
||||
"Missing field 'tx_json.Sequence'."}},
|
||||
|
||||
{ "Malformed 'seed'.",
|
||||
R"({
|
||||
"command": "doesnt_matter",
|
||||
"account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
|
||||
"key_type": "ed25519",
|
||||
"seed": "not a seed",
|
||||
"tx_json": {
|
||||
"Account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
|
||||
"Amount": "1000000000",
|
||||
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
|
||||
"TransactionType": "Payment"
|
||||
}
|
||||
})",
|
||||
{
|
||||
"Invalid field 'seed'.",
|
||||
"Invalid field 'seed'.",
|
||||
"Missing field 'tx_json.Sequence'.",
|
||||
"Missing field 'tx_json.Sequence'."}},
|
||||
|
||||
{ "'tx_json' must be present.",
|
||||
R"({
|
||||
"command": "doesnt_matter",
|
||||
@@ -841,6 +888,52 @@ R"({
|
||||
"",
|
||||
"Missing field 'tx_json.Signers'."}},
|
||||
|
||||
{ "Offline sign_for using 'seed' instead of 'secret'.",
|
||||
R"({
|
||||
"command": "doesnt_matter",
|
||||
"account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
|
||||
"key_type": "ed25519",
|
||||
"seed": "sh1yJfwoi98zCygwijUzuHmJDeVKd",
|
||||
"offline": 1,
|
||||
"tx_json": {
|
||||
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
|
||||
"Amount": "1000000000",
|
||||
"Destination": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
|
||||
"Fee": 50,
|
||||
"Sequence": 0,
|
||||
"SigningPubKey": "",
|
||||
"TransactionType": "Payment"
|
||||
}
|
||||
})",
|
||||
{
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"Missing field 'tx_json.Signers'."}},
|
||||
|
||||
{ "Malformed seed in sign_for.",
|
||||
R"({
|
||||
"command": "doesnt_matter",
|
||||
"account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
|
||||
"key_type": "ed25519",
|
||||
"seed": "sh1yJfwoi98zCygwjUzuHmJDeVKd",
|
||||
"offline": 1,
|
||||
"tx_json": {
|
||||
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
|
||||
"Amount": "1000000000",
|
||||
"Destination": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
|
||||
"Fee": 50,
|
||||
"Sequence": 0,
|
||||
"SigningPubKey": "",
|
||||
"TransactionType": "Payment"
|
||||
}
|
||||
})",
|
||||
{
|
||||
"Invalid field 'seed'.",
|
||||
"Invalid field 'seed'.",
|
||||
"Invalid field 'seed'.",
|
||||
"Missing field 'tx_json.Signers'."}},
|
||||
|
||||
{ "Missing 'Account' in sign_for.",
|
||||
R"({
|
||||
"command": "doesnt_matter",
|
||||
@@ -1840,12 +1933,16 @@ public:
|
||||
test::jtx::Account const a {"a"}; // rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA
|
||||
test::jtx::Account const g {"g"}; // rLPwWB1itaUGMV8kbMLLysjGkEpTM2Soy4
|
||||
auto const USD = g["USD"];
|
||||
|
||||
// Account: rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi
|
||||
// seed: sh1yJfwoi98zCygwijUzuHmJDeVKd
|
||||
test::jtx::Account const ed {"ed", KeyType::ed25519};
|
||||
// master is rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh.
|
||||
// "b" (not in the ledger) is rDg53Haik2475DJx8bjMDSDPj4VX7htaMd.
|
||||
// "c" (phantom signer) is rPcNzota6B8YBokhYtcTNqQVCngtbnWfux.
|
||||
|
||||
test::jtx::Env env(*this, test::jtx::features(featureMultiSign));
|
||||
env.fund(test::jtx::XRP(100000), a, g);
|
||||
env.fund(test::jtx::XRP(100000), a, ed, g);
|
||||
env.close();
|
||||
|
||||
env(trust(a, USD(1000)));
|
||||
|
||||
Reference in New Issue
Block a user