mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-19 18:15:50 +00:00
started amendment
This commit is contained in:
@@ -106,8 +106,25 @@ EscrowCreate::preflight(PreflightContext const& ctx)
|
|||||||
if (!isTesSuccess(ret))
|
if (!isTesSuccess(ret))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (!isXRP(ctx.tx[sfAmount]))
|
STAmount const amount {ctx.tx[sfAmount]};
|
||||||
return temBAD_AMOUNT;
|
if (!isXRP(amount))
|
||||||
|
{
|
||||||
|
if (!ctx.view.rules().enabled(featurePaychanAndEscrowForTokens))
|
||||||
|
return temBAD_AMOUNT;
|
||||||
|
|
||||||
|
if (!isLegalNet(amount))
|
||||||
|
return temBAD_AMOUNT;
|
||||||
|
|
||||||
|
if (isFakeXRP(amount))
|
||||||
|
return temBAD_CURRENCY;
|
||||||
|
|
||||||
|
if (account == amount.getIssuer())
|
||||||
|
{
|
||||||
|
JLOG(ctx.j.trace())
|
||||||
|
<< "Malformed transaction: Cannot escrow own tokens to self.";
|
||||||
|
return temDST_IS_SRC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx.tx[sfAmount] <= beast::zero)
|
if (ctx.tx[sfAmount] <= beast::zero)
|
||||||
return temBAD_AMOUNT;
|
return temBAD_AMOUNT;
|
||||||
@@ -199,7 +216,12 @@ EscrowCreate::doApply()
|
|||||||
if (!sle)
|
if (!sle)
|
||||||
return tefINTERNAL;
|
return tefINTERNAL;
|
||||||
|
|
||||||
|
STAmount const amount {ctx.tx[sfAmount]};
|
||||||
|
|
||||||
|
std::shared_ptr<SLE> sleLine;
|
||||||
|
|
||||||
// Check reserve and funds availability
|
// Check reserve and funds availability
|
||||||
|
if (isXRP(amount))
|
||||||
{
|
{
|
||||||
auto const balance = STAmount((*sle)[sfBalance]).xrp();
|
auto const balance = STAmount((*sle)[sfBalance]).xrp();
|
||||||
auto const reserve =
|
auto const reserve =
|
||||||
@@ -211,6 +233,52 @@ EscrowCreate::doApply()
|
|||||||
if (balance < reserve + STAmount(ctx_.tx[sfAmount]).xrp())
|
if (balance < reserve + STAmount(ctx_.tx[sfAmount]).xrp())
|
||||||
return tecUNFUNDED;
|
return tecUNFUNDED;
|
||||||
}
|
}
|
||||||
|
else if (ctx.view.rules().enabled(featurePaychanAndEscrowForTokens))
|
||||||
|
{
|
||||||
|
// find the user's trustline
|
||||||
|
auto const currency = amount.getCurrency();
|
||||||
|
auto const issuer = amount.getIssuer();
|
||||||
|
|
||||||
|
if (!ctx_.view.peek(keylet::account(issuer)))
|
||||||
|
{
|
||||||
|
JLOG(ctx_.j.warn
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isGlobalFrozen(ctx_.view(), issuer))
|
||||||
|
{
|
||||||
|
JLOG(ctx_.j.warn()) << "Creating escrow for frozen asset";
|
||||||
|
return tecFROZEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleLine = ctx_.view().peek(keylet::line(account, issuer, currency));
|
||||||
|
|
||||||
|
if (!sleLine)
|
||||||
|
return tecUNFUNDED_PAYMENT;
|
||||||
|
|
||||||
|
if (sleLine->isFlag(ctx_.tx[sfDestination] > issuer ? lsfHighFreeze : lsfLowFreeze))
|
||||||
|
{
|
||||||
|
JLOG(ctx_.j.warn()) << "Creating escrow for destination frozen trustline";
|
||||||
|
return tecFROZEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool high = account > issuer;
|
||||||
|
|
||||||
|
STAmount balance = (*sleLine)[sfBalance];
|
||||||
|
|
||||||
|
STAmount lockedBalance {sfLockedBalance};
|
||||||
|
if (sleLine->isFieldPresent(sfLockedBalance))
|
||||||
|
lockedBalance = (*sleLine)[sfLockedBalance];
|
||||||
|
|
||||||
|
auto spendableBalance = balance - lockedBalance;
|
||||||
|
|
||||||
|
if (high)
|
||||||
|
spendableBalance = -spendableBalance;
|
||||||
|
|
||||||
|
if (amount > spendableBalance)
|
||||||
|
return tecUNFUNDED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return tecINTERNAL; // should never happen
|
||||||
|
|
||||||
// Check destination account
|
// Check destination account
|
||||||
{
|
{
|
||||||
@@ -265,7 +333,26 @@ EscrowCreate::doApply()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deduct owner's balance, increment owner count
|
// 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) && sleLine)
|
||||||
|
{
|
||||||
|
// update trustline to reflect locked up balance
|
||||||
|
auto const issuer = amount.getIssuer();
|
||||||
|
bool high = account > issuer;
|
||||||
|
|
||||||
|
STAmount lockedBalance;
|
||||||
|
|
||||||
|
if (sleLine->isFieldPresent(sfLockedBalance))
|
||||||
|
lockedBalance = (*sleLine)[sfLockedBalance];
|
||||||
|
|
||||||
|
lockedBalance += high ? -amount : amount;
|
||||||
|
sleLine->setFieldAmount(sfLockedBalance, lockedBalance);
|
||||||
|
ctx_.view().update(sleLine);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return tecINTERNAL; // should never happen
|
||||||
|
|
||||||
adjustOwnerCount(ctx_.view(), sle, 1, ctx_.journal);
|
adjustOwnerCount(ctx_.view(), sle, 1, ctx_.journal);
|
||||||
ctx_.view().update(sle);
|
ctx_.view().update(sle);
|
||||||
|
|
||||||
@@ -489,7 +576,86 @@ EscrowFinish::doApply()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transfer amount to destination
|
// Transfer amount to destination
|
||||||
(*sled)[sfBalance] = (*sled)[sfBalance] + (*slep)[sfAmount];
|
auto amount = (*sled)[sfBalance];
|
||||||
|
|
||||||
|
if (isXRP(amount))
|
||||||
|
{
|
||||||
|
(*sled)[sfBalance] = (*sled)[sfBalance] + (*slep)[sfAmount];
|
||||||
|
}
|
||||||
|
else if (ctx.view.rules().enabled(featurePaychanAndEscrowForTokens))
|
||||||
|
{
|
||||||
|
// check if the destination has a trustline already
|
||||||
|
auto issuer = amount.getIssuer();
|
||||||
|
auto currency = amount.getCurrency();
|
||||||
|
|
||||||
|
// check the issuer exists
|
||||||
|
if (!ctx_.view().exits(keylet::account(issuer)))
|
||||||
|
{
|
||||||
|
JLOG(ctx_.j.warn())
|
||||||
|
<< "Cannot finish escrow for token from non-existent issuer: "
|
||||||
|
<< to_string(issuer);
|
||||||
|
return tecNO_ISSUER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the trustline isn't frozen
|
||||||
|
if (isGlobalFrozen(ctx_.view(), issuer))
|
||||||
|
{
|
||||||
|
JLOG(ctx_.j.warn()) << "Cannot finish an escrow for frozen issuer";
|
||||||
|
return tecFROZEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the source line exists
|
||||||
|
auto sleSrcLine = ctx_.view().peek(keylet::line(account, issuer, currency));
|
||||||
|
if (!sleSrcLine)
|
||||||
|
{
|
||||||
|
JLOG(ctx_.j.error())
|
||||||
|
<< "Cannot finish an escrow where the source line does not exist: "
|
||||||
|
<< "acc: " << to_string(account) << " "
|
||||||
|
<< "iss: " << to_string(issuer) << " "
|
||||||
|
<< "cur: " << to_string(currency);
|
||||||
|
return tefINTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet k = keylet::line(destID, issuer, currency);
|
||||||
|
|
||||||
|
// check if the dest line exists, and if it doesn't create it if we're allowed to
|
||||||
|
auto sleDestLine = ctx_.view().peek(k);
|
||||||
|
if (!sleDestLine)
|
||||||
|
{
|
||||||
|
// if a line doesn't already exist between issuer and destination then
|
||||||
|
// such a line can now be created but only if either the person who signed
|
||||||
|
// for this txn is the destination account or the source and dest are the same
|
||||||
|
if (account != destID && account_ != destID)
|
||||||
|
return tecNO_PERMISSION;
|
||||||
|
|
||||||
|
// create trustline
|
||||||
|
|
||||||
|
// RH UPTO
|
||||||
|
|
||||||
|
// 1. reduce sfLockedBalance on source line by escrow[sfAmount]
|
||||||
|
// 2. reduce sfBalance on source line by escrow[sfAmount]
|
||||||
|
// 3. increase sfBalance on dest line by escrow[sfAmount]
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// trustline already exists
|
||||||
|
// check is it's frozen
|
||||||
|
if (destID != issuer)
|
||||||
|
{
|
||||||
|
if (sleLine->isFlag(destID > issuer ? lsfHighFreeze : lsfLowFreeze))
|
||||||
|
{
|
||||||
|
JLOG(ctx_.j.warn())
|
||||||
|
<< "Finishing an escrow for destination frozen trustline.";
|
||||||
|
return tecFROZEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if balance is higher than limit then only allow if dest is signer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return tecINTERNAL; // should never happen
|
||||||
|
|
||||||
ctx_.view().update(sled);
|
ctx_.view().update(sled);
|
||||||
|
|
||||||
// Adjust source owner count
|
// Adjust source owner count
|
||||||
|
|||||||
@@ -333,6 +333,7 @@ extern uint256 const featureFlowSortStrands;
|
|||||||
extern uint256 const fixSTAmountCanonicalize;
|
extern uint256 const fixSTAmountCanonicalize;
|
||||||
extern uint256 const fixRmSmallIncreasedQOffers;
|
extern uint256 const fixRmSmallIncreasedQOffers;
|
||||||
extern uint256 const featureCheckCashMakesTrustLine;
|
extern uint256 const featureCheckCashMakesTrustLine;
|
||||||
|
extern uint256 const featurePaychanAndEscrowForTokens;
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|
||||||
|
|||||||
@@ -448,6 +448,7 @@ extern SF_AMOUNT const sfHighLimit;
|
|||||||
extern SF_AMOUNT const sfFee;
|
extern SF_AMOUNT const sfFee;
|
||||||
extern SF_AMOUNT const sfSendMax;
|
extern SF_AMOUNT const sfSendMax;
|
||||||
extern SF_AMOUNT const sfDeliverMin;
|
extern SF_AMOUNT const sfDeliverMin;
|
||||||
|
extern SF_AMOUNT const sfLockedBalance;
|
||||||
|
|
||||||
// currency amount (uncommon)
|
// currency amount (uncommon)
|
||||||
extern SF_AMOUNT const sfMinimumOffer;
|
extern SF_AMOUNT const sfMinimumOffer;
|
||||||
|
|||||||
@@ -516,6 +516,16 @@ isXRP(STAmount const& amount)
|
|||||||
return isXRP(amount.issue().currency);
|
return isXRP(amount.issue().currency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
isFakeXRP(STAmount const& amount)
|
||||||
|
{
|
||||||
|
if (mIsNative)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return isFakeXRP(amount.issue().currency);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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
|
||||||
|
|||||||
@@ -77,6 +77,12 @@ isXRP(Currency const& c)
|
|||||||
return c == beast::zero;
|
return c == beast::zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
isFakeXRP(Currency const& c)
|
||||||
|
{
|
||||||
|
return c == badCurrency();
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns "", "XRP", or three letter ISO code. */
|
/** Returns "", "XRP", or three letter ISO code. */
|
||||||
std::string
|
std::string
|
||||||
to_string(Currency const& c);
|
to_string(Currency const& c);
|
||||||
|
|||||||
@@ -437,6 +437,7 @@ REGISTER_FEATURE(FlowSortStrands, Supported::yes, DefaultVote::yes
|
|||||||
REGISTER_FIX (fixSTAmountCanonicalize, Supported::yes, DefaultVote::yes);
|
REGISTER_FIX (fixSTAmountCanonicalize, Supported::yes, DefaultVote::yes);
|
||||||
REGISTER_FIX (fixRmSmallIncreasedQOffers, Supported::yes, DefaultVote::yes);
|
REGISTER_FIX (fixRmSmallIncreasedQOffers, Supported::yes, DefaultVote::yes);
|
||||||
REGISTER_FEATURE(CheckCashMakesTrustLine, Supported::yes, DefaultVote::no);
|
REGISTER_FEATURE(CheckCashMakesTrustLine, Supported::yes, DefaultVote::no);
|
||||||
|
REGISTER_FEATURE(PaychanAndEscrowForTokens, Supported::yes, DefaultVote::no);
|
||||||
|
|
||||||
// The following amendments have been active for at least two years. Their
|
// The following amendments have been active for at least two years. Their
|
||||||
// pre-amendment code has been removed and the identifiers are deprecated.
|
// pre-amendment code has been removed and the identifiers are deprecated.
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ LedgerFormats::LedgerFormats()
|
|||||||
{sfHighNode, soeOPTIONAL},
|
{sfHighNode, soeOPTIONAL},
|
||||||
{sfHighQualityIn, soeOPTIONAL},
|
{sfHighQualityIn, soeOPTIONAL},
|
||||||
{sfHighQualityOut, soeOPTIONAL},
|
{sfHighQualityOut, soeOPTIONAL},
|
||||||
|
{sfLockedBalance, soeOPTIONAL},
|
||||||
},
|
},
|
||||||
commonFields);
|
commonFields);
|
||||||
|
|
||||||
|
|||||||
@@ -201,6 +201,8 @@ CONSTRUCT_TYPED_SFIELD(sfDeliverMin, "DeliverMin", AMOUNT,
|
|||||||
CONSTRUCT_TYPED_SFIELD(sfMinimumOffer, "MinimumOffer", AMOUNT, 16);
|
CONSTRUCT_TYPED_SFIELD(sfMinimumOffer, "MinimumOffer", AMOUNT, 16);
|
||||||
CONSTRUCT_TYPED_SFIELD(sfRippleEscrow, "RippleEscrow", AMOUNT, 17);
|
CONSTRUCT_TYPED_SFIELD(sfRippleEscrow, "RippleEscrow", AMOUNT, 17);
|
||||||
CONSTRUCT_TYPED_SFIELD(sfDeliveredAmount, "DeliveredAmount", AMOUNT, 18);
|
CONSTRUCT_TYPED_SFIELD(sfDeliveredAmount, "DeliveredAmount", AMOUNT, 18);
|
||||||
|
// 19, 20 left for xls20
|
||||||
|
CONSTRUCT_TYPED_SFIELD(sfLockedBalance, "LockedBalance", AMOUNT, 21);
|
||||||
|
|
||||||
// variable length (common)
|
// variable length (common)
|
||||||
CONSTRUCT_TYPED_SFIELD(sfPublicKey, "PublicKey", VL, 1);
|
CONSTRUCT_TYPED_SFIELD(sfPublicKey, "PublicKey", VL, 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user