From 754f59707822bd84dde86baad0100e977380b767 Mon Sep 17 00:00:00 2001 From: tequ Date: Tue, 7 Oct 2025 16:02:02 +0900 Subject: [PATCH] Support sfSponsorSignature autofilling in Simulate RPC --- src/test/rpc/Simulate_test.cpp | 85 +++++++++++++++++++++++++++++ src/xrpld/rpc/handlers/Simulate.cpp | 7 +++ 2 files changed, 92 insertions(+) diff --git a/src/test/rpc/Simulate_test.cpp b/src/test/rpc/Simulate_test.cpp index 0a36a8a841..b5c5a8428c 100644 --- a/src/test/rpc/Simulate_test.cpp +++ b/src/test/rpc/Simulate_test.cpp @@ -592,6 +592,91 @@ 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, 2, 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] = newDomain; + tx[sfSponsor.jsonName][sfAccount.jsonName] = sponsor.human(); + tx[sfSponsor.jsonName][sfFlags.jsonName] = tfSponsorFee; + tx[sfSponsorSignature.jsonName] = Json::objectValue; + + // 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 diff --git a/src/xrpld/rpc/handlers/Simulate.cpp b/src/xrpld/rpc/handlers/Simulate.cpp index 35cb7587d4..56e87d3d29 100644 --- a/src/xrpld/rpc/handlers/Simulate.cpp +++ b/src/xrpld/rpc/handlers/Simulate.cpp @@ -149,6 +149,13 @@ autofillTx(Json::Value& tx_json, RPC::JsonContext& context) if (auto error = autofillSignature(tx_json)) return *error; + if (tx_json.isMember(sfSponsorSignature.jsonName)) + { + if (auto error = + autofillSignature(tx_json[sfSponsorSignature.jsonName])) + return *error; + } + if (!tx_json.isMember(jss::Sequence)) { auto const seq = getAutofillSequence(tx_json, context);