Files
rippled/src/test/rpc/AmendmentBlocked_test.cpp
2026-04-17 16:43:49 +00:00

238 lines
9.0 KiB
C++

#include <test/jtx/Env.h>
#include <test/jtx/WSClient.h>
#include <test/jtx/amount.h>
#include <test/jtx/envconfig.h>
#include <test/jtx/multisign.h>
#include <test/jtx/noop.h>
#include <test/jtx/pay.h>
#include <test/jtx/regkey.h>
#include <test/jtx/sig.h>
#include <xrpld/core/Config.h>
#include <xrpld/core/ConfigSections.h>
#include <xrpl/basics/strHex.h>
#include <xrpl/beast/unit_test/suite.h>
#include <xrpl/json/to_string.h>
#include <xrpl/protocol/KeyType.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/server/NetworkOPs.h>
#include <memory>
namespace xrpl {
class AmendmentBlocked_test : public beast::unit_test::suite
{
void
testBlockedMethods()
{
using namespace test::jtx;
Env env{*this, envconfig([](std::unique_ptr<Config> cfg) {
cfg->loadFromString("[" SECTION_SIGNING_SUPPORT "]\ntrue");
return cfg;
})};
auto const gw = Account{"gateway"};
auto const USD = gw["USD"];
auto const alice = Account{"alice"};
auto const bob = Account{"bob"};
Account const ali{"ali", KeyType::secp256k1};
env.fund(XRP(10000), alice, bob, gw);
env.memoize(ali);
// This close() ensures that all the accounts get created and their
// default ripple flag gets set before the trust lines are created.
// Without it, the ordering manages to create alice's trust line with
// noRipple set on gw's end. The existing tests pass either way, but
// better to do it right.
env.close();
env.trust(USD(600), alice);
env.trust(USD(700), bob);
env(pay(gw, alice, USD(70)));
env(pay(gw, bob, USD(50)));
env.close();
auto wsc = test::makeWSClient(env.app().config());
auto current = env.current();
// ledger_accept
auto jr = env.rpc("ledger_accept")[jss::result];
BEAST_EXPECT(jr[jss::ledger_current_index] == current->seq() + 1);
BEAST_EXPECT(!jr.isMember(jss::warnings));
// ledger_current
jr = env.rpc("ledger_current")[jss::result];
BEAST_EXPECT(jr[jss::ledger_current_index] == current->seq() + 1);
BEAST_EXPECT(!jr.isMember(jss::warnings));
// owner_info
jr = env.rpc("owner_info", alice.human())[jss::result];
BEAST_EXPECT(jr.isMember(jss::accepted) && jr.isMember(jss::current));
BEAST_EXPECT(!jr.isMember(jss::warnings));
// path_find
Json::Value pf_req;
pf_req[jss::subcommand] = "create";
pf_req[jss::source_account] = alice.human();
pf_req[jss::destination_account] = bob.human();
pf_req[jss::destination_amount] = bob["USD"](20).value().getJson(JsonOptions::none);
jr = wsc->invoke("path_find", pf_req)[jss::result];
BEAST_EXPECT(
jr.isMember(jss::alternatives) && jr[jss::alternatives].isArray() &&
jr[jss::alternatives].size() == 1);
BEAST_EXPECT(!jr.isMember(jss::warnings));
// submit
auto jt = env.jt(noop(alice));
Serializer s;
jt.stx->add(s);
jr = env.rpc("submit", strHex(s.slice()))[jss::result];
BEAST_EXPECT(jr.isMember(jss::engine_result) && jr[jss::engine_result] == "tesSUCCESS");
BEAST_EXPECT(!jr.isMember(jss::warnings));
// submit_multisigned
env(signers(bob, 1, {{alice, 1}}), sig(bob));
env(regkey(alice, ali));
env.close();
Json::Value set_tx;
set_tx[jss::Account] = bob.human();
set_tx[jss::TransactionType] = jss::AccountSet;
set_tx[jss::Fee] = (8 * env.current()->fees().base).jsonClipped();
set_tx[jss::Sequence] = env.seq(bob);
set_tx[jss::SigningPubKey] = "";
Json::Value sign_for;
sign_for[jss::tx_json] = set_tx;
sign_for[jss::account] = alice.human();
sign_for[jss::secret] = ali.name();
jr = env.rpc("json", "sign_for", to_string(sign_for))[jss::result];
BEAST_EXPECT(jr[jss::status] == "success");
BEAST_EXPECT(!jr.isMember(jss::warnings));
Json::Value ms_req;
ms_req[jss::tx_json] = jr[jss::tx_json];
jr = env.rpc("json", "submit_multisigned", to_string(ms_req))[jss::result];
BEAST_EXPECT(jr.isMember(jss::engine_result) && jr[jss::engine_result] == "tesSUCCESS");
BEAST_EXPECT(!jr.isMember(jss::warnings));
// set up an amendment warning. Nothing changes
env.app().getOPs().setAmendmentWarned();
current = env.current();
// ledger_accept
jr = env.rpc("ledger_accept")[jss::result];
BEAST_EXPECT(jr[jss::ledger_current_index] == current->seq() + 1);
BEAST_EXPECT(!jr.isMember(jss::warnings));
// ledger_current
jr = env.rpc("ledger_current")[jss::result];
BEAST_EXPECT(jr[jss::ledger_current_index] == current->seq() + 1);
BEAST_EXPECT(!jr.isMember(jss::warnings));
// owner_info
jr = env.rpc("owner_info", alice.human())[jss::result];
BEAST_EXPECT(jr.isMember(jss::accepted) && jr.isMember(jss::current));
BEAST_EXPECT(!jr.isMember(jss::warnings));
// path_find
pf_req[jss::subcommand] = "create";
pf_req[jss::source_account] = alice.human();
pf_req[jss::destination_account] = bob.human();
pf_req[jss::destination_amount] = bob["USD"](20).value().getJson(JsonOptions::none);
jr = wsc->invoke("path_find", pf_req)[jss::result];
BEAST_EXPECT(
jr.isMember(jss::alternatives) && jr[jss::alternatives].isArray() &&
jr[jss::alternatives].size() == 1);
BEAST_EXPECT(!jr.isMember(jss::warnings));
// submit
jt = env.jt(noop(alice));
s.erase();
jt.stx->add(s);
jr = env.rpc("submit", strHex(s.slice()))[jss::result];
BEAST_EXPECT(jr.isMember(jss::engine_result) && jr[jss::engine_result] == "tesSUCCESS");
BEAST_EXPECT(!jr.isMember(jss::warnings));
// submit_multisigned
env(signers(bob, 1, {{alice, 1}}), sig(bob));
env(regkey(alice, ali));
env.close();
set_tx[jss::Account] = bob.human();
set_tx[jss::TransactionType] = jss::AccountSet;
set_tx[jss::Fee] = (8 * env.current()->fees().base).jsonClipped();
set_tx[jss::Sequence] = env.seq(bob);
set_tx[jss::SigningPubKey] = "";
sign_for[jss::tx_json] = set_tx;
sign_for[jss::account] = alice.human();
sign_for[jss::secret] = ali.name();
jr = env.rpc("json", "sign_for", to_string(sign_for))[jss::result];
BEAST_EXPECT(jr[jss::status] == "success");
BEAST_EXPECT(!jr.isMember(jss::warnings));
ms_req[jss::tx_json] = jr[jss::tx_json];
jr = env.rpc("json", "submit_multisigned", to_string(ms_req))[jss::result];
BEAST_EXPECT(jr.isMember(jss::engine_result) && jr[jss::engine_result] == "tesSUCCESS");
BEAST_EXPECT(!jr.isMember(jss::warnings));
// make the network amendment blocked...now all the same
// requests should fail
env.app().getOPs().setAmendmentBlocked();
// ledger_accept
jr = env.rpc("ledger_accept")[jss::result];
BEAST_EXPECT(jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked");
BEAST_EXPECT(jr[jss::status] == "error");
BEAST_EXPECT(!jr.isMember(jss::warnings));
// ledger_current
jr = env.rpc("ledger_current")[jss::result];
BEAST_EXPECT(jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked");
BEAST_EXPECT(jr[jss::status] == "error");
BEAST_EXPECT(!jr.isMember(jss::warnings));
// owner_info
jr = env.rpc("owner_info", alice.human())[jss::result];
BEAST_EXPECT(jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked");
BEAST_EXPECT(jr[jss::status] == "error");
BEAST_EXPECT(!jr.isMember(jss::warnings));
// path_find
jr = wsc->invoke("path_find", pf_req)[jss::result];
BEAST_EXPECT(jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked");
BEAST_EXPECT(jr[jss::status] == "error");
BEAST_EXPECT(!jr.isMember(jss::warnings));
// submit
jr = env.rpc("submit", strHex(s.slice()))[jss::result];
BEAST_EXPECT(jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked");
BEAST_EXPECT(jr[jss::status] == "error");
BEAST_EXPECT(!jr.isMember(jss::warnings));
// submit_multisigned
set_tx[jss::Sequence] = env.seq(bob);
sign_for[jss::tx_json] = set_tx;
jr = env.rpc("json", "sign_for", to_string(sign_for))[jss::result];
BEAST_EXPECT(jr[jss::status] == "success");
ms_req[jss::tx_json] = jr[jss::tx_json];
jr = env.rpc("json", "submit_multisigned", to_string(ms_req))[jss::result];
BEAST_EXPECT(jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked");
BEAST_EXPECT(!jr.isMember(jss::warnings));
}
public:
void
run() override
{
testBlockedMethods();
}
};
BEAST_DEFINE_TESTSUITE(AmendmentBlocked, rpc, xrpl);
} // namespace xrpl