Skip to content

Commit 99b7700

Browse files
RichardAHdangell7
authored andcommitted
amendment xls34d
XRPLF/XRPL-Standards#88 started amendment escrow trustline code finished, untested not compiling compiling fix invariants for IOU escrows/paychans prevent trustlines being spent below spendable balance bug fixes for IOU escrows preliminary paychan IOU support, compiling, not tested bug fixes, testing move all trustline lock and unlock logic to view, untested more refactoring compiling debugging, bug fixes templates major refactor templates for trustTransfer and lock fix logging to use journals escrow bug fixes, escrow create/finish/cancel working update claim serialization format add sfLockCount and isAddable add error message, address isAddable xrp edgecases bug fixes add lockedbalance and lockcount to account_lines rpc update error handling & fix xrp issue fix: format error change check from xrp to native + error handle add IC to tecUNFUNDED add ic signClaim fix amount bug comment unused variable tests escrow tests change error type add paychan tests enable test w/ features fix account_channels resp cont. paychan tests escrow tests cont. + lint/clean update rpc auth + verify enable disallowXRP test (escrow) paychan tests tests; rpc, disallow & abusetl fix disalllow XRP bug lint fix disallow XRP tests fix consequences test fixup consequences test update rpc call `value/currency/issuer` fix paychan marker cleanup and fix rpc call test add gateway feature clang-format fix no-line bug add pre test fix test name remove invariant test clang-format nit clang-format clang-format
1 parent 0ce15e0 commit 99b7700

28 files changed

+6474
-196
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ bin/project-cache.jam
2222
# Ignore object files.
2323
*.o
2424
build
25+
.build
2526
.nih_c
2627
tags
2728
TAGS

