mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-29 01:50:43 +00:00
Co-authored-by: tequ <git@tequ.dev> Co-authored-by: yinyiqian1 <yqian@ripple.com> Co-authored-by: Mayukha Vadari <mvadari@ripple.com> Co-authored-by: Mayukha Vadari <mvadari@gmail.com> Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com> Co-authored-by: Peter Chen <34582813+PeterChen13579@users.noreply.github.com> Co-authored-by: Zhiyuan Wang <96991820+Kassaking7@users.noreply.github.com> Co-authored-by: Ayaz Salikhov <asalikhov@ripple.com> Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com> Co-authored-by: Zhiyuan Wang <1830604455@qq.com>
This commit is contained in:
@@ -364,6 +364,37 @@ class Simulate_test : public beast::unit_test::Suite
|
||||
auto const resp = env.rpc("json", "simulate", to_string(params));
|
||||
BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'tx.Signers[0]'.");
|
||||
}
|
||||
{
|
||||
// Non-object SponsorSignature field
|
||||
json::Value params;
|
||||
json::Value txJson = json::ValueType::Object;
|
||||
txJson[jss::TransactionType] = jss::AccountSet;
|
||||
txJson[jss::Account] = env.master.human();
|
||||
txJson[sfSponsorSignature] = "";
|
||||
params[jss::tx_json] = txJson;
|
||||
|
||||
auto const resp = env.rpc("json", "simulate", to_string(params));
|
||||
BEAST_EXPECT(
|
||||
resp[jss::result][jss::error_message] ==
|
||||
"Invalid field 'SponsorSignature', not object.");
|
||||
}
|
||||
{
|
||||
// Invalid SponsorSignature.Signers field
|
||||
json::Value params;
|
||||
json::Value txJson = json::ValueType::Object;
|
||||
txJson[jss::TransactionType] = jss::AccountSet;
|
||||
txJson[jss::Account] = env.master.human();
|
||||
json::Value sponsorSignature = json::ValueType::Object;
|
||||
sponsorSignature[sfSigners] = "1";
|
||||
txJson[sfSponsorSignature] = sponsorSignature;
|
||||
params[jss::tx_json] = txJson;
|
||||
|
||||
auto const resp = env.rpc("json", "simulate", to_string(params));
|
||||
BEAST_EXPECTS(
|
||||
resp[jss::result][jss::error_message] ==
|
||||
"Invalid field 'tx.SponsorSignature.Signers'.",
|
||||
resp.toStyledString());
|
||||
}
|
||||
{
|
||||
// Invalid transaction
|
||||
json::Value params;
|
||||
@@ -561,6 +592,75 @@ class Simulate_test : public beast::unit_test::Suite
|
||||
// test without autofill
|
||||
testTx(env, tx, validateOutput);
|
||||
}
|
||||
|
||||
{
|
||||
// autofill sponsor signature
|
||||
|
||||
auto validateOutput = [&](json::Value const& resp, json::Value const& tx) {
|
||||
auto result = resp[jss::result];
|
||||
checkBasicReturnValidity(
|
||||
result, tx, env.seq(env.master), env.current()->fees().base);
|
||||
|
||||
BEAST_EXPECT(result[jss::engine_result] == "tesSUCCESS");
|
||||
BEAST_EXPECT(result[jss::engine_result_code] == 0);
|
||||
BEAST_EXPECT(
|
||||
result[jss::engine_result_message] ==
|
||||
"The simulated transaction would have been applied.");
|
||||
|
||||
if (BEAST_EXPECT(result.isMember(jss::meta) || result.isMember(jss::meta_blob)))
|
||||
{
|
||||
json::Value const metadata = getJsonMetadata(result);
|
||||
|
||||
if (BEAST_EXPECT(metadata.isMember(sfAffectedNodes.jsonName)))
|
||||
{
|
||||
BEAST_EXPECT(metadata[sfAffectedNodes.jsonName].size() == 2);
|
||||
|
||||
auto node = metadata[sfAffectedNodes.jsonName][0u];
|
||||
if (BEAST_EXPECT(node.isMember(sfModifiedNode.jsonName)))
|
||||
{
|
||||
auto modifiedNode = node[sfModifiedNode];
|
||||
BEAST_EXPECT(modifiedNode[sfLedgerEntryType] == "AccountRoot");
|
||||
auto previousFields = modifiedNode[sfPreviousFields];
|
||||
BEAST_EXPECT(!previousFields.isMember(sfBalance.jsonName));
|
||||
}
|
||||
|
||||
auto node2 = metadata[sfAffectedNodes.jsonName][1u];
|
||||
if (BEAST_EXPECT(node2.isMember(sfModifiedNode.jsonName)))
|
||||
{
|
||||
auto modifiedNode = node2[sfModifiedNode];
|
||||
BEAST_EXPECT(modifiedNode[sfLedgerEntryType] == "AccountRoot");
|
||||
|
||||
auto previousFields = modifiedNode[sfPreviousFields];
|
||||
BEAST_EXPECT(previousFields.isMember(sfBalance.jsonName));
|
||||
}
|
||||
}
|
||||
BEAST_EXPECT(metadata[sfTransactionIndex.jsonName] == 0);
|
||||
BEAST_EXPECT(metadata[sfTransactionResult.jsonName] == "tesSUCCESS");
|
||||
}
|
||||
};
|
||||
|
||||
Account const sponsor("sponsor");
|
||||
env.fund(XRP(10000), sponsor);
|
||||
env.close();
|
||||
|
||||
json::Value tx;
|
||||
|
||||
tx[jss::Account] = env.master.human();
|
||||
tx[jss::TransactionType] = jss::AccountSet;
|
||||
tx[sfDomain.jsonName] = kNewDomain;
|
||||
tx[sfSponsor.jsonName] = sponsor.human();
|
||||
tx[sfSponsorFlags.jsonName] = spfSponsorFee;
|
||||
tx[sfSponsorSignature.jsonName] = json::ValueType::Object;
|
||||
|
||||
// test with autofill
|
||||
testTx(env, tx, validateOutput);
|
||||
|
||||
tx[sfSponsorSignature.jsonName][sfTxnSignature.jsonName] = "";
|
||||
tx[sfSponsorSignature.jsonName][sfSigningPubKey.jsonName] = "";
|
||||
|
||||
// test without autofill
|
||||
testTx(env, tx, validateOutput);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -763,6 +863,58 @@ class Simulate_test : public beast::unit_test::Suite
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testSuccessfulSponsoredTransactionMultisigned()
|
||||
{
|
||||
testcase("Successful sponsored multi-signed transaction");
|
||||
|
||||
using namespace jtx;
|
||||
Env env(*this);
|
||||
Account const sponsor("sponsor");
|
||||
Account const signer("signer");
|
||||
env.fund(XRP(10000), sponsor, signer);
|
||||
env.close();
|
||||
|
||||
env(signers(sponsor, 1, {{signer, 1}}));
|
||||
env.close();
|
||||
|
||||
auto validateOutput = [&](json::Value const& resp, json::Value const& tx) {
|
||||
auto const result = resp[jss::result];
|
||||
// Verifies Fee autofill counts nested sponsor-signature signers.
|
||||
auto const expectedFee = env.current()->fees().base * 2;
|
||||
checkBasicReturnValidity(result, tx, env.seq(env.master), expectedFee);
|
||||
|
||||
BEAST_EXPECT(result[jss::engine_result] == "tesSUCCESS");
|
||||
BEAST_EXPECT(result[jss::engine_result_code] == 0);
|
||||
BEAST_EXPECT(
|
||||
result[jss::engine_result_message] ==
|
||||
"The simulated transaction would have been applied.");
|
||||
|
||||
if (BEAST_EXPECT(result.isMember(jss::meta) || result.isMember(jss::meta_blob)))
|
||||
{
|
||||
json::Value const metadata = getJsonMetadata(result);
|
||||
BEAST_EXPECT(metadata[sfTransactionResult.jsonName] == "tesSUCCESS");
|
||||
}
|
||||
};
|
||||
|
||||
json::Value tx;
|
||||
tx[jss::Account] = env.master.human();
|
||||
tx[jss::TransactionType] = jss::AccountSet;
|
||||
tx[sfDomain] = "123ABC";
|
||||
tx[sfSponsor.jsonName] = sponsor.human();
|
||||
tx[sfSponsorFlags.jsonName] = spfSponsorFee;
|
||||
tx[sfSponsorSignature.jsonName] = json::ValueType::Object;
|
||||
tx[sfSponsorSignature.jsonName][sfSigners.jsonName] = json::ValueType::Array;
|
||||
|
||||
json::Value signerObj;
|
||||
signerObj[sfSigner][jss::Account] = signer.human();
|
||||
tx[sfSponsorSignature.jsonName][sfSigners.jsonName].append(signerObj);
|
||||
|
||||
// Leave Fee unset so simulate must autofill it after sponsor signer normalization.
|
||||
BEAST_EXPECT(!tx.isMember(jss::Fee));
|
||||
testTx(env, tx, validateOutput, false);
|
||||
}
|
||||
|
||||
void
|
||||
testTransactionSigningFailure()
|
||||
{
|
||||
@@ -1195,6 +1347,7 @@ public:
|
||||
testTransactionNonTecFailure();
|
||||
testTransactionTecFailure();
|
||||
testSuccessfulTransactionMultisigned();
|
||||
testSuccessfulSponsoredTransactionMultisigned();
|
||||
testTransactionSigningFailure();
|
||||
testInvalidSingleAndMultiSigningTransaction();
|
||||
testMultisignedBadPubKey();
|
||||
|
||||
Reference in New Issue
Block a user