Skip to content
Closed
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
26bdc43
amendment xls34d
RichardAH Mar 22, 2022
7deb949
rename tests (ic -> token)
dangell7 Feb 8, 2023
c08f6e0
bump feature
dangell7 Feb 8, 2023
e0c67c2
Merge branch 'develop' into icv2-squash
dangell7 Feb 8, 2023
0590c0b
clang-format
dangell7 Feb 8, 2023
b9fef82
update precision tests
dangell7 Feb 8, 2023
34d9b9f
Merge branch 'develop' into icv2-squash
dangell7 Feb 10, 2023
33d748b
update definitions (amendment clash)
dangell7 Feb 15, 2023
3649edf
Merge branch 'develop' into icv2-squash
dangell7 Feb 15, 2023
ffefe74
update ter code
dangell7 Feb 16, 2023
8015ac3
refactor tests
dangell7 Mar 21, 2023
19a776c
bump sField and Ter
dangell7 Mar 21, 2023
e87be8e
[fold] clang-format
dangell7 Mar 21, 2023
d88d5f5
[fold] bad clang-format
dangell7 Mar 21, 2023
7ba5a15
Merge branch 'develop' into icv2-squash
dangell7 Mar 21, 2023
1ef2b37
Merge branch 'develop' into icv2-squash
dangell7 Apr 27, 2023
8f12ae3
Merge branch 'develop' into icv2-squash
dangell7 May 19, 2023
44ea1ac
update gateway tests
dangell7 Jun 16, 2023
e53fb72
make `sfTransferRate` optional
dangell7 Jun 21, 2023
7c0151b
add amendment guard for sfTransferRate
dangell7 Jun 21, 2023
ccb6124
split tests into existing / xls34
dangell7 Jun 21, 2023
502db8f
make variables `const`
dangell7 Jun 21, 2023
d7bf45b
clang-format
dangell7 Jun 21, 2023
15da85c
chage error code
dangell7 Jun 21, 2023
0528e5b
guard optional `sfTransferRate`
dangell7 Jun 23, 2023
038e532
rename tests
dangell7 Jun 23, 2023
27bf4f4
Guard Optional sfTransferRate
dangell7 Jun 26, 2023
7e75743
clang-format
dangell7 Jun 26, 2023
eea7fcb
Merge branch 'develop' into icv2-squash
dangell7 Jun 26, 2023
c3f3dc0
Merge branch 'develop' into icv2-squash
dangell7 Sep 10, 2023
75e46de
Update TER.h
dangell7 Sep 10, 2023
e06ac19
Merge branch 'develop' into icv2-squash
dangell7 Oct 3, 2023
0182eec
Merge commit 'c706926' into icv2-squash
dangell7 Jul 17, 2024
c6dd217
Merge commit 'f6879da' into icv2-squash
dangell7 Jul 17, 2024
e3a06c5
Move CMake directory
Jul 17, 2024
51429d5
Merge remote-tracking branch 'upstream' into icv2-squash
dangell7 Jul 17, 2024
431b32b
Delete PerfLog.h
dangell7 Jul 17, 2024
5ddece0
fix merge issues
dangell7 Jul 17, 2024
b25e2bf
fix escrow
dangell7 Jul 18, 2024
e2ceefb
update tests
dangell7 Jul 20, 2024
97f33e2
Update PayChan_test.cpp
dangell7 Jul 20, 2024
cbc0258
[fold] refactor and tests
dangell7 Jul 21, 2024
2c9dbc3
clang-format
dangell7 Jul 21, 2024
1b31440
[fold] fix windows error
dangell7 Jul 21, 2024
1806df0
[fold] remove unused code
dangell7 Jul 21, 2024
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
2 changes: 2 additions & 0 deletions src/ripple/app/paths/TrustLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ TrustLineBase::TrustLineBase(
, mLowLimit(sle->getFieldAmount(sfLowLimit))
, mHighLimit(sle->getFieldAmount(sfHighLimit))
, mBalance(sle->getFieldAmount(sfBalance))
, mLockedBalance((*sle)[~sfLockedBalance])
, mLockCount((*sle)[~sfLockCount])
, mFlags(sle->getFieldU32(sfFlags))
, mViewLowest(mLowLimit.getIssuer() == viewAccount)
{
Expand Down
15 changes: 15 additions & 0 deletions src/ripple/app/paths/TrustLine.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,18 @@ class TrustLineBase
return mBalance;
}

std::optional<STAmount> const&
getLockedBalance() const
{
return mLockedBalance;
}

std::optional<uint32_t> const&
getLockCount() const
{
return mLockCount;
}

STAmount const&
getLimit() const
{
Expand All @@ -174,6 +186,9 @@ class TrustLineBase
STAmount const mHighLimit;

STAmount mBalance;
std::optional<STAmount> mLockedBalance;
std::optional<uint32_t> mLockCount; // RH NOTE: this is from sfLockCount
// has nothing to do with a mutex.

std::uint32_t mFlags;

Expand Down
256 changes: 237 additions & 19 deletions src/ripple/app/tx/impl/Escrow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <ripple/ledger/View.h>
#include <ripple/protocol/Feature.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/Rate.h>
#include <ripple/protocol/TxFlags.h>
#include <ripple/protocol/digest.h>
#include <ripple/protocol/st.h>
Expand Down Expand Up @@ -93,7 +94,8 @@ after(NetClock::time_point now, std::uint32_t mark)
TxConsequences
EscrowCreate::makeTxConsequences(PreflightContext const& ctx)
{
return TxConsequences{ctx.tx, ctx.tx[sfAmount].xrp()};
return TxConsequences{
ctx.tx, isXRP(ctx.tx[sfAmount]) ? ctx.tx[sfAmount].xrp() : beast::zero};
}

NotTEC
Expand All @@ -105,8 +107,18 @@ EscrowCreate::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (!isXRP(ctx.tx[sfAmount]))
return temBAD_AMOUNT;
STAmount const amount{ctx.tx[sfAmount]};
if (!isXRP(amount))
{
if (!ctx.rules.enabled(featurePaychanAndEscrowForTokens))
return temBAD_AMOUNT;

if (!isLegalNet(amount))
return temBAD_AMOUNT;

if (isFakeXRP(amount))
return temBAD_CURRENCY;
}

if (ctx.tx[sfAmount] <= beast::zero)
return temBAD_AMOUNT;
Expand Down Expand Up @@ -198,17 +210,70 @@ EscrowCreate::doApply()
if (!sle)
return tefINTERNAL;

// Check reserve and funds availability
{
auto const balance = STAmount((*sle)[sfBalance]).xrp();
auto const reserve =
ctx_.view().fees().accountReserve((*sle)[sfOwnerCount] + 1);
STAmount const amount{ctx_.tx[sfAmount]};

std::shared_ptr<SLE> sleLine;

if (balance < reserve)
return tecINSUFFICIENT_RESERVE;
auto const balance = STAmount((*sle)[sfBalance]).xrp();
auto const reserve =
ctx_.view().fees().accountReserve((*sle)[sfOwnerCount] + 1);
bool const isIssuer = amount.getIssuer() == account;

if (balance < reserve)
return tecINSUFFICIENT_RESERVE;

// Check reserve and funds availability
if (isXRP(amount))
{
if (balance < reserve + STAmount(ctx_.tx[sfAmount]).xrp())
return tecUNFUNDED;
// pass
}
else
{
// preflight will prevent this ever firing, included
// defensively for completeness
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
return temDISABLED;

TER const result = trustTransferAllowed(
ctx_.view(),
{account, ctx_.tx[sfDestination]},
amount.issue(),
ctx_.journal);

JLOG(ctx_.journal.trace())
<< "EscrowCreate::doApply trustTransferAllowed result=" << result;

if (!isTesSuccess(result))
return result;

// issuer does not need to lock anything
if (!isIssuer)
{
// perform the lock as a dry run before
// we modify anything on-ledger
sleLine = ctx_.view().peek(keylet::line(
account, amount.getIssuer(), amount.getCurrency()));

// check if the escrow is capable of being
// finished before we allow it to be created
if (!sleLine)
return tecNO_LINE;

{
TER const result = trustAdjustLockedBalance(
ctx_.view(), sleLine, amount, 1, ctx_.journal, DryRun);

JLOG(ctx_.journal.trace())
<< "EscrowCreate::doApply trustAdjustLockedBalance (dry) "
"result="
<< result;

if (!isTesSuccess(result))
return result;
}
}
}

// Check destination account
Expand All @@ -223,7 +288,7 @@ EscrowCreate::doApply()

// Obeying the lsfDissalowXRP flag was a bug. Piggyback on
// featureDepositAuth to remove the bug.
if (!ctx_.view().rules().enabled(featureDepositAuth) &&
if (!ctx_.view().rules().enabled(featureDepositAuth) && isXRP(amount) &&
((*sled)[sfFlags] & lsfDisallowXRP))
return tecNO_TARGET;
}
Expand All @@ -242,6 +307,12 @@ EscrowCreate::doApply()
(*slep)[~sfFinishAfter] = ctx_.tx[~sfFinishAfter];
(*slep)[~sfDestinationTag] = ctx_.tx[~sfDestinationTag];

if (ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
{
auto const xferRate = transferRate(view(), amount.getIssuer());
(*slep)[~sfTransferRate] = xferRate.value;
}

ctx_.view().insert(slep);

// Add escrow to sender's owner directory
Expand All @@ -264,7 +335,33 @@ EscrowCreate::doApply()
}

// Deduct owner's balance, increment owner count
(*sle)[sfBalance] = (*sle)[sfBalance] - ctx_.tx[sfAmount];
if (isXRP(amount))
(*sle)[sfBalance] = (*sle)[sfBalance] - ctx_.tx[sfAmount];
else
{
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
return temDISABLED;

// issuer does not need to lock anything
if (!isIssuer)
{
if (!sleLine)
return tecNO_LINE;

// do the lock-up for real now
TER const result = trustAdjustLockedBalance(
ctx_.view(), sleLine, amount, 1, ctx_.journal, WetRun);

JLOG(ctx_.journal.trace())
<< "EscrowCreate::doApply trustAdjustLockedBalance (wet) "
"result="
<< result;

if (!isTesSuccess(result))
return result;
}
}

adjustOwnerCount(ctx_.view(), sle, 1, ctx_.journal);
ctx_.view().update(sle);

Expand Down Expand Up @@ -359,6 +456,10 @@ EscrowFinish::doApply()
if (!slep)
return tecNO_TARGET;

AccountID const account = (*slep)[sfAccount];
auto const sle = ctx_.view().peek(keylet::account(account));
auto const amount = slep->getFieldAmount(sfAmount);

// If a cancel time is present, a finish operation should only succeed prior
// to that time. fix1571 corrects a logic error in the check that would make
// a finish only succeed strictly after the cancel time.
Expand Down Expand Up @@ -459,7 +560,42 @@ EscrowFinish::doApply()
}
}

AccountID const account = (*slep)[sfAccount];
if (!isXRP(amount))
{
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
return temDISABLED;

if (!slep->isFieldPresent(sfTransferRate))
return tecINTERNAL;

Rate lockedRate = ripple::Rate(slep->getFieldU32(sfTransferRate));
auto const issuerAccID = amount.getIssuer();
auto const xferRate = transferRate(view(), issuerAccID);
// update if issuer rate is less than locked rate
if (xferRate < lockedRate)
lockedRate = xferRate;

// perform a dry run of the transfer before we
// change anything on-ledger
TER const result = trustTransferLockedBalance(
ctx_.view(),
account_, // txn signing account
sle, // src account
sled, // dst account
amount, // xfer amount
-1,
lockedRate,
j_,
DryRun // dry run
);

JLOG(j_.trace())
<< "EscrowFinish::doApply trustTransferLockedBalance (dry) result="
<< result;

if (!isTesSuccess(result))
return result;
}

// Remove escrow from owner directory
{
Expand All @@ -483,12 +619,47 @@ EscrowFinish::doApply()
}
}

