mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
fix: Improve multi-sign usage of simulate (#5479)
This change allows users to submit simulate requests from a multi-sign account without needing to specify the accounts that are doing the multi-signing, and fixes an error with simulate that allowed double-"signed" (both single-sign and multi-sign public keys are provided) transactions.
This commit is contained in:
@@ -720,7 +720,11 @@ class Simulate_test : public beast::unit_test::suite
|
||||
Json::Value const& tx) {
|
||||
auto result = resp[jss::result];
|
||||
checkBasicReturnValidity(
|
||||
result, tx, env.seq(alice), env.current()->fees().base * 2);
|
||||
result,
|
||||
tx,
|
||||
env.seq(alice),
|
||||
tx.isMember(jss::Signers) ? env.current()->fees().base * 2
|
||||
: env.current()->fees().base);
|
||||
|
||||
BEAST_EXPECT(result[jss::engine_result] == "tesSUCCESS");
|
||||
BEAST_EXPECT(result[jss::engine_result_code] == 0);
|
||||
@@ -762,6 +766,10 @@ class Simulate_test : public beast::unit_test::suite
|
||||
tx[jss::Account] = alice.human();
|
||||
tx[jss::TransactionType] = jss::AccountSet;
|
||||
tx[sfDomain] = newDomain;
|
||||
|
||||
// test with autofill
|
||||
testTx(env, tx, validateOutput, false);
|
||||
|
||||
tx[sfSigners] = Json::arrayValue;
|
||||
{
|
||||
Json::Value signer;
|
||||
@@ -771,7 +779,7 @@ class Simulate_test : public beast::unit_test::suite
|
||||
tx[sfSigners].append(signerOuter);
|
||||
}
|
||||
|
||||
// test with autofill
|
||||
// test with just signer accounts
|
||||
testTx(env, tx, validateOutput, false);
|
||||
|
||||
tx[sfSigningPubKey] = "";
|
||||
@@ -780,8 +788,7 @@ class Simulate_test : public beast::unit_test::suite
|
||||
// transaction requires a non-base fee
|
||||
tx[sfFee] =
|
||||
(env.current()->fees().base * 2).jsonClipped().asString();
|
||||
tx[sfSigners][0u][sfSigner][jss::SigningPubKey] =
|
||||
strHex(becky.pk().slice());
|
||||
tx[sfSigners][0u][sfSigner][jss::SigningPubKey] = "";
|
||||
tx[sfSigners][0u][sfSigner][jss::TxnSignature] = "";
|
||||
|
||||
// test without autofill
|
||||
@@ -830,11 +837,12 @@ class Simulate_test : public beast::unit_test::suite
|
||||
tx[jss::Account] = env.master.human();
|
||||
tx[jss::TransactionType] = jss::AccountSet;
|
||||
tx[sfDomain] = newDomain;
|
||||
// master key is disabled, so this is invalid
|
||||
tx[jss::SigningPubKey] = strHex(env.master.pk().slice());
|
||||
|
||||
// test with autofill
|
||||
testTx(env, tx, testSimulation);
|
||||
|
||||
tx[sfSigningPubKey] = "";
|
||||
tx[sfTxnSignature] = "";
|
||||
tx[sfSequence] = env.seq(env.master);
|
||||
tx[sfFee] = env.current()->fees().base.jsonClipped().asString();
|
||||
@@ -844,6 +852,79 @@ class Simulate_test : public beast::unit_test::suite
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testInvalidSingleAndMultiSigningTransaction()
|
||||
{
|
||||
testcase(
|
||||
"Transaction with both single-signing SigningPubKey and "
|
||||
"multi-signing Signers");
|
||||
|
||||
using namespace jtx;
|
||||
Env env(*this);
|
||||
static auto const newDomain = "123ABC";
|
||||
Account const alice("alice");
|
||||
Account const becky("becky");
|
||||
Account const carol("carol");
|
||||
env.fund(XRP(10000), alice);
|
||||
env.close();
|
||||
|
||||
// set up valid multisign
|
||||
env(signers(alice, 1, {{becky, 1}, {carol, 1}}));
|
||||
env.close();
|
||||
|
||||
{
|
||||
std::function<void(Json::Value const&, Json::Value const&)> const&
|
||||
testSimulation = [&](Json::Value const& resp,
|
||||
Json::Value const& tx) {
|
||||
auto result = resp[jss::result];
|
||||
checkBasicReturnValidity(
|
||||
result,
|
||||
tx,
|
||||
env.seq(env.master),
|
||||
env.current()->fees().base * 2);
|
||||
|
||||
BEAST_EXPECT(result[jss::engine_result] == "temINVALID");
|
||||
BEAST_EXPECT(result[jss::engine_result_code] == -277);
|
||||
BEAST_EXPECT(
|
||||
result[jss::engine_result_message] ==
|
||||
"The transaction is ill-formed.");
|
||||
|
||||
BEAST_EXPECT(
|
||||
!result.isMember(jss::meta) &&
|
||||
!result.isMember(jss::meta_blob));
|
||||
};
|
||||
|
||||
Json::Value tx;
|
||||
|
||||
tx[jss::Account] = env.master.human();
|
||||
tx[jss::TransactionType] = jss::AccountSet;
|
||||
tx[sfDomain] = newDomain;
|
||||
// master key is disabled, so this is invalid
|
||||
tx[jss::SigningPubKey] = strHex(env.master.pk().slice());
|
||||
tx[sfSigners] = Json::arrayValue;
|
||||
{
|
||||
Json::Value signer;
|
||||
signer[jss::Account] = becky.human();
|
||||
Json::Value signerOuter;
|
||||
signerOuter[sfSigner] = signer;
|
||||
tx[sfSigners].append(signerOuter);
|
||||
}
|
||||
|
||||
// test with autofill
|
||||
testTx(env, tx, testSimulation, false);
|
||||
|
||||
tx[sfTxnSignature] = "";
|
||||
tx[sfSequence] = env.seq(env.master);
|
||||
tx[sfFee] = env.current()->fees().base.jsonClipped().asString();
|
||||
tx[sfSigners][0u][sfSigner][jss::SigningPubKey] =
|
||||
strHex(becky.pk().slice());
|
||||
tx[sfSigners][0u][sfSigner][jss::TxnSignature] = "";
|
||||
|
||||
// test without autofill
|
||||
testTx(env, tx, testSimulation);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testMultisignedBadPubKey()
|
||||
{
|
||||
@@ -1117,6 +1198,7 @@ public:
|
||||
testTransactionTecFailure();
|
||||
testSuccessfulTransactionMultisigned();
|
||||
testTransactionSigningFailure();
|
||||
testInvalidSingleAndMultiSigningTransaction();
|
||||
testMultisignedBadPubKey();
|
||||
testDeleteExpiredCredentials();
|
||||
testSuccessfulTransactionNetworkID();
|
||||
|
||||
Reference in New Issue
Block a user