mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-02 00:15:50 +00:00
Disallow both single- and multi-signing in RPC (RIPD-1713):
The ledger already declared a transaction that is both single- and multi-signing malformed. This just adds some checking in the signing RPC commands (like submit and sign_for) which allows that sort of error to be identified a bit closer to the user. In the process of adding this code a bug was found in the RPCCall unit test. That bug is fixed as well.
This commit is contained in:
committed by
Nik Bougalis
parent
d8c450d272
commit
36d6758945
@@ -1,7 +1,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
Copyright (c) 2012 - 2019 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -81,6 +81,8 @@ enum error_code_i
|
||||
// Bad parameter
|
||||
rpcACT_BITCOIN,
|
||||
rpcACT_MALFORMED,
|
||||
rpcALREADY_MULTISIG,
|
||||
rpcALREADY_SINGLE_SIG,
|
||||
rpcQUALITY_MALFORMED,
|
||||
rpcBAD_BLOB,
|
||||
rpcBAD_FEATURE,
|
||||
@@ -106,7 +108,7 @@ enum error_code_i
|
||||
rpcPAYS_AMT_MALFORMED,
|
||||
rpcPORT_MALFORMED,
|
||||
rpcPUBLIC_MALFORMED,
|
||||
rpcSIGN_FOR_MALFORMED,
|
||||
rpcSIGNING_MALFORMED,
|
||||
rpcSENDMAX_MALFORMED,
|
||||
rpcSRC_ACT_MALFORMED,
|
||||
rpcSRC_ACT_MISSING,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
Copyright (c) 2012 - 2019 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -54,6 +54,8 @@ public:
|
||||
add (rpcACT_EXISTS, "actExists", "Account already exists.");
|
||||
add (rpcACT_MALFORMED, "actMalformed", "Account malformed.");
|
||||
add (rpcACT_NOT_FOUND, "actNotFound", "Account not found.");
|
||||
add (rpcALREADY_MULTISIG, "alreadyMultisig", "Already multisigned.");
|
||||
add (rpcALREADY_SINGLE_SIG, "alreadySingleSig", "Already single-signed.");
|
||||
add (rpcAMENDMENT_BLOCKED, "amendmentBlocked", "Amendment blocked, need upgrade.");
|
||||
add (rpcATX_DEPRECATED, "deprecated", "Use the new API or specify a ledger range.");
|
||||
add (rpcBAD_BLOB, "badBlob", "Blob must be a non-empty hex string.");
|
||||
@@ -64,7 +66,7 @@ public:
|
||||
add (rpcBAD_SEED, "badSeed", "Disallowed seed.");
|
||||
add (rpcBAD_SYNTAX, "badSyntax", "Syntax error.");
|
||||
add (rpcCHANNEL_MALFORMED, "channelMalformed", "Payment channel is malformed.");
|
||||
add (rpcCHANNEL_AMT_MALFORMED, "channelAmtMalformed","Payment channel amount is malformed.");
|
||||
add (rpcCHANNEL_AMT_MALFORMED, "channelAmtMalformed", "Payment channel amount is malformed.");
|
||||
add (rpcCOMMAND_MISSING, "commandMissing", "Missing command entry.");
|
||||
add (rpcDST_ACT_MALFORMED, "dstActMalformed", "Destination account is malformed.");
|
||||
add (rpcDST_ACT_MISSING, "dstActMissing", "Destination account not provided.");
|
||||
@@ -106,7 +108,7 @@ public:
|
||||
add (rpcPORT_MALFORMED, "portMalformed", "Port is malformed.");
|
||||
add (rpcPUBLIC_MALFORMED, "publicMalformed", "Public key is malformed.");
|
||||
add (rpcQUALITY_MALFORMED, "qualityMalformed", "Quality malformed.");
|
||||
add (rpcSIGN_FOR_MALFORMED, "signForMalformed", "Signing for account is malformed.");
|
||||
add (rpcSIGNING_MALFORMED, "signingMalformed", "Signing of transaction is malformed.");
|
||||
add (rpcSLOW_DOWN, "slowDown", "You are placing too much load on the server.");
|
||||
add (rpcSRC_ACT_MALFORMED, "srcActMalformed", "Source account is malformed.");
|
||||
add (rpcSRC_ACT_MISSING, "srcActMissing", "Source account not provided.");
|
||||
|
||||
@@ -80,6 +80,11 @@ public:
|
||||
(multiSignature_ != nullptr));
|
||||
}
|
||||
|
||||
bool isSingleSigning () const
|
||||
{
|
||||
return !isMultiSigning();
|
||||
}
|
||||
|
||||
// When multi-signing we should not edit the tx_json fields.
|
||||
bool editFields () const
|
||||
{
|
||||
@@ -447,9 +452,20 @@ transactionPreProcessImpl (
|
||||
tx_json[jss::Flags] = tfFullyCanonicalSig;
|
||||
}
|
||||
|
||||
// If multisigning then we need to return the public key.
|
||||
// If multisigning there should not be a single signature and vice versa.
|
||||
if (signingArgs.isMultiSigning())
|
||||
{
|
||||
if (tx_json.isMember (sfTxnSignature.jsonName))
|
||||
return rpcError (rpcALREADY_SINGLE_SIG);
|
||||
|
||||
// If multisigning then we need to return the public key.
|
||||
signingArgs.setPublicKey (keypair.first);
|
||||
}
|
||||
else if (signingArgs.isSingleSigning())
|
||||
{
|
||||
if (tx_json.isMember (sfSigners.jsonName))
|
||||
return rpcError (rpcALREADY_MULTISIG);
|
||||
}
|
||||
|
||||
if (verify)
|
||||
{
|
||||
@@ -524,7 +540,7 @@ transactionPreProcessImpl (
|
||||
|
||||
signingArgs.moveMultiSignature (std::move (multisig));
|
||||
}
|
||||
else
|
||||
else if (signingArgs.isSingleSigning())
|
||||
{
|
||||
stpTrans->sign (keypair.first, keypair.second);
|
||||
}
|
||||
@@ -1131,6 +1147,10 @@ Json::Value transactionSubmitMultiSigned (
|
||||
return RPC::make_error (rpcINVALID_PARAMS, err.str ());
|
||||
}
|
||||
|
||||
// There may not be a TxnSignature field.
|
||||
if (stpTrans->isFieldPresent (sfTxnSignature))
|
||||
return rpcError (rpcSIGNING_MALFORMED);
|
||||
|
||||
// The Fee field must be in XRP and greater than zero.
|
||||
auto const fee = stpTrans->getFieldAmount (sfFee);
|
||||
|
||||
|
||||
@@ -855,6 +855,36 @@ R"({
|
||||
"Missing field 'tx_json.Sequence'.",
|
||||
"Missing field 'tx_json.Sequence'."}}},
|
||||
|
||||
{ "Single-sign a multisigned transaction.", __LINE__,
|
||||
R"({
|
||||
"command": "doesnt_matter",
|
||||
"account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
|
||||
"secret": "a",
|
||||
"tx_json": {
|
||||
"Account" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
|
||||
"Amount" : "1000000000",
|
||||
"Destination" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"Fee" : "50",
|
||||
"Sequence" : 0,
|
||||
"Signers" : [
|
||||
{
|
||||
"Signer" : {
|
||||
"Account" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"SigningPubKey" : "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TxnSignature" : "304502210080EB23E78A841DDC5E3A4F10DE6EAF052207D6B519BF8954467ADB221B3F349002202CA458E8D4E4DE7176D27A91628545E7B295A5DFC8ADF0B5CD3E279B6FA02998"
|
||||
}
|
||||
}
|
||||
],
|
||||
"SigningPubKey" : "",
|
||||
"TransactionType" : "Payment"
|
||||
}
|
||||
})",
|
||||
{{
|
||||
"Already multisigned.",
|
||||
"Already multisigned.",
|
||||
"Secret does not match account.",
|
||||
""}}},
|
||||
|
||||
{ "Minimal sign_for.", __LINE__,
|
||||
R"({
|
||||
"command": "doesnt_matter",
|
||||
@@ -1109,8 +1139,8 @@ R"({
|
||||
}
|
||||
})",
|
||||
{{
|
||||
"Secret does not match account.",
|
||||
"Secret does not match account.",
|
||||
"Already multisigned.",
|
||||
"Already multisigned.",
|
||||
"Duplicate Signers:Signer:Account entries (rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh) are not allowed.",
|
||||
""}}},
|
||||
|
||||
@@ -1139,8 +1169,8 @@ R"({
|
||||
}
|
||||
})",
|
||||
{{
|
||||
"Secret does not match account.",
|
||||
"Secret does not match account.",
|
||||
"Already multisigned.",
|
||||
"Already multisigned.",
|
||||
"",
|
||||
""}}},
|
||||
|
||||
@@ -1169,8 +1199,8 @@ R"({
|
||||
}
|
||||
})",
|
||||
{{
|
||||
"Secret does not match account.",
|
||||
"Secret does not match account.",
|
||||
"Already multisigned.",
|
||||
"Already multisigned.",
|
||||
"Invalid signature.",
|
||||
"Invalid signature."}}},
|
||||
|
||||
@@ -1215,6 +1245,37 @@ R"({
|
||||
"Missing field 'tx_json.TransactionType'.",
|
||||
"Missing field 'tx_json.TransactionType'."}}},
|
||||
|
||||
{ "TxnSignature in sign_for.", __LINE__,
|
||||
R"({
|
||||
"command": "doesnt_matter",
|
||||
"account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
|
||||
"secret": "c",
|
||||
"tx_json": {
|
||||
"Account" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
|
||||
"Amount" : "1000000000",
|
||||
"Destination" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"Fee" : "50",
|
||||
"Sequence" : 0,
|
||||
"Signers" : [
|
||||
{
|
||||
"Signer" : {
|
||||
"Account" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"SigningPubKey" : "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TxnSignature" : "304502210080EB23E78A841DDC5E3A4F10DE6EAF052207D6B519BF8954467ADB221B3F349002202CA458E8D4E4DE7176D27A91628545E7B295A5DFC8ADF0B5CD3E279B6FA02998"
|
||||
}
|
||||
}
|
||||
],
|
||||
"SigningPubKey" : "",
|
||||
"TxnSignature" : "304502210080EB23E78A841DDC5E3A4F10DE6EAF052207D6B519BF8954467ADB221B3F349002202CA458E8D4E4DE7176D27A91628545E7B295A5DFC8ADF0B5CD3E279B6FA02998",
|
||||
"TransactionType" : "Payment"
|
||||
}
|
||||
})",
|
||||
{{
|
||||
"Already multisigned.",
|
||||
"Already multisigned.",
|
||||
"Already single-signed.",
|
||||
"Signing of transaction is malformed."}}},
|
||||
|
||||
{ "Invalid field 'tx_json': string instead of object", __LINE__,
|
||||
R"({
|
||||
"command": "doesnt_matter",
|
||||
@@ -2337,7 +2398,8 @@ public:
|
||||
{
|
||||
std::ostringstream description;
|
||||
description << txnTest.description << " Called "
|
||||
<< get<2>(testFunc) << "()";
|
||||
<< get<2>(testFunc) << "(). Got \'"
|
||||
<< errStr << "\'";
|
||||
fail (description.str(), __FILE__, txnTest.line);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6970,10 +6970,20 @@ public:
|
||||
Json::Value exp;
|
||||
Json::Reader{}.parse (rpcCallTest.exp, exp);
|
||||
|
||||
// If there is an "error_code" field, remove it. Error codes
|
||||
// are not expected to stay stable between releases.
|
||||
got.removeMember ("error_code");
|
||||
exp.removeMember ("error_code");
|
||||
// Lambda to remove the "params[0u]:error_code" field if present.
|
||||
// Error codes are not expected to be stable between releases.
|
||||
auto rmErrorCode = [] (Json::Value& json)
|
||||
{
|
||||
if (json.isMember (jss::params) &&
|
||||
json[jss::params].isArray() &&
|
||||
json[jss::params].size() > 0 &&
|
||||
json[jss::params][0u].isObject())
|
||||
{
|
||||
json[jss::params][0u].removeMember (jss::error_code);
|
||||
}
|
||||
};
|
||||
rmErrorCode (got);
|
||||
rmErrorCode (exp);
|
||||
|
||||
// Pass if we didn't expect a throw and we got what we expected.
|
||||
if ((rpcCallTest.throwsWhat == RPCCallTestData::no_exception) &&
|
||||
|
||||
Reference in New Issue
Block a user