fix invariants for IOU escrows/paychans

This commit is contained in:
Richard Holland
2022-03-25 12:15:01 +00:00
parent 9dd831a7f4
commit 384b224d64
2 changed files with 38 additions and 17 deletions

View File

@@ -93,7 +93,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
@@ -270,7 +271,7 @@ EscrowCreate::doApply()
STAmount balance = (*sleLine)[sfBalance];
STAmount lockedBalance {sfLockedBalance};
STAmount lockedBalance {sfLockedBalance, amount.issue()};
if (sleLine->isFieldPresent(sfLockedBalance))
lockedBalance = (*sleLine)[sfLockedBalance];
@@ -343,10 +344,9 @@ EscrowCreate::doApply()
else if (ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens) && sleLine)
{
// update trustline to reflect locked up balance
auto const issuer = amount.getIssuer();
bool high = account > issuer;
bool high = account > amount.getIssuer();
STAmount lockedBalance;
STAmount lockedBalance {sfLockedBalance, amount.issue()};
if (sleLine->isFieldPresent(sfLockedBalance))
lockedBalance = (*sleLine)[sfLockedBalance];
@@ -898,7 +898,11 @@ EscrowCancel::doApply()
}
sleSrcLine->setFieldAmount(sfBalance, isLow ? finalBalance : -finalBalance);
sleSrcLine->setFieldAmount(sfLockedBalance, isLow ? finalLockedBalance : -finalLockedBalance);
if (finalLockedBalance == beast::zero)
sleSrcLine->makeFieldAbsent(sfLockedBalance);
else
sleSrcLine->setFieldAmount(sfLockedBalance, isLow ? finalLockedBalance : -finalLockedBalance);
view.update(sleSrcLine);
}

View File

@@ -95,11 +95,14 @@ XRPNotCreated::visitEntry(
drops_ -= (*before)[sfBalance].xrp().drops();
break;
case ltPAYCHAN:
drops_ -=
((*before)[sfAmount] - (*before)[sfBalance]).xrp().drops();
if (isXRP((*before)[sfAmount]))
drops_ -=
((*before)[sfAmount] - (*before)[sfBalance]).xrp().drops();
break;
case ltESCROW:
drops_ -= (*before)[sfAmount].xrp().drops();
if (isXRP((*before)[sfAmount]))
drops_ -=
(*before)[sfAmount].xrp().drops();
break;
default:
break;
@@ -114,14 +117,14 @@ XRPNotCreated::visitEntry(
drops_ += (*after)[sfBalance].xrp().drops();
break;
case ltPAYCHAN:
if (!isDelete)
drops_ += ((*after)[sfAmount] - (*after)[sfBalance])
.xrp()
.drops();
if (!isDelete && isXRP((*after)[sfAmount]))
drops_ +=
((*after)[sfAmount] - (*after)[sfBalance]).xrp().drops();
break;
case ltESCROW:
if (!isDelete)
drops_ += (*after)[sfAmount].xrp().drops();
if (!isDelete && isXRP((*after)[sfAmount]))
drops_ +=
(*after)[sfAmount].xrp().drops();
break;
default:
break;
@@ -281,12 +284,26 @@ NoZeroEscrow::visitEntry(
bool
NoZeroEscrow::finalize(
STTx const&,
STTx const& txn,
TER const,
XRPAmount const,
ReadView const&,
ReadView const& rv,
beast::Journal const& j)
{
// bypass this invariant check for IOU escrows
if (bad_ &&
rv.rules().enabled(featurePaychanAndEscrowForTokens) &&
txn.isFieldPresent(sfTransactionType) &&
txn.isFieldPresent(sfAmount))
{
uint16_t tt = txn.getFieldU16(sfTransactionType);
if (tt == ttESCROW_CREATE || tt == ttESCROW_FINISH || tt == ttESCROW_CANCEL)
{
if (!isXRP(txn.getFieldAmount(sfAmount)))
return true;
}
}
if (bad_)
{
JLOG(j.fatal()) << "Invariant failed: escrow specifies invalid amount";