src/ripple/app/paths/TrustLine.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ TrustLineBase::TrustLineBase(
3232
, mLowLimit(sle->getFieldAmount(sfLowLimit))
3333
, mHighLimit(sle->getFieldAmount(sfHighLimit))
3434
, mBalance(sle->getFieldAmount(sfBalance))
35+
, mLockedBalance((*sle)[~sfLockedBalance])
36+
, mLockCount((*sle)[~sfLockCount])
3537
, mFlags(sle->getFieldU32(sfFlags))
3638
, mViewLowest(mLowLimit.getIssuer() == viewAccount)
3739
{

src/ripple/app/paths/TrustLine.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,18 @@ class TrustLineBase
152152
return mBalance;
153153
}
154154

155+
std::optional<STAmount> const&
156+
getLockedBalance() const
157+
{
158+
return mLockedBalance;
159+
}
160+
161+
std::optional<uint32_t> const&
162+
getLockCount() const
163+
{
164+
return mLockCount;
165+
}
166+
155167
STAmount const&
156168
getLimit() const
157169
{
@@ -174,6 +186,9 @@ class TrustLineBase
174186
STAmount const mHighLimit;
175187

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

178193
std::uint32_t mFlags;
179194

src/ripple/app/tx/impl/Escrow.cpp

Lines changed: 208 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <ripple/ledger/View.h>
3131
#include <ripple/protocol/Feature.h>
3232
#include <ripple/protocol/Indexes.h>
33+
#include <ripple/protocol/Rate.h>
3334
#include <ripple/protocol/TxFlags.h>
3435
#include <ripple/protocol/digest.h>
3536
#include <ripple/protocol/st.h>
@@ -93,7 +94,8 @@ after(NetClock::time_point now, std::uint32_t mark)
9394
TxConsequences
9495
EscrowCreate::makeTxConsequences(PreflightContext const& ctx)
9596
{
96-
return TxConsequences{ctx.tx, ctx.tx[sfAmount].xrp()};
97+
return TxConsequences{
98+
ctx.tx, isXRP(ctx.tx[sfAmount]) ? ctx.tx[sfAmount].xrp() : beast::zero};
9799
}
98100

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

108-
if (!isXRP(ctx.tx[sfAmount]))
109-
return temBAD_AMOUNT;
110+
STAmount const amount{ctx.tx[sfAmount]};
111+
if (!isXRP(amount))
112+
{
113+
if (!ctx.rules.enabled(featurePaychanAndEscrowForTokens))
114+
return temBAD_AMOUNT;
115+
116+
if (!isLegalNet(amount))
117+
return temBAD_AMOUNT;
118+
119+
if (isFakeXRP(amount))
120+
return temBAD_CURRENCY;
121+
}
110122

111123
if (ctx.tx[sfAmount] <= beast::zero)
112124
return temBAD_AMOUNT;
@@ -198,17 +210,70 @@ EscrowCreate::doApply()
198210
if (!sle)
199211
return tefINTERNAL;
200212

201-
// Check reserve and funds availability
202-
{
203-
auto const balance = STAmount((*sle)[sfBalance]).xrp();
204-
auto const reserve =
205-
ctx_.view().fees().accountReserve((*sle)[sfOwnerCount] + 1);
213+
STAmount const amount{ctx_.tx[sfAmount]};
214+
215+
std::shared_ptr<SLE> sleLine;
216+
217+
auto const balance = STAmount((*sle)[sfBalance]).xrp();
218+
auto const reserve =
219+
ctx_.view().fees().accountReserve((*sle)[sfOwnerCount] + 1);
220+
bool isIssuer = amount.getIssuer() == account;
206221

207-
if (balance < reserve)
208-
return tecINSUFFICIENT_RESERVE;
222+
if (balance < reserve)
223+
return tecINSUFFICIENT_RESERVE;
209224

225+
// Check reserve and funds availability
226+
if (isXRP(amount))
227+
{
210228
if (balance < reserve + STAmount(ctx_.tx[sfAmount]).xrp())
211229
return tecUNFUNDED;
230+
// pass
231+
}
232+
else
233+
{
234+
// preflight will prevent this ever firing, included
235+
// defensively for completeness
236+
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
237+
return temDISABLED;
238+
239+
TER result = trustTransferAllowed(
240+
ctx_.view(),
241+
{account, ctx_.tx[sfDestination]},
242+
amount.issue(),
243+
ctx_.journal);
244+
245+
JLOG(ctx_.journal.trace())
246+
<< "EscrowCreate::doApply trustTransferAllowed result=" << result;
247+
248+
if (!isTesSuccess(result))
249+
return result;
250+
251+
// issuer does not need to lock anything
252+
if (!isIssuer)
253+
{
254+
// perform the lock as a dry run before
255+
// we modify anything on-ledger
256+
sleLine = ctx_.view().peek(keylet::line(
257+
account, amount.getIssuer(), amount.getCurrency()));
258+
259+
// check if the escrow is capable of being
260+
// finished before we allow it to be created
261+
if (!sleLine)
262+
return tecNO_LINE;
263+
264+
{
265+
TER result = trustAdjustLockedBalance(
266+
ctx_.view(), sleLine, amount, 1, ctx_.journal, DryRun);
267+
268+
JLOG(ctx_.journal.trace())
269+
<< "EscrowCreate::doApply trustAdjustLockedBalance (dry) "
270+
"result="
271+
<< result;
272+
273+
if (!isTesSuccess(result))
274+
return result;
275+
}
276+
}
212277
}
213278

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

224289
// Obeying the lsfDissalowXRP flag was a bug. Piggyback on
225290
// featureDepositAuth to remove the bug.
226-
if (!ctx_.view().rules().enabled(featureDepositAuth) &&
291+
if (!ctx_.view().rules().enabled(featureDepositAuth) && isXRP(amount) &&
227292
((*sled)[sfFlags] & lsfDisallowXRP))
228293
return tecNO_TARGET;
229294
}
@@ -264,7 +329,33 @@ EscrowCreate::doApply()
264329
}
265330

266331
// Deduct owner's balance, increment owner count
267-
(*sle)[sfBalance] = (*sle)[sfBalance] - ctx_.tx[sfAmount];
332+
if (isXRP(amount))
333+
(*sle)[sfBalance] = (*sle)[sfBalance] - ctx_.tx[sfAmount];
334+
else
335+
{
336+
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
337+
return temDISABLED;
338+
339+
// issuer does not need to lock anything
340+
if (!isIssuer)
341+
{
342+
if (!sleLine)
343+
return tecNO_LINE;
344+
345+
// do the lock-up for real now
346+
TER result = trustAdjustLockedBalance(
347+
ctx_.view(), sleLine, amount, 1, ctx_.journal, WetRun);
348+
349+
JLOG(ctx_.journal.trace())
350+
<< "EscrowCreate::doApply trustAdjustLockedBalance (wet) "
351+
"result="
352+
<< result;
353+
354+
if (!isTesSuccess(result))
355+
return result;
356+
}
357+
}
358+
268359
adjustOwnerCount(ctx_.view(), sle, 1, ctx_.journal);
269360
ctx_.view().update(sle);
270361

@@ -360,6 +451,10 @@ EscrowFinish::doApply()
360451
if (!slep)
361452
return tecNO_TARGET;
362453

454+
AccountID const account = (*slep)[sfAccount];
455+
auto const sle = ctx_.view().peek(keylet::account(account));
456+
auto amount = slep->getFieldAmount(sfAmount);
457+
363458
// If a cancel time is present, a finish operation should only succeed prior
364459
// to that time. fix1571 corrects a logic error in the check that would make
365460
// a finish only succeed strictly after the cancel time.
@@ -460,7 +555,31 @@ EscrowFinish::doApply()
460555
}
461556
}
462557

