Skip to content

Commit

Permalink
Strongly typed wrapper for Payment Channels ledger object
Browse files Browse the repository at this point in the history
This commit introduces implementation for the said wrapper. Occurences of PayChan keylet have been modified to indicate the new type.
One function in PayChan_test.cpp:channelAndSle(...) uses the readSLE API. It has a dependency on inOwnerDir(...) function. This can be ported only after completion of the Directory ledger object wrapper.
  • Loading branch information
ckeshava committed Jun 1, 2023
1 parent c6d98e6 commit 9933dae
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/ripple/app/tx/impl/PayChan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ PayChanCreate::doApply()
//
// Note that we we use the value from the sequence or ticket as the
// payChan sequence. For more explanation see comments in SeqProxy.h.
Keylet const payChanKeylet =
PayChanKeylet const payChanKeylet =
keylet::payChan(account, dst, ctx_.tx.getSeqProxy().value());
auto const slep = std::make_shared<SLE>(payChanKeylet);

Expand Down
2 changes: 1 addition & 1 deletion src/ripple/ledger/ApplyView.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ class ApplyView : public ReadView
std::optional<std::uint64_t>
dirInsert(
Keylet const& directory,
Keylet const& key,
KeyletBase const& key,
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
{
return dirAdd(false, directory, key.key, describe);
Expand Down
2 changes: 1 addition & 1 deletion src/ripple/protocol/Indexes.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ Keylet
escrow(AccountID const& src, std::uint32_t seq) noexcept;

/** A PaymentChannel */
Keylet
PayChanKeylet
payChan(AccountID const& src, AccountID const& dst, std::uint32_t seq) noexcept;

/** NFT page keylets
Expand Down
15 changes: 15 additions & 0 deletions src/ripple/protocol/Keylet.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,21 @@ static_assert(std::is_move_assignable_v<Keylet>);
static_assert(std::is_nothrow_destructible_v<Keylet>);
#endif

template <bool>
class PayChanImpl;

struct PayChanKeylet final : public KeyletBase
{
template <bool Writable>
using TWrapped = PayChanImpl<Writable>;

using KeyletBase::check;

explicit PayChanKeylet(uint256 const& key) : KeyletBase(ltPAYCHAN, key)
{
}
};

template <bool>
class AcctRootImpl;

Expand Down
33 changes: 33 additions & 0 deletions src/ripple/protocol/PayChan.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,39 @@

namespace ripple {

template <bool Writable>
class PayChanImpl final : public LedgerEntryWrapper<Writable>
{
using Base = LedgerEntryWrapper<Writable>;
using SleT = typename Base::SleT;
using Base::wrapped_;

// This constructor is private so only the factory functions can
// construct an PayChanImpl.
PayChanImpl(std::shared_ptr<SleT>&& w) : Base(std::move(w))
{
}

// Friend declarations of factory functions.
//
// For classes that contain factories we must declare the entire class
// as a friend unless the class declaration is visible at this point.
friend class ReadView;
friend class ApplyView;

public:
// Conversion operator from PayChanImpl<true> to PayChanImpl<false>.
operator PayChanImpl<true>() const
{
return PayChanImpl<false>(
std::const_pointer_cast<std::shared_ptr<STLedgerEntry const>>(
wrapped_));
}
};

using PayChan = PayChanImpl<true>;
using PayChanRd = PayChanImpl<false>;

inline void
serializePayChanAuthorization(
Serializer& msg,
Expand Down
7 changes: 3 additions & 4 deletions src/ripple/protocol/impl/Indexes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,12 +320,11 @@ escrow(AccountID const& src, std::uint32_t seq) noexcept
return {ltESCROW, indexHash(LedgerNameSpace::ESCROW, src, seq)};
}

Keylet
PayChanKeylet
payChan(AccountID const& src, AccountID const& dst, std::uint32_t seq) noexcept
{
return {
ltPAYCHAN,
indexHash(LedgerNameSpace::XRP_PAYMENT_CHANNEL, src, dst, seq)};
return PayChanKeylet(
indexHash(LedgerNameSpace::XRP_PAYMENT_CHANNEL, src, dst, seq));
}

Keylet
Expand Down
10 changes: 6 additions & 4 deletions src/test/app/AccountDelete_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ class AccountDelete_test : public beast::unit_test::suite
env(escrowCancel(becky, alice, escrowSeq));
env.close();

Keylet const alicePayChanKey{
PayChanKeylet const alicePayChanKey{
keylet::payChan(alice, becky, env.seq(alice))};

env(payChanCreate(
Expand All @@ -426,7 +426,7 @@ class AccountDelete_test : public beast::unit_test::suite

// Lambda to close a PayChannel.
auto payChanClose = [](jtx::Account const& account,
Keylet const& payChanKeylet,
KeyletBase const& payChanKeylet,
PublicKey const& pk) {
Json::Value jv;
jv[jss::TransactionType] = jss::PaymentChannelClaim;
Expand All @@ -447,7 +447,8 @@ class AccountDelete_test : public beast::unit_test::suite
// gw creates a PayChannel with alice as the destination. With the
// amendment passed this should prevent alice from deleting her
// account.
Keylet const gwPayChanKey{keylet::payChan(gw, alice, env.seq(gw))};
PayChanKeylet const gwPayChanKey{
keylet::payChan(gw, alice, env.seq(gw))};

env(payChanCreate(gw, alice, XRP(68), 4s, env.now() + 2s, alice.pk()));
env.close();
Expand Down Expand Up @@ -492,7 +493,8 @@ class AccountDelete_test : public beast::unit_test::suite
BEAST_EXPECT(env.closed()->exists(beckyAcctKey));

using namespace std::chrono_literals;
Keylet const payChanKey{keylet::payChan(alice, becky, env.seq(alice))};
PayChanKeylet const payChanKey{
keylet::payChan(alice, becky, env.seq(alice))};
auto const payChanXRP = XRP(37);

env(payChanCreate(
Expand Down
6 changes: 4 additions & 2 deletions src/test/app/PayChan_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ struct PayChan_test : public beast::unit_test::suite
return k.key;
}

// Keshava: Modify this function to use read() after keylet::ownerDir has
// been updated. inOwnerDir(...) has a dependency on ltDirNode.
static std::pair<uint256, std::shared_ptr<SLE const>>
channelKeyAndSle(
ReadView const& view,
Expand Down Expand Up @@ -81,8 +83,8 @@ struct PayChan_test : public beast::unit_test::suite
static bool
channelExists(ReadView const& view, uint256 const& chan)
{
auto const slep = view.readSLE(Keylet(ltPAYCHAN, chan));
return bool(slep);
auto const slep = view.read(PayChanKeylet(chan));
return slep.has_value();
}

static STAmount
Expand Down

0 comments on commit 9933dae

Please sign in to comment.