From 4f94f07b2b16e63f461689f2fe5aded919c8779f Mon Sep 17 00:00:00 2001 From: dangell7 Date: Sun, 1 Jan 2023 22:46:57 -0500 Subject: [PATCH] add ic signClaim --- src/test/app/PayChan_test.cpp | 256 ++++++++++++++++++++++++++++++---- 1 file changed, 225 insertions(+), 31 deletions(-) diff --git a/src/test/app/PayChan_test.cpp b/src/test/app/PayChan_test.cpp index cf600a9fc..99dcf4526 100644 --- a/src/test/app/PayChan_test.cpp +++ b/src/test/app/PayChan_test.cpp @@ -63,7 +63,29 @@ struct PayChan_test : public beast::unit_test::suite STAmount const& authAmt) { Serializer msg; - serializePayChanAuthorization(msg, channel, authAmt.xrp()); + serializePayChanAuthorization( + msg, + channel, + authAmt.xrp() + ); + return sign(pk, sk, msg.slice()); + } + + static Buffer + signClaimICAuth( + PublicKey const& pk, + SecretKey const& sk, + uint256 const& channel, + STAmount const& authAmt) + { + Serializer msg; + serializePayChanAuthorization( + msg, + channel, + authAmt.iou(), + authAmt.getCurrency(), + authAmt.getIssuer() + ); return sign(pk, sk, msg.slice()); } @@ -92,6 +114,13 @@ struct PayChan_test : public beast::unit_test::suite return (*slep)[sfAmount]; } + static STAmount + lockedAmount(jtx::Env const& env, jtx::Account const& account, jtx::Account const& gw, jtx::IOU const& iou) + { + auto const tl = env.le(keylet::line(account, gw, iou.currency)); + return (*tl)[sfLockedBalance]; + } + static std::optional channelExpiration(ReadView const& view, uint256 const& chan) { @@ -175,9 +204,9 @@ struct PayChan_test : public beast::unit_test::suite } void - testSimple() + testNSimple() { - testcase("simple"); + testcase("nsimple"); using namespace jtx; using namespace std::literals::chrono_literals; Env env(*this); @@ -205,10 +234,7 @@ struct PayChan_test : public beast::unit_test::suite BEAST_EXPECT(chanAmt == XRP(2000)); { - // bad amounts (non-xrp, negative amounts) - env(create(alice, bob, USDA(1000), settleDelay, pk), - ter(temBAD_AMOUNT)); - env(fund(alice, chan, USDA(1000)), ter(temBAD_AMOUNT)); + // bad amounts (negative amounts) env(create(alice, bob, XRP(-1000), settleDelay, pk), ter(temBAD_AMOUNT)); env(fund(alice, chan, XRP(-1000)), ter(temBAD_AMOUNT)); @@ -231,13 +257,9 @@ struct PayChan_test : public beast::unit_test::suite env(create(alice, bob, XRP(10000), settleDelay, pk), ter(tecUNFUNDED)); { - // No signature claim with bad amounts (negative and non-xrp) - auto const iou = USDA(100).value(); + // No signature claim with bad amounts (negative) auto const negXRP = XRP(-100).value(); auto const posXRP = XRP(100).value(); - env(claim(alice, chan, iou, iou), ter(temBAD_AMOUNT)); - env(claim(alice, chan, posXRP, iou), ter(temBAD_AMOUNT)); - env(claim(alice, chan, iou, posXRP), ter(temBAD_AMOUNT)); env(claim(alice, chan, negXRP, negXRP), ter(temBAD_AMOUNT)); env(claim(alice, chan, posXRP, negXRP), ter(temBAD_AMOUNT)); env(claim(alice, chan, negXRP, posXRP), ter(temBAD_AMOUNT)); @@ -349,6 +371,177 @@ struct PayChan_test : public beast::unit_test::suite } } + void + testICSimple() + { + testcase("icsimple"); + using namespace jtx; + using namespace std::literals::chrono_literals; + Env env(*this); + auto const gw = Account{"gateway"}; + auto const USD = gw["USD"]; + + auto const alice = Account("alice"); + auto const bob = Account("bob"); + env.fund(XRP(10000), alice, bob, gw); + env.trust(USD(100000), alice, bob); + env(pay(gw, alice, USD(10000))); + + auto const pk = alice.pk(); + auto const settleDelay = 100s; + auto const chan = channel(alice, bob, env.seq(alice)); + env(create(alice, bob, USD(1000), settleDelay, pk)); + BEAST_EXPECT(channelBalance(*env.current(), chan) == USD(0)); + BEAST_EXPECT(channelAmount(*env.current(), chan) == USD(1000)); + + { + auto const preAlice = lockedAmount(env, alice, gw, USD); + env(fund(alice, chan, USD(1000))); + auto const postAlice = lockedAmount(env, alice, gw, USD); + BEAST_EXPECT(postAlice == preAlice - USD(1000)); + } + + auto chanBal = channelBalance(*env.current(), chan); + auto chanAmt = channelAmount(*env.current(), chan); + BEAST_EXPECT(chanBal == USD(0)); + BEAST_EXPECT(chanAmt == USD(2000)); + + { + // bad amounts (negative amounts) + env(create(alice, bob, USD(-1000), settleDelay, pk), + ter(temBAD_AMOUNT)); + env(fund(alice, chan, USD(-1000)), ter(temBAD_AMOUNT)); + } + + // invalid account + env(create(alice, "noAccount", USD(1000), settleDelay, pk), + ter(tecNO_DST)); + // can't create channel to the same account + env(create(alice, alice, USD(1000), settleDelay, pk), + ter(temDST_IS_SRC)); + // invalid channel + + env(fund( + alice, + channel(alice, "noAccount", env.seq(alice) - 1), + USD(1000)), + ter(tecNO_ENTRY)); + // not enough funds + env(create(alice, bob, USD(10000), settleDelay, pk), ter(tecUNFUNDED_PAYMENT)); + + { + // No signature claim with bad amounts (negative) + auto const negIC = USD(-100).value(); + auto const posIC = USD(100).value(); + env(claim(alice, chan, negIC, negIC), ter(temBAD_AMOUNT)); + env(claim(alice, chan, posIC, negIC), ter(temBAD_AMOUNT)); + env(claim(alice, chan, negIC, posIC), ter(temBAD_AMOUNT)); + } + { + // No signature claim more than authorized + auto const delta = USD(500); + auto const reqBal = chanBal + delta; + auto const authAmt = reqBal + USD(-100); + assert(reqBal <= chanAmt); + env(claim(alice, chan, reqBal, authAmt), ter(temBAD_AMOUNT)); + } + { + // No signature needed since the owner is claiming + auto const preBob = env.balance(bob, USD.issue()); + auto const delta = USD(500); + auto const reqBal = chanBal + delta; + auto const authAmt = reqBal + USD(100); + assert(reqBal <= chanAmt); + env(claim(alice, chan, reqBal, authAmt)); + BEAST_EXPECT(channelBalance(*env.current(), chan) == reqBal); + BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt); + BEAST_EXPECT(env.balance(bob, USD.issue()) == preBob + delta); + chanBal = reqBal; + } + { + // Claim with signature + auto preBob = env.balance(bob, USD.issue()); + auto const delta = USD(500); + auto const reqBal = chanBal + delta; + auto const authAmt = reqBal + USD(100); + assert(reqBal <= chanAmt); + auto const sig = + signClaimICAuth(alice.pk(), alice.sk(), chan, authAmt); + env(claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk())); + BEAST_EXPECT(channelBalance(*env.current(), chan) == reqBal); + BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt); + BEAST_EXPECT(env.balance(bob, USD.issue()) == preBob + delta); + chanBal = reqBal; + + // claim again + preBob = env.balance(bob, USD.issue()); + env(claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk()), + ter(tecUNFUNDED_PAYMENT)); + BEAST_EXPECT(channelBalance(*env.current(), chan) == chanBal); + BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt); + BEAST_EXPECT(env.balance(bob, USD.issue()) == preBob); + } + // { + // // Try to claim more than authorized + // auto const preBob = env.balance(bob, USD.issue()); + // STAmount const authAmt = chanBal + USD(500); + // STAmount const reqAmt = authAmt + STAmount{1}; + // assert(reqAmt <= chanAmt); + // auto const sig = + // signClaimICAuth(alice.pk(), alice.sk(), chan, authAmt); + // env(claim(bob, chan, reqAmt, authAmt, Slice(sig), alice.pk()), + // ter(temBAD_AMOUNT)); + // BEAST_EXPECT(channelBalance(*env.current(), chan) == chanBal); + // BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt); + // BEAST_EXPECT(env.balance(bob, USD.issue()) == preBob); + // } + + // // Dst tries to fund the channel + // env(fund(bob, chan, USD(1000)), ter(tecNO_PERMISSION)); + // BEAST_EXPECT(channelBalance(*env.current(), chan) == chanBal); + // BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt); + + // { + // // Wrong signing key + // auto const sig = signClaimICAuth(bob.pk(), bob.sk(), chan, USD(1500)); + // env(claim( + // bob, + // chan, + // USD(1500).value(), + // USD(1500).value(), + // Slice(sig), + // bob.pk()), + // ter(temBAD_SIGNER)); + // BEAST_EXPECT(channelBalance(*env.current(), chan) == chanBal); + // BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt); + // } + // { + // // Bad signature + // auto const sig = signClaimICAuth(bob.pk(), bob.sk(), chan, USD(1500)); + // env(claim( + // bob, + // chan, + // USD(1500).value(), + // USD(1500).value(), + // Slice(sig), + // alice.pk()), + // ter(temBAD_SIGNATURE)); + // BEAST_EXPECT(channelBalance(*env.current(), chan) == chanBal); + // BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt); + // } + // { + // // Dst closes channel + // auto const preAlice = env.balance(alice, USD.issue()); + // auto const preBob = env.balance(bob, USD.issue()); + // env(claim(bob, chan), txflags(tfClose)); + // BEAST_EXPECT(!channelExists(*env.current(), chan)); + // auto const delta = chanAmt - chanBal; + // assert(delta > beast::zero); + // BEAST_EXPECT(env.balance(alice, USD.issue()) == preAlice + delta); + // BEAST_EXPECT(env.balance(bob, USD.issue()) == preBob); + // } + } + void testCancelAfter() { @@ -2042,25 +2235,26 @@ struct PayChan_test : public beast::unit_test::suite void run() override { - testSimple(); - testCancelAfter(); - testSettleDelay(); - testExpiration(); - testCloseDry(); - testDefaultAmount(); - testDisallowXRP(); - testDstTag(); - testDepositAuth(); - testMultiple(); - testAccountChannelsRPC(); - testAccountChannelsRPCMarkers(); - testAccountChannelsRPCSenderOnly(); - testAuthVerifyRPC(); - testOptionalFields(); - testMalformedPK(); - testMetaAndOwnership(); - testAccountDelete(); - testUsingTickets(); + testNSimple(); + testICSimple(); + // testCancelAfter(); + // testSettleDelay(); + // testExpiration(); + // testCloseDry(); + // testDefaultAmount(); + // testDisallowXRP(); + // testDstTag(); + // testDepositAuth(); + // testMultiple(); + // testAccountChannelsRPC(); + // testAccountChannelsRPCMarkers(); + // testAccountChannelsRPCSenderOnly(); + // testAuthVerifyRPC(); + // testOptionalFields(); + // testMalformedPK(); + // testMetaAndOwnership(); + // testAccountDelete(); + // testUsingTickets(); } };