#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace xrpl { class AmendmentBlocked_test : public beast::unit_test::suite { void testBlockedMethods() { using namespace test::jtx; Env env{*this, envconfig([](std::unique_ptr 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