Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified .github/scripts/strategy-matrix/generate.py
100755 → 100644
Empty file.
127 changes: 123 additions & 4 deletions include/xrpl/ledger/helpers/EscrowHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,132 @@
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/protocol/Concepts.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Issue.h>
#include <xrpl/protocol/MPTAmount.h>
#include <xrpl/protocol/MPTIssue.h>
#include <xrpl/protocol/Rate.h>

namespace xrpl {

template <ValidIssueType T>
TER
escrowLockApplyHelper(
ApplyView& view,
AccountID const& issuer,
AccountID const& sender,
STAmount const& amount,
beast::Journal journal);

template <>
inline TER
escrowLockApplyHelper<Issue>(
ApplyView& view,
AccountID const& issuer,
AccountID const& sender,
STAmount const& amount,
beast::Journal journal)
{
// Defensive: Issuer cannot create an escrow
if (issuer == sender)
return tecINTERNAL; // LCOV_EXCL_LINE

auto const ter =
directSendNoFee(view, sender, issuer, amount, !amount.holds<MPTIssue>(), journal);
if (!isTesSuccess(ter))
return ter; // LCOV_EXCL_LINE
return tesSUCCESS;
}

template <>
inline TER
escrowLockApplyHelper<MPTIssue>(
ApplyView& view,
AccountID const& issuer,
AccountID const& sender,
STAmount const& amount,
beast::Journal journal)
{
// Defensive: Issuer cannot create an escrow
if (issuer == sender)
return tecINTERNAL; // LCOV_EXCL_LINE

auto const ter = lockEscrowMPT(view, sender, amount, journal);
if (!isTesSuccess(ter))
return ter; // LCOV_EXCL_LINE
return tesSUCCESS;
}

template <ValidIssueType T>
TER
escrowUnlockPreclaimHelper(
ReadView const& view,
AccountID const& account,
STAmount const& amount,
bool checkFreeze = true);

template <>
inline TER
escrowUnlockPreclaimHelper<Issue>(
ReadView const& view,
AccountID const& account,
STAmount const& amount,
bool checkFreeze)
{
AccountID const& issuer = amount.getIssuer();
// If the issuer is the same as the account, return tesSUCCESS
if (issuer == account)
return tesSUCCESS;

// If the issuer has requireAuth set, check if the destination is authorized
if (auto const ter = requireAuth(view, amount.get<Issue>(), account); !isTesSuccess(ter))
return ter;

// If the issuer has deep frozen the destination, return tecFROZEN
if (checkFreeze &&
isDeepFrozen(view, account, amount.get<Issue>().currency, amount.getIssuer()))
return tecFROZEN;

return tesSUCCESS;
}

template <>
inline TER
escrowUnlockPreclaimHelper<MPTIssue>(
ReadView const& view,
AccountID const& account,
STAmount const& amount,
bool checkFreeze)
{
AccountID const& issuer = amount.getIssuer();
// If the issuer is the same as the account, return tesSUCCESS
if (issuer == account)
return tesSUCCESS;

// If the mpt does not exist, return tecOBJECT_NOT_FOUND
auto const issuanceKey = keylet::mptIssuance(amount.get<MPTIssue>().getMptID());
auto const sleIssuance = view.read(issuanceKey);
if (!sleIssuance)
return tecOBJECT_NOT_FOUND;

// If the issuer has requireAuth set, check if the account is
// authorized
auto const& mptIssue = amount.get<MPTIssue>();
if (auto const ter = requireAuth(view, mptIssue, account, AuthType::WeakAuth);
!isTesSuccess(ter))
return ter;

// If the issuer has frozen the account, return tecLOCKED
if (checkFreeze && isFrozen(view, account, mptIssue))
return tecLOCKED;

return tesSUCCESS;
}

//------------------------------------------------------------------------------

template <ValidIssueType T>
TER
escrowUnlockApplyHelper(
Expand Down Expand Up @@ -46,14 +165,15 @@ escrowUnlockApplyHelper<Issue>(
bool const recvLow = issuer > receiver;
bool const senderIssuer = issuer == sender;
bool const receiverIssuer = issuer == receiver;
bool const lineExisted = view.exists(trustLineKey);

if (senderIssuer)
return tecINTERNAL; // LCOV_EXCL_LINE

if (receiverIssuer)
return tesSUCCESS;

if (!view.exists(trustLineKey) && createAsset)
if (!lineExisted && createAsset)
{
// Can the account cover the trust line's reserve?
if (std::uint32_t const ownerCount = {sleDest->at(sfOwnerCount)};
Expand Down Expand Up @@ -120,9 +240,8 @@ escrowUnlockApplyHelper<Issue>(
finalAmt = amount.value() - xferFee;
}

// validate the line limit if the account submitting txn is not the receiver
// of the funds
if (!createAsset)
// validate the line limit for pre-existing trust lines
if (lineExisted)
{
auto const sleRippleState = view.peek(trustLineKey);
if (!sleRippleState)
Expand Down
2 changes: 2 additions & 0 deletions include/xrpl/ledger/helpers/PaymentChannelHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/UintTypes.h>

Expand All @@ -12,6 +13,7 @@ closeChannel(
std::shared_ptr<SLE> const& slep,
ApplyView& view,
uint256 const& key,
AccountID const& txAccount,
beast::Journal j);

} // namespace xrpl
60 changes: 60 additions & 0 deletions include/xrpl/protocol/PayChan.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
#pragma once

#include <xrpl/basics/base_uint.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/IOUAmount.h>
#include <xrpl/protocol/Issue.h>
#include <xrpl/protocol/MPTAmount.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/UintTypes.h>
#include <xrpl/protocol/XRPAmount.h>

namespace xrpl {
Expand All @@ -15,4 +21,58 @@ serializePayChanAuthorization(Serializer& msg, uint256 const& key, XRPAmount con
msg.add64(amt.drops());
}

inline void
serializePayChanAuthorization(
Serializer& msg,
uint256 const& key,
IOUAmount const& amt,
Currency const& cur,
AccountID const& iss)
{
msg.add32(HashPrefix::PaymentChannelClaim);
msg.addBitString(key);
if (amt == beast::kZERO)
msg.add64(STAmount::kISSUED_CURRENCY);
else if (amt.signum() == -1) // 512 = not native
msg.add64(
amt.mantissa() | (static_cast<std::uint64_t>(amt.exponent() + 512 + 97) << (64 - 10)));
else // 256 = positive
msg.add64(
amt.mantissa() |
(static_cast<std::uint64_t>(amt.exponent() + 512 + 256 + 97) << (64 - 10)));
msg.addBitString(cur);
msg.addBitString(iss);
}

inline void
serializePayChanAuthorization(
Serializer& msg,
uint256 const& key,
MPTAmount const& amt,
MPTID const& mptID,
AccountID const& iss)
{
msg.add32(HashPrefix::PaymentChannelClaim);
msg.addBitString(key);
msg.add64(amt.value());
msg.addBitString(mptID);
msg.addBitString(iss);
}

inline void
serializePayChanAuthorization(Serializer& msg, uint256 const& key, STAmount const& amt)
{
if (amt.native())
serializePayChanAuthorization(msg, key, amt.xrp());
else if (amt.holds<Issue>())
serializePayChanAuthorization(
msg, key, amt.iou(), amt.get<Issue>().currency, amt.get<Issue>().account);
else if (amt.holds<MPTIssue>())
{
auto const mpt = amt.get<MPTIssue>();
auto const mptID = mpt.getMptID();
serializePayChanAuthorization(msg, key, amt.mpt(), mptID, amt.getIssuer());
}
}

} // namespace xrpl
1 change: 1 addition & 0 deletions include/xrpl/protocol/detail/features.macro
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// Add new amendments to the top of this list.
// Keep it sorted in reverse chronological order.

XRPL_FEATURE(TokenPaychan, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (Cleanup3_2_0, Supported::No, VoteBehavior::DefaultNo)
XRPL_FEATURE(MPTokensV2, Supported::No, VoteBehavior::DefaultNo)
XRPL_FIX (Security3_1_3, Supported::No, VoteBehavior::DefaultNo)
Expand Down
2 changes: 2 additions & 0 deletions include/xrpl/protocol/detail/ledger_entries.macro
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ LEDGER_ENTRY(ltPAYCHAN, 0x0078, PayChannel, payment_channel, ({
{sfPreviousTxnID, SoeRequired},
{sfPreviousTxnLgrSeq, SoeRequired},
{sfDestinationNode, SoeOptional},
{sfTransferRate, SoeOptional},
{sfIssuerNode, SoeOptional},
}))

/** The ledger object which tracks the AMM.
Expand Down
8 changes: 4 additions & 4 deletions include/xrpl/protocol/detail/transactions.macro
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ TRANSACTION(ttPAYCHAN_CREATE, 13, PaymentChannelCreate,
NoPriv,
({
{sfDestination, SoeRequired},
{sfAmount, SoeRequired},
{sfAmount, SoeRequired, SoeMptSupported},
{sfSettleDelay, SoeRequired},
{sfPublicKey, SoeRequired},
{sfCancelAfter, SoeOptional},
Expand All @@ -208,7 +208,7 @@ TRANSACTION(ttPAYCHAN_FUND, 14, PaymentChannelFund,
NoPriv,
({
{sfChannel, SoeRequired},
{sfAmount, SoeRequired},
{sfAmount, SoeRequired, SoeMptSupported},
{sfExpiration, SoeOptional},
}))

Expand All @@ -222,8 +222,8 @@ TRANSACTION(ttPAYCHAN_CLAIM, 15, PaymentChannelClaim,
NoPriv,
({
{sfChannel, SoeRequired},
{sfAmount, SoeOptional},
{sfBalance, SoeOptional},
{sfAmount, SoeOptional, SoeMptSupported},
{sfBalance, SoeOptional, SoeMptSupported},
{sfSignature, SoeOptional},
{sfPublicKey, SoeOptional},
{sfCredentialIDs, SoeOptional},
Expand Down
1 change: 1 addition & 0 deletions include/xrpl/protocol/jss.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ JSS(errored); //
JSS(error_code); // out: error
JSS(error_exception); // out: Submit
JSS(error_message); // out: error
JSS(escrowed); // out: escrowed
JSS(expand); // in: handler/Ledger
JSS(expected_date); // out: any (warnings)
JSS(expected_date_UTC); // out: any (warnings)
Expand Down
Loading