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

View File

@@ -95,11 +95,14 @@ XRPNotCreated::visitEntry(
drops_ -= (*before)[sfBalance].xrp().drops(); drops_ -= (*before)[sfBalance].xrp().drops();
break; break;
case ltPAYCHAN: case ltPAYCHAN:
if (isXRP((*before)[sfAmount]))
drops_ -= drops_ -=
((*before)[sfAmount] - (*before)[sfBalance]).xrp().drops(); ((*before)[sfAmount] - (*before)[sfBalance]).xrp().drops();
break; break;
case ltESCROW: case ltESCROW:
drops_ -= (*before)[sfAmount].xrp().drops(); if (isXRP((*before)[sfAmount]))
drops_ -=
(*before)[sfAmount].xrp().drops();
break; break;
default: default:
break; break;
@@ -114,14 +117,14 @@ XRPNotCreated::visitEntry(
drops_ += (*after)[sfBalance].xrp().drops(); drops_ += (*after)[sfBalance].xrp().drops();
break; break;
case ltPAYCHAN: case ltPAYCHAN:
if (!isDelete) if (!isDelete && isXRP((*after)[sfAmount]))
drops_ += ((*after)[sfAmount] - (*after)[sfBalance]) drops_ +=
.xrp() ((*after)[sfAmount] - (*after)[sfBalance]).xrp().drops();
.drops();
break; break;
case ltESCROW: case ltESCROW:
if (!isDelete) if (!isDelete && isXRP((*after)[sfAmount]))
drops_ += (*after)[sfAmount].xrp().drops(); drops_ +=
(*after)[sfAmount].xrp().drops();
break; break;
default: default:
break; break;
@@ -281,12 +284,26 @@ NoZeroEscrow::visitEntry(
bool bool
NoZeroEscrow::finalize( NoZeroEscrow::finalize(
STTx const&, STTx const& txn,
TER const, TER const,
XRPAmount const, XRPAmount const,
ReadView const&, ReadView const& rv,
beast::Journal const& j) 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_) if (bad_)
{ {
JLOG(j.fatal()) << "Invariant failed: escrow specifies invalid amount"; JLOG(j.fatal()) << "Invariant failed: escrow specifies invalid amount";