diff --git a/src/ripple/app/paths/impl/PaySteps.cpp b/src/ripple/app/paths/impl/PaySteps.cpp index d05aec4a8a..ae43ecaf35 100644 --- a/src/ripple/app/paths/impl/PaySteps.cpp +++ b/src/ripple/app/paths/impl/PaySteps.cpp @@ -400,6 +400,12 @@ toStrandV2 ( !isConsistent(deliver) || (sendMaxIssue && !isConsistent(*sendMaxIssue))) return {temBAD_PATH, Strand{}}; + if ((sendMaxIssue && sendMaxIssue->account == noAccount()) || + (src == noAccount()) || + (dst == noAccount()) || + (deliver.account == noAccount())) + return {temBAD_PATH, Strand{}}; + for (auto const& pe : path) { auto const t = pe.getNodeType(); @@ -423,6 +429,12 @@ toStrandV2 ( if (hasCurrency && hasIssuer && isXRP(pe.getCurrency()) != isXRP(pe.getIssuerID())) return {temBAD_PATH, Strand{}}; + + if (hasIssuer && (pe.getIssuerID() == noAccount())) + return {temBAD_PATH, Strand{}}; + + if (hasAccount && (pe.getAccountID() == noAccount())) + return {temBAD_PATH, Strand{}}; } Issue curIssue = [&] diff --git a/src/test/app/PayStrand_test.cpp b/src/test/app/PayStrand_test.cpp index 425250aabd..867b8cb594 100644 --- a/src/test/app/PayStrand_test.cpp +++ b/src/test/app/PayStrand_test.cpp @@ -1415,6 +1415,63 @@ struct PayStrand_test : public beast::unit_test::suite } } + void + testNoAccount(std::initializer_list fs) + { + testcase("test no account"); + using namespace jtx; + + auto const alice = Account("alice"); + auto const bob = Account("bob"); + auto const gw = Account("gw"); + auto const USD = gw["USD"]; + + Env env(*this, features(fs)); + env.fund(XRP(10000), alice, bob, gw); + + STAmount sendMax{USD.issue(), 100, 1}; + STAmount noAccountAmount{Issue{USD.currency, noAccount()}, 100, 1}; + STAmount deliver; + AccountID const srcAcc = alice.id(); + AccountID dstAcc = bob.id(); + STPathSet pathSet; + ::ripple::path::RippleCalc::Input inputs; + inputs.defaultPathsAllowed = true; + try + { + PaymentSandbox sb{env.current().get(), tapNONE}; + { + auto const r = ::ripple::path::RippleCalc::rippleCalculate( + sb, sendMax, deliver, dstAcc, noAccount(), pathSet, + env.app().logs(), &inputs); + BEAST_EXPECT(r.result() == temBAD_PATH); + } + { + auto const r = ::ripple::path::RippleCalc::rippleCalculate( + sb, sendMax, deliver, noAccount(), srcAcc, pathSet, + env.app().logs(), &inputs); + BEAST_EXPECT(r.result() == temBAD_PATH); + } + { + auto const r = ::ripple::path::RippleCalc::rippleCalculate( + sb, noAccountAmount, deliver, dstAcc, srcAcc, pathSet, + env.app().logs(), &inputs); + BEAST_EXPECT(r.result() == temBAD_PATH); + } + + { + auto const r = ::ripple::path::RippleCalc::rippleCalculate( + sb, sendMax, noAccountAmount, dstAcc, srcAcc, pathSet, + env.app().logs(), &inputs); + BEAST_EXPECT(r.result() == temBAD_PATH); + } + } + catch (...) + { + this->fail(); + } + } + void run() override { @@ -1430,6 +1487,7 @@ struct PayStrand_test : public beast::unit_test::suite testLoop({featureFlow}); testLoop({featureFlow, fix1373}); testLoop({featureFlow, fix1373, featureFlowCross}); + testNoAccount({featureFlow, fix1373}); } };