Skip to content

Commit

Permalink
amendment xls34d
Browse files Browse the repository at this point in the history
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
  • Loading branch information
RichardAH authored and dangell7 committed Jan 24, 2023
1 parent 0ce15e0 commit 809ca07
Show file tree
Hide file tree
Showing 28 changed files with 6,474 additions and 196 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -22,6 +22,7 @@ bin/project-cache.jam
# Ignore object files.
*.o
build
.build
.nih_c
tags
TAGS
Expand Down
2 changes: 2 additions & 0 deletions src/ripple/app/paths/TrustLine.cpp
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
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
227 changes: 208 additions & 19 deletions src/ripple/app/tx/impl/Escrow.cpp
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;

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

if (balance < reserve)
return tecINSUFFICIENT_RESERVE;
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 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 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 Down Expand Up @@ -264,7 +329,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 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 @@ -360,6 +451,10 @@ EscrowFinish::doApply()
if (!slep)
return tecNO_TARGET;

AccountID const account = (*slep)[sfAccount];
auto const sle = ctx_.view().peek(keylet::account(account));
auto 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 @@ -460,7 +555,31 @@ EscrowFinish::doApply()
}
}

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

// perform a dry run of the transfer before we
// change anything on-ledger
TER result = trustTransferLockedBalance(
ctx_.view(),
account_, // txn signing account
sle, // src account
sled, // dst account
amount, // xfer amount
-1,
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 @@ -484,12 +603,35 @@ EscrowFinish::doApply()
}
}

// Transfer amount to destination
(*sled)[sfBalance] = (*sled)[sfBalance] + (*slep)[sfAmount];
if (isXRP(amount))
(*sled)[sfBalance] = (*sled)[sfBalance] + (*slep)[sfAmount];
else
{
// 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 result = trustTransferLockedBalance(
ctx_.view(),
account_, // txn signing account
sle, // src account
sled, // dst account
amount, // xfer amount
-1,
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 @@ -543,6 +685,30 @@ EscrowCancel::doApply()
}

AccountID const account = (*slep)[sfAccount];
auto const sle = ctx_.view().peek(keylet::account(account));
auto amount = slep->getFieldAmount(sfAmount);
bool 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 result = trustAdjustLockedBalance(
ctx_.view(), sleLine, -amount, -1, ctx_.journal, DryRun);
result != tesSUCCESS)
return result;
}
}

// Remove escrow from owner directory
{
Expand All @@ -569,9 +735,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 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

0 comments on commit 809ca07

Please sign in to comment.