463-
AccountID const account = (*slep)[sfAccount];
558+
if (!isXRP(amount))
559+
{
560+
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
561+
return temDISABLED;
562+
563+
// perform a dry run of the transfer before we
564+
// change anything on-ledger
565+
TER result = trustTransferLockedBalance(
566+
ctx_.view(),
567+
account_, // txn signing account
568+
sle, // src account
569+
sled, // dst account
570+
amount, // xfer amount
571+
-1,
572+
j_,
573+
DryRun // dry run
574+
);
575+
576+
JLOG(j_.trace())
577+
<< "EscrowFinish::doApply trustTransferLockedBalance (dry) result="
578+
<< result;
579+
580+
if (!isTesSuccess(result))
581+
return result;
582+
}
464583

465584
// Remove escrow from owner directory
466585
{
@@ -484,12 +603,35 @@ EscrowFinish::doApply()
484603
}
485604
}
486605

487-
// Transfer amount to destination
488-
(*sled)[sfBalance] = (*sled)[sfBalance] + (*slep)[sfAmount];
606+
if (isXRP(amount))
607+
(*sled)[sfBalance] = (*sled)[sfBalance] + (*slep)[sfAmount];
608+
else
609+
{
610+
// all the significant complexity of checking the validity of this
611+
// transfer and ensuring the lines exist etc is hidden away in this
612+
// function, all we need to do is call it and return if unsuccessful.
613+
TER result = trustTransferLockedBalance(
614+
ctx_.view(),
615+
account_, // txn signing account
616+
sle, // src account
617+
sled, // dst account
618+
amount, // xfer amount
619+
-1,
620+
j_,
621+
WetRun // wet run;
622+
);
623+
624+
JLOG(j_.trace())
625+
<< "EscrowFinish::doApply trustTransferLockedBalance (wet) result="
626+
<< result;
627+
628+
if (!isTesSuccess(result))
629+
return result;
630+
}
631+
489632
ctx_.view().update(sled);
490633

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

@@ -543,6 +685,30 @@ EscrowCancel::doApply()
543685
}
544686

545687
AccountID const account = (*slep)[sfAccount];
688+
auto const sle = ctx_.view().peek(keylet::account(account));
689+
auto amount = slep->getFieldAmount(sfAmount);
690+
bool isIssuer = amount.getIssuer() == account;
691+
692+
std::shared_ptr<SLE> sleLine;
693+
694+
if (!isXRP(amount))
695+
{
696+
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
697+
return temDISABLED;
698+
699+
// issuer does not need to lock anything
700+
if (!isIssuer)
701+
{
702+
sleLine = ctx_.view().peek(keylet::line(
703+
account, amount.getIssuer(), amount.getCurrency()));
704+
705+
// dry run before we make any changes to ledger
706+
if (TER result = trustAdjustLockedBalance(
707+
ctx_.view(), sleLine, -amount, -1, ctx_.journal, DryRun);
708+
result != tesSUCCESS)
709+
return result;
710+
}
711+
}
546712

547713
// Remove escrow from owner directory
548714
{
@@ -569,9 +735,32 @@ EscrowCancel::doApply()
569735
}
570736
}
571737

572-
// Transfer amount back to owner, decrement owner count
573-
auto const sle = ctx_.view().peek(keylet::account(account));
574-
(*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount];
738+
// Transfer amount back to the owner (or unlock it in TL case)
739+
if (isXRP(amount))
740+
(*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount];
741+
else
742+
{
743+
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
744+
return temDISABLED;
745+
746+
// issuer does not need to lock anything
747+
if (!isIssuer)
748+
{
749+
// unlock previously locked tokens from source line
750+
TER result = trustAdjustLockedBalance(
751+
ctx_.view(), sleLine, -amount, -1, ctx_.journal, WetRun);
752+
753+
JLOG(ctx_.journal.trace())
754+
<< "EscrowCancel::doApply trustAdjustLockedBalance (wet) "
755+
"result="
756+
<< result;
757+
758+
if (!isTesSuccess(result))
759+
return result;
760+
}
761+
}
762+
763+
// Decrement owner count
575764
adjustOwnerCount(ctx_.view(), sle, -1, ctx_.journal);
576765
ctx_.view().update(sle);
577766

0 commit comments

Comments
 (0)