diff --git a/src/ripple/rpc/handlers/AccountChannels.cpp b/src/ripple/rpc/handlers/AccountChannels.cpp index 08c3d87ee..6614561e0 100644 --- a/src/ripple/rpc/handlers/AccountChannels.cpp +++ b/src/ripple/rpc/handlers/AccountChannels.cpp @@ -148,14 +148,13 @@ Json::Value doAccountChannels (RPC::JsonContext& context) if (!forEachItemAfter(*ledger, accountID, startAfter, startHint, limit-visitData.items.size()+1, - [&visitData](std::shared_ptr const& sleCur) - { - - if (sleCur && sleCur->getType () == ltPAYCHAN && - (! visitData.hasDst || + [&visitData, &accountID](std::shared_ptr const& sleCur) { + if (sleCur && sleCur->getType() == ltPAYCHAN && + (*sleCur)[sfAccount] == accountID && + (!visitData.hasDst || visitData.raDstAccount == (*sleCur)[sfDestination])) { - visitData.items.emplace_back (sleCur); + visitData.items.emplace_back(sleCur); return true; } diff --git a/src/test/app/PayChan_test.cpp b/src/test/app/PayChan_test.cpp index 208b718ec..22764086d 100644 --- a/src/test/app/PayChan_test.cpp +++ b/src/test/app/PayChan_test.cpp @@ -887,7 +887,6 @@ struct PayChan_test : public beast::unit_test::suite env(create(alice, bob, channelFunds, settleDelay, pk)); env.close(); auto const chan1Str = to_string(channel(*env.current(), alice, bob)); - std::string chan1PkStr; { auto const r = env.rpc("account_channels", alice.human(), bob.human()); @@ -895,8 +894,6 @@ struct PayChan_test : public beast::unit_test::suite BEAST_EXPECT( r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str); BEAST_EXPECT(r[jss::result][jss::validated]); - chan1PkStr = - r[jss::result][jss::channels][0u][jss::public_key].asString(); } { auto const r = env.rpc("account_channels", alice.human()); @@ -904,8 +901,6 @@ struct PayChan_test : public beast::unit_test::suite BEAST_EXPECT( r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str); BEAST_EXPECT(r[jss::result][jss::validated]); - chan1PkStr = - r[jss::result][jss::channels][0u][jss::public_key].asString(); } { auto const r = @@ -1046,6 +1041,41 @@ struct PayChan_test : public beast::unit_test::suite } } + void + testAccountChannelsRPCSenderOnly() + { + // Check that the account_channels command only returns channels owned by the account + testcase("Account channels RPC owner only"); + + using namespace test::jtx; + using namespace std::literals; + + + auto const alice = Account("alice"); + auto const bob = Account("bob"); + Env env(*this); + env.fund(XRP(10000), alice, bob); + + // Create a channel from alice to bob and from bob to alice + // When retrieving alice's channels, it should only retrieve the + // channels where alice is the source, not the destination + auto const settleDelay = 3600s; + auto const channelFunds = XRP (1000); + env(create(alice, bob, channelFunds, settleDelay, alice.pk())); + env(create(bob, alice, channelFunds, settleDelay, bob.pk())); + + auto const r = [&]{ + Json::Value jvc; + jvc[jss::account] = alice.human(); + + return env.rpc( + "json", "account_channels", to_string(jvc))[jss::result]; + }(); + BEAST_EXPECT(r.isMember(jss::channels)); + BEAST_EXPECT(r[jss::channels].size() == 1); + BEAST_EXPECT(r[jss::channels][0u][jss::destination_account].asString() == bob.human()); + } + void testAuthVerifyRPC () { @@ -1814,6 +1844,7 @@ struct PayChan_test : public beast::unit_test::suite testMultiple(); testAccountChannelsRPC(); testAccountChannelsRPCMarkers(); + testAccountChannelsRPCSenderOnly(); testAuthVerifyRPC(); testOptionalFields(); testMalformedPK();