mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-19 18:15:50 +00:00
add sfLockCount and isAddable
This commit is contained in:
@@ -267,6 +267,7 @@ EscrowCreate::doApply()
|
|||||||
ctx_.view(),
|
ctx_.view(),
|
||||||
sleLine,
|
sleLine,
|
||||||
amount,
|
amount,
|
||||||
|
1,
|
||||||
ctx_.journal,
|
ctx_.journal,
|
||||||
DryRun);
|
DryRun);
|
||||||
|
|
||||||
@@ -345,6 +346,7 @@ EscrowCreate::doApply()
|
|||||||
ctx_.view(),
|
ctx_.view(),
|
||||||
sleLine,
|
sleLine,
|
||||||
amount,
|
amount,
|
||||||
|
1,
|
||||||
ctx_.journal,
|
ctx_.journal,
|
||||||
WetRun);
|
WetRun);
|
||||||
|
|
||||||
@@ -570,6 +572,7 @@ EscrowFinish::doApply()
|
|||||||
sle, // src account
|
sle, // src account
|
||||||
sled, // dst account
|
sled, // dst account
|
||||||
amount, // xfer amount
|
amount, // xfer amount
|
||||||
|
-1,
|
||||||
j_,
|
j_,
|
||||||
DryRun // dry run
|
DryRun // dry run
|
||||||
);
|
);
|
||||||
@@ -620,6 +623,7 @@ EscrowFinish::doApply()
|
|||||||
sle, // src account
|
sle, // src account
|
||||||
sled, // dst account
|
sled, // dst account
|
||||||
amount, // xfer amount
|
amount, // xfer amount
|
||||||
|
-1,
|
||||||
j_,
|
j_,
|
||||||
WetRun // wet run;
|
WetRun // wet run;
|
||||||
);
|
);
|
||||||
@@ -708,6 +712,7 @@ EscrowCancel::doApply()
|
|||||||
ctx_.view(),
|
ctx_.view(),
|
||||||
sleLine,
|
sleLine,
|
||||||
-amount,
|
-amount,
|
||||||
|
-1,
|
||||||
ctx_.journal,
|
ctx_.journal,
|
||||||
DryRun);
|
DryRun);
|
||||||
result != tesSUCCESS)
|
result != tesSUCCESS)
|
||||||
@@ -753,6 +758,7 @@ EscrowCancel::doApply()
|
|||||||
ctx_.view(),
|
ctx_.view(),
|
||||||
sleLine,
|
sleLine,
|
||||||
-amount,
|
-amount,
|
||||||
|
-1,
|
||||||
ctx_.journal,
|
ctx_.journal,
|
||||||
WetRun);
|
WetRun);
|
||||||
|
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ closeChannel(
|
|||||||
view,
|
view,
|
||||||
sleLine,
|
sleLine,
|
||||||
-amount,
|
-amount,
|
||||||
|
-1,
|
||||||
j,
|
j,
|
||||||
DryRun);
|
DryRun);
|
||||||
|
|
||||||
@@ -189,6 +190,7 @@ closeChannel(
|
|||||||
view,
|
view,
|
||||||
sleLine,
|
sleLine,
|
||||||
-amount,
|
-amount,
|
||||||
|
-1,
|
||||||
j,
|
j,
|
||||||
WetRun);
|
WetRun);
|
||||||
|
|
||||||
@@ -312,6 +314,7 @@ PayChanCreate::preclaim(PreclaimContext const& ctx)
|
|||||||
ctx.view,
|
ctx.view,
|
||||||
sleLine,
|
sleLine,
|
||||||
amount,
|
amount,
|
||||||
|
1,
|
||||||
ctx.j,
|
ctx.j,
|
||||||
DryRun);
|
DryRun);
|
||||||
|
|
||||||
@@ -417,6 +420,7 @@ PayChanCreate::doApply()
|
|||||||
ctx_.view(),
|
ctx_.view(),
|
||||||
sleLine,
|
sleLine,
|
||||||
amount,
|
amount,
|
||||||
|
1,
|
||||||
ctx_.journal,
|
ctx_.journal,
|
||||||
WetRun);
|
WetRun);
|
||||||
|
|
||||||
@@ -506,6 +510,7 @@ PayChanFund::doApply()
|
|||||||
ctx_.view(),
|
ctx_.view(),
|
||||||
sleLine,
|
sleLine,
|
||||||
amount,
|
amount,
|
||||||
|
1,
|
||||||
ctx_.journal,
|
ctx_.journal,
|
||||||
DryRun);
|
DryRun);
|
||||||
|
|
||||||
@@ -587,6 +592,7 @@ PayChanFund::doApply()
|
|||||||
ctx_.view(),
|
ctx_.view(),
|
||||||
sleLine,
|
sleLine,
|
||||||
amount,
|
amount,
|
||||||
|
1,
|
||||||
ctx_.journal,
|
ctx_.journal,
|
||||||
WetRun);
|
WetRun);
|
||||||
|
|
||||||
@@ -776,6 +782,7 @@ PayChanClaim::doApply()
|
|||||||
sleSrcAcc,
|
sleSrcAcc,
|
||||||
sled,
|
sled,
|
||||||
reqDelta,
|
reqDelta,
|
||||||
|
0,
|
||||||
ctx_.journal,
|
ctx_.journal,
|
||||||
WetRun);
|
WetRun);
|
||||||
|
|
||||||
|
|||||||
@@ -475,6 +475,7 @@ trustAdjustLockedBalance(
|
|||||||
V& view,
|
V& view,
|
||||||
S& sleLine,
|
S& sleLine,
|
||||||
STAmount const& deltaAmt,
|
STAmount const& deltaAmt,
|
||||||
|
int deltaLockCount, // if +1 lockCount is increased, -1 is decreased, 0 unchanged
|
||||||
beast::Journal const& j,
|
beast::Journal const& j,
|
||||||
R dryRun)
|
R dryRun)
|
||||||
{
|
{
|
||||||
@@ -542,26 +543,43 @@ trustAdjustLockedBalance(
|
|||||||
return tecUNFUNDED_PAYMENT;
|
return tecUNFUNDED_PAYMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
STAmount lockedBalance {sfLockedBalance, deltaAmt.issue()};
|
STAmount priorLockedBalance {sfLockedBalance, deltaAmt.issue()};
|
||||||
if (sleLine->isFieldPresent(sfLockedBalance))
|
if (sleLine->isFieldPresent(sfLockedBalance))
|
||||||
lockedBalance =
|
priorLockedBalance =
|
||||||
high ? -(*sleLine)[sfLockedBalance] : (*sleLine)[sfLockedBalance];
|
high ? -(*sleLine)[sfLockedBalance] : (*sleLine)[sfLockedBalance];
|
||||||
|
|
||||||
lockedBalance += deltaAmt;
|
uint32_t priorLockCount = 0;
|
||||||
|
if (sleLine->isFieldPresent(sfLockCount))
|
||||||
|
priorLockCount = sleLine->getFieldU32(sfLockCount);
|
||||||
|
|
||||||
if (lockedBalance > balance)
|
uint32_t finalLockCount = priorLockCount + deltaLockCount;
|
||||||
|
STAmount finalLockedBalance = priorLockedBalance + deltaAmt;
|
||||||
|
|
||||||
|
if (finalLockedBalance > balance)
|
||||||
{
|
{
|
||||||
JLOG(j.trace())
|
JLOG(j.trace())
|
||||||
<< "trustAdjustLockedBalance: "
|
<< "trustAdjustLockedBalance: "
|
||||||
<< "lockedBalance("
|
<< "lockedBalance("
|
||||||
<< lockedBalance
|
<< finalLockedBalance
|
||||||
<< ") > balance("
|
<< ") > balance("
|
||||||
<< balance
|
<< balance
|
||||||
<< ") = true\n";
|
<< ") = true\n";
|
||||||
return tecUNFUNDED_PAYMENT;
|
return tecUNFUNDED_PAYMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lockedBalance < beast::zero)
|
if (finalLockedBalance < beast::zero)
|
||||||
|
return tecINTERNAL;
|
||||||
|
|
||||||
|
// check if there is significant precision loss
|
||||||
|
if (!isAddable(balance, deltaAmt) ||
|
||||||
|
!isAddable(priorLockedBalance, deltaAmt) ||
|
||||||
|
!isAddable(finalLockedBalance, balance))
|
||||||
|
return tecPRECISION_LOSS;
|
||||||
|
|
||||||
|
// sanity check possible overflows on the lock counter
|
||||||
|
if ((deltaLockCount > 0 && priorLockCount > finalLockCount) ||
|
||||||
|
(deltaLockCount < 0 && priorLockCount < finalLockCount) ||
|
||||||
|
(deltaLockCount == 0 && priorLockCount != finalLockCount))
|
||||||
return tecINTERNAL;
|
return tecINTERNAL;
|
||||||
|
|
||||||
// we won't update any SLEs if it is a dry run
|
// we won't update any SLEs if it is a dry run
|
||||||
@@ -570,11 +588,17 @@ trustAdjustLockedBalance(
|
|||||||
|
|
||||||
if constexpr(std::is_same<V, ApplyView>::value && std::is_same<S, std::shared_ptr<SLE>>::value)
|
if constexpr(std::is_same<V, ApplyView>::value && std::is_same<S, std::shared_ptr<SLE>>::value)
|
||||||
{
|
{
|
||||||
if (lockedBalance == beast::zero)
|
if (finalLockedBalance == beast::zero || finalLockCount == 0)
|
||||||
|
{
|
||||||
sleLine->makeFieldAbsent(sfLockedBalance);
|
sleLine->makeFieldAbsent(sfLockedBalance);
|
||||||
|
sleLine->makeFieldAbsent(sfLockCount);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
sleLine->
|
sleLine->
|
||||||
setFieldAmount(sfLockedBalance, high ? -lockedBalance : lockedBalance);
|
setFieldAmount(sfLockedBalance, high ? -finalLockedBalance : finalLockedBalance);
|
||||||
|
sleLine->setFieldU32(sfLockCount, finalLockCount);
|
||||||
|
}
|
||||||
|
|
||||||
view.update(sleLine);
|
view.update(sleLine);
|
||||||
}
|
}
|
||||||
@@ -752,6 +776,7 @@ trustTransferLockedBalance(
|
|||||||
S& sleSrcAcc,
|
S& sleSrcAcc,
|
||||||
S& sleDstAcc,
|
S& sleDstAcc,
|
||||||
STAmount const& amount, // issuer, currency are in this field
|
STAmount const& amount, // issuer, currency are in this field
|
||||||
|
int deltaLockCount, // -1 decrement, +1 increment, 0 unchanged
|
||||||
beast::Journal const& j,
|
beast::Journal const& j,
|
||||||
R dryRun)
|
R dryRun)
|
||||||
{
|
{
|
||||||
@@ -820,10 +845,10 @@ trustTransferLockedBalance(
|
|||||||
return tecNO_LINE;
|
return tecNO_LINE;
|
||||||
|
|
||||||
// can't transfer a locked balance that does not exist
|
// can't transfer a locked balance that does not exist
|
||||||
if (!sleSrcLine->isFieldPresent(sfLockedBalance))
|
if (!sleSrcLine->isFieldPresent(sfLockedBalance) || !sleSrcLine->isFieldPresent(sfLockCount))
|
||||||
{
|
{
|
||||||
JLOG(j.trace())
|
JLOG(j.trace())
|
||||||
<< "trustTransferLockedBalance could not find sfLockedBalance on source line";
|
<< "trustTransferLockedBalance could not find sfLockedBalance/sfLockCount on source line";
|
||||||
return tecUNFUNDED_PAYMENT;
|
return tecUNFUNDED_PAYMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -836,6 +861,8 @@ trustTransferLockedBalance(
|
|||||||
STAmount priorLockedBalance =
|
STAmount priorLockedBalance =
|
||||||
srcHigh ? -((*sleSrcLine)[sfLockedBalance]) : (*sleSrcLine)[sfLockedBalance];
|
srcHigh ? -((*sleSrcLine)[sfLockedBalance]) : (*sleSrcLine)[sfLockedBalance];
|
||||||
|
|
||||||
|
uint32_t priorLockCount = (*sleSrcLine)[sfLockCount];
|
||||||
|
|
||||||
AccountID srcIssuerAccID =
|
AccountID srcIssuerAccID =
|
||||||
sleSrcLine->getFieldAmount(srcHigh ? sfLowLimit : sfHighLimit).getIssuer();
|
sleSrcLine->getFieldAmount(srcHigh ? sfLowLimit : sfHighLimit).getIssuer();
|
||||||
|
|
||||||
@@ -853,6 +880,19 @@ trustTransferLockedBalance(
|
|||||||
|
|
||||||
STAmount finalLockedBalance = priorLockedBalance - amount;
|
STAmount finalLockedBalance = priorLockedBalance - amount;
|
||||||
|
|
||||||
|
uint32_t finalLockCount = priorLockCount + deltaLockCount;
|
||||||
|
|
||||||
|
// check if there is significant precision loss
|
||||||
|
if (!isAddable(priorBalance, amount) ||
|
||||||
|
!isAddable(priorLockedBalance, amount))
|
||||||
|
return tecPRECISION_LOSS;
|
||||||
|
|
||||||
|
// sanity check possible overflows on the lock counter
|
||||||
|
if ((deltaLockCount > 0 && priorLockCount > finalLockCount) ||
|
||||||
|
(deltaLockCount < 0 && priorLockCount < finalLockCount) ||
|
||||||
|
(deltaLockCount == 0 && priorLockCount != finalLockCount))
|
||||||
|
return tecINTERNAL;
|
||||||
|
|
||||||
// this should never happen but defensively check it here before updating sle
|
// this should never happen but defensively check it here before updating sle
|
||||||
if (finalBalance < beast::zero || finalLockedBalance < beast::zero)
|
if (finalBalance < beast::zero || finalLockedBalance < beast::zero)
|
||||||
{
|
{
|
||||||
@@ -865,10 +905,16 @@ trustTransferLockedBalance(
|
|||||||
{
|
{
|
||||||
sleSrcLine->setFieldAmount(sfBalance, srcHigh ? -finalBalance : finalBalance);
|
sleSrcLine->setFieldAmount(sfBalance, srcHigh ? -finalBalance : finalBalance);
|
||||||
|
|
||||||
if (finalLockedBalance == beast::zero)
|
if (finalLockedBalance == beast::zero || finalLockCount == 0)
|
||||||
|
{
|
||||||
sleSrcLine->makeFieldAbsent(sfLockedBalance);
|
sleSrcLine->makeFieldAbsent(sfLockedBalance);
|
||||||
|
sleSrcLine->makeFieldAbsent(sfLockCount);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
sleSrcLine->setFieldAmount(sfLockedBalance, srcHigh ? -finalLockedBalance : finalLockedBalance);
|
sleSrcLine->setFieldAmount(sfLockedBalance, srcHigh ? -finalLockedBalance : finalLockedBalance);
|
||||||
|
sleSrcLine->setFieldU32(sfLockCount, finalLockCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -959,6 +1005,10 @@ trustTransferLockedBalance(
|
|||||||
return tecPATH_DRY;
|
return tecPATH_DRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if there is significant precision loss
|
||||||
|
if (!isAddable(priorBalance, dstAmt))
|
||||||
|
return tecPRECISION_LOSS;
|
||||||
|
|
||||||
if constexpr(!dryRun)
|
if constexpr(!dryRun)
|
||||||
sleDstLine->setFieldAmount(sfBalance, dstHigh ? -finalBalance : finalBalance);
|
sleDstLine->setFieldAmount(sfBalance, dstHigh ? -finalBalance : finalBalance);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -400,6 +400,7 @@ extern SF_UINT32 const sfMintedNFTokens;
|
|||||||
extern SF_UINT32 const sfBurnedNFTokens;
|
extern SF_UINT32 const sfBurnedNFTokens;
|
||||||
extern SF_UINT32 const sfHookStateCount;
|
extern SF_UINT32 const sfHookStateCount;
|
||||||
extern SF_UINT32 const sfEmitGeneration;
|
extern SF_UINT32 const sfEmitGeneration;
|
||||||
|
extern SF_UINT32 const sfLockCount;
|
||||||
|
|
||||||
// 64-bit integers (common)
|
// 64-bit integers (common)
|
||||||
extern SF_UINT64 const sfIndexNext;
|
extern SF_UINT64 const sfIndexNext;
|
||||||
|
|||||||
@@ -526,6 +526,29 @@ isFakeXRP(STAmount const& amount)
|
|||||||
return isFakeXRP(amount.issue().currency);
|
return isFakeXRP(amount.issue().currency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** returns true iff adding or subtracting results in less than or equal to 0.01% precision loss **/
|
||||||
|
inline bool
|
||||||
|
isAddable(STAmount const& amt1, STAmount const& amt2)
|
||||||
|
{
|
||||||
|
if (amt1 == beast::zero || amt2 == beast::zero)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
static const STAmount one {IOUAmount{1, 0}, noIssue()};
|
||||||
|
static const STAmount maxLoss {IOUAmount{1, -4}, noIssue()};
|
||||||
|
|
||||||
|
STAmount A = amt1;
|
||||||
|
STAmount B = amt2;
|
||||||
|
|
||||||
|
A.setIssue(noIssue());
|
||||||
|
B.setIssue(noIssue());
|
||||||
|
|
||||||
|
STAmount lhs = divide((A - B) + B, A, noIssue()) - one;
|
||||||
|
STAmount rhs = divide((B - A) + A, B, noIssue()) - one;
|
||||||
|
|
||||||
|
return ((rhs.negative() ? -rhs : rhs) + (lhs.negative() ? -lhs : lhs)) <= maxLoss;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Since `canonicalize` does not have access to a ledger, this is needed to put
|
// Since `canonicalize` does not have access to a ledger, this is needed to put
|
||||||
// the low-level routine stAmountCanonicalize on an amendment switch. Only
|
// the low-level routine stAmountCanonicalize on an amendment switch. Only
|
||||||
// transactions need to use this switchover. Outside of a transaction it's safe
|
// transactions need to use this switchover. Outside of a transaction it's safe
|
||||||
|
|||||||
@@ -289,6 +289,7 @@ enum TECcodes : TERUnderlyingType {
|
|||||||
tecINSUFFICIENT_FUNDS = 159,
|
tecINSUFFICIENT_FUNDS = 159,
|
||||||
tecOBJECT_NOT_FOUND = 160,
|
tecOBJECT_NOT_FOUND = 160,
|
||||||
tecINSUFFICIENT_PAYMENT = 161,
|
tecINSUFFICIENT_PAYMENT = 161,
|
||||||
|
tecPRECISION_LOSS = 162,
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ LedgerFormats::LedgerFormats()
|
|||||||
{sfHighQualityIn, soeOPTIONAL},
|
{sfHighQualityIn, soeOPTIONAL},
|
||||||
{sfHighQualityOut, soeOPTIONAL},
|
{sfHighQualityOut, soeOPTIONAL},
|
||||||
{sfLockedBalance, soeOPTIONAL},
|
{sfLockedBalance, soeOPTIONAL},
|
||||||
|
{sfLockCount, soeOPTIONAL},
|
||||||
},
|
},
|
||||||
commonFields);
|
commonFields);
|
||||||
|
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ CONSTRUCT_TYPED_SFIELD(sfMintedNFTokens, "MintedNFTokens", UINT32,
|
|||||||
CONSTRUCT_TYPED_SFIELD(sfBurnedNFTokens, "BurnedNFTokens", UINT32, 44);
|
CONSTRUCT_TYPED_SFIELD(sfBurnedNFTokens, "BurnedNFTokens", UINT32, 44);
|
||||||
CONSTRUCT_TYPED_SFIELD(sfHookStateCount, "HookStateCount", UINT32, 45);
|
CONSTRUCT_TYPED_SFIELD(sfHookStateCount, "HookStateCount", UINT32, 45);
|
||||||
CONSTRUCT_TYPED_SFIELD(sfEmitGeneration, "EmitGeneration", UINT32, 46);
|
CONSTRUCT_TYPED_SFIELD(sfEmitGeneration, "EmitGeneration", UINT32, 46);
|
||||||
|
CONSTRUCT_TYPED_SFIELD(sfLockCount, "LockCount", UINT32, 47);
|
||||||
|
|
||||||
// 64-bit integers (common)
|
// 64-bit integers (common)
|
||||||
CONSTRUCT_TYPED_SFIELD(sfIndexNext, "IndexNext", UINT64, 1);
|
CONSTRUCT_TYPED_SFIELD(sfIndexNext, "IndexNext", UINT64, 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user