// Transfer amount to destination
(*sled)[sfBalance] = (*sled)[sfBalance] + (*slep)[sfAmount];
if (isXRP(amount))
(*sled)[sfBalance] = (*sled)[sfBalance] + (*slep)[sfAmount];
else
{
// compute transfer fee, if any
if (!slep->isFieldPresent(sfTransferRate))
return tecINTERNAL;

Rate lockedRate = ripple::Rate(slep->getFieldU32(sfTransferRate));
auto const issuerAccID = amount.getIssuer();
auto const xferRate = transferRate(view(), issuerAccID);
// update if issuer rate is less than locked rate
if (xferRate < lockedRate)
lockedRate = xferRate;

// all the significant complexity of checking the validity of this
// transfer and ensuring the lines exist etc is hidden away in this
// function, all we need to do is call it and return if unsuccessful.
TER const result = trustTransferLockedBalance(
ctx_.view(),
account_, // txn signing account
sle, // src account
sled, // dst account
amount, // xfer amount
-1,
lockedRate,
j_,
WetRun // wet run;
);

JLOG(j_.trace())
<< "EscrowFinish::doApply trustTransferLockedBalance (wet) result="
<< result;

if (!isTesSuccess(result))
return result;
}

ctx_.view().update(sled);

// Adjust source owner count
auto const sle = ctx_.view().peek(keylet::account(account));
adjustOwnerCount(ctx_.view(), sle, -1, ctx_.journal);
ctx_.view().update(sle);

Expand Down Expand Up @@ -542,6 +713,30 @@ EscrowCancel::doApply()
}

AccountID const account = (*slep)[sfAccount];
auto const sle = ctx_.view().peek(keylet::account(account));
auto const amount = slep->getFieldAmount(sfAmount);
bool const isIssuer = amount.getIssuer() == account;

std::shared_ptr<SLE> sleLine;

if (!isXRP(amount))
{
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
return temDISABLED;

// issuer does not need to lock anything
if (!isIssuer)
{
sleLine = ctx_.view().peek(keylet::line(
account, amount.getIssuer(), amount.getCurrency()));

// dry run before we make any changes to ledger
if (TER const result = trustAdjustLockedBalance(
ctx_.view(), sleLine, -amount, -1, ctx_.journal, DryRun);
result != tesSUCCESS)
return result;
}
}

// Remove escrow from owner directory
{
Expand All @@ -568,9 +763,32 @@ EscrowCancel::doApply()
}
}

// Transfer amount back to owner, decrement owner count
auto const sle = ctx_.view().peek(keylet::account(account));
(*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount];
// Transfer amount back to the owner (or unlock it in TL case)
if (isXRP(amount))
(*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount];
else
{
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
return temDISABLED;

// issuer does not need to lock anything
if (!isIssuer)
{
// unlock previously locked tokens from source line
TER const result = trustAdjustLockedBalance(
ctx_.view(), sleLine, -amount, -1, ctx_.journal, WetRun);

JLOG(ctx_.journal.trace())
<< "EscrowCancel::doApply trustAdjustLockedBalance (wet) "
"result="
<< result;

if (!isTesSuccess(result))
return result;
}
}

// Decrement owner count
adjustOwnerCount(ctx_.view(), sle, -1, ctx_.journal);
ctx_.view().update(sle);

Expand Down
Loading