Rework offer amount calculation.

This commit is contained in:
Arthur Britto
2012-07-13 15:27:22 -07:00
parent 9d40598b2b
commit a3fb732e24
5 changed files with 65 additions and 46 deletions

View File

@@ -737,41 +737,50 @@ uint64 STAmount::getRate(const STAmount& offerOut, const STAmount& offerIn)
return (ret << (64 - 8)) | r.getMantissa();
}
STAmount STAmount::getClaimed(STAmount& offerOut, STAmount& offerIn, STAmount& paid)
{ // if someone is offering (offerOut) for (offerIn), and I pay (paid), how much do I get?
// Taker gets all taker can pay for with saTakerFunds, limited by saOfferPays and saOfferFunds.
// --> saOfferFunds: Limit for saOfferPays
// --> saTakerFunds: Limit for saOfferGets
// --> saOfferPays: Request : this should be reduced as the offer is fullfilled.
// --> saOfferGets: Request : this should be reduced as the offer is fullfilled.
// --> saTakerPays: Total : Used to know the approximate ratio of the exchange.
// --> saTakerGets: Total : Used to know the approximate ratio of the exchange.
// <-- saTakerPaid: Actual
// <-- saTakerGot: Actual
// <-- bRemove: remove offer it is either fullfilled or unfunded
bool STAmount::applyOffer(
const STAmount& saOfferFunds, const STAmount& saTakerFunds,
const STAmount& saOfferPays, const STAmount& saOfferGets,
const STAmount& saTakerPays, const STAmount& saTakerGets,
STAmount& saTakerPaid, STAmount& saTakerGot)
{
saOfferGets.throwComparable(saTakerPays);
offerIn.throwComparable(paid);
assert(!saOfferFunds.isZero() && !saTakerFunds.isZero()); // Must have funds.
assert(!saOfferGets.isZero() && !saOfferPays.isZero()); // Must not be a null offer.
if (offerIn.isZero() || offerOut.isZero())
{ // If the offer is invalid or empty, you pay nothing and get nothing and the offer is dead
offerIn.zero();
offerOut.zero();
paid.zero();
return STAmount();
}
// Amount offer can pay out, limited by offer and funds.
STAmount saOfferPaysAvailable = saOfferFunds < saOfferPays ? saOfferFunds : saOfferPays;
// If you pay nothing, you get nothing. Offer is untouched
if (paid.isZero()) return STAmount();
// Amount offer needs to get to be complete, limited by offer funds.
STAmount saOfferGetsAvailable =
saOfferFunds == saOfferPays
? saOfferGets // Offer was fully funded, avoid shenanigans.
: divide(multiply(saTakerPays, saOfferPaysAvailable, uint160(1)), saTakerGets, saOfferGets.getCurrency());
if (paid >= offerIn)
{ // If you pay equal to or more than the offer amount, you get the whole offer and pay its input
STAmount ret(offerOut);
paid = offerIn;
offerOut.zero();
offerIn.zero();
return ret;
}
// partial satisfaction of a normal offer
STAmount ret = divide(multiply(paid, offerOut, uint160(1)), offerIn, offerOut.getCurrency());
offerOut -= ret;
offerIn -= paid;
if (offerOut.isZero() || offerIn.isZero())
if (saTakerFunds >= saOfferGetsAvailable)
{
offerIn.zero();
offerOut.zero();
// Taker gets all of offer available.
saTakerPaid = saOfferGetsAvailable; // Taker paid what offer could get.
saTakerGot = saOfferPaysAvailable; // Taker got what offer could pay.
return true; // No left over offer.
}
return ret;
// Taker only get's a portion of offer.
saTakerPaid = saTakerFunds; // Taker paid all he had.
saTakerGot = divide(multiply(saTakerFunds, saOfferPaysAvailable, uint160(1)), saOfferGetsAvailable, saOfferPays.getCurrency());
return saTakerGot >= saOfferPaysAvailable;
}
STAmount STAmount::getPay(const STAmount& offerOut, const STAmount& offerIn, const STAmount& needed)

View File

@@ -156,10 +156,10 @@ public:
static Ledger::pointer loadByHash(const uint256& ledgerHash);
// next/prev function
SLE::pointer getNextSLE(const uint256& hash); // first node >hash
SLE::pointer getNextSLE(const uint256& hash, const uint256& max); // first node >hash, <max
SLE::pointer getPrevSLE(const uint256& hash); // last node <hash
SLE::pointer getPrevSLE(const uint256& hash, const uint256& min); // last node <hash, >min
SLE::pointer getNextSLE(const uint256& uHash); // first node >hash
SLE::pointer getNextSLE(const uint256& uHash, const uint256& uEnd); // first node >hash, <end
SLE::pointer getPrevSLE(const uint256& uHash); // last node <hash
SLE::pointer getPrevSLE(const uint256& uHash, const uint256& uBegin); // last node <hash, >begin
// index calculation functions
static uint256 getAccountRootIndex(const uint160& uAccountID);
@@ -232,8 +232,9 @@ public:
// Quality
//
static uint256 getQualityIndex(const uint256& uBase, const uint64 uNodeDir=0);
static uint256 getQualityNext(const uint256& uBase);
static uint256 getQualityIndex(const uint256& uBase, const uint64 uNodeDir=0);
static uint256 getQualityNext(const uint256& uBase);
static uint64 getQuality(const uint256& uBase);
//
// Ripple functions : credit lines

View File

@@ -15,6 +15,11 @@ uint256 Ledger::getQualityIndex(const uint256& uBase, const uint64 uNodeDir)
return uNode;
}
uint64 Ledger::getQuality(const uint256& uBase)
{
return be64toh(((uint64*) uBase.end())[-1]);
}
uint256 Ledger::getQualityNext(const uint256& uBase)
{
static uint256 uNext("10000000000000000");

View File

@@ -46,34 +46,34 @@ LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SLE::pointer entry)
return lepOKAY;
}
SLE::pointer Ledger::getNextSLE(const uint256& hash)
SLE::pointer Ledger::getNextSLE(const uint256& uHash)
{
SHAMapItem::pointer node = mAccountStateMap->peekNextItem(hash);
SHAMapItem::pointer node = mAccountStateMap->peekNextItem(uHash);
if (!node)
return SLE::pointer();
return boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
}
SLE::pointer Ledger::getNextSLE(const uint256& hash, const uint256& max)
SLE::pointer Ledger::getNextSLE(const uint256& uHash, const uint256& uEnd)
{
SHAMapItem::pointer node = mAccountStateMap->peekNextItem(hash);
if ((!node) || (node->getTag() > max))
SHAMapItem::pointer node = mAccountStateMap->peekNextItem(uHash);
if ((!node) || (node->getTag() > uEnd))
return SLE::pointer();
return boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
}
SLE::pointer Ledger::getPrevSLE(const uint256& hash)
SLE::pointer Ledger::getPrevSLE(const uint256& uHash)
{
SHAMapItem::pointer node = mAccountStateMap->peekPrevItem(hash);
SHAMapItem::pointer node = mAccountStateMap->peekPrevItem(uHash);
if (!node)
return SLE::pointer();
return boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
}
SLE::pointer Ledger::getPrevSLE(const uint256& hash, const uint256& min)
SLE::pointer Ledger::getPrevSLE(const uint256& uHash, const uint256& uBegin)
{
SHAMapItem::pointer node = mAccountStateMap->peekNextItem(hash);
if ((!node) || (node->getTag() < min))
SHAMapItem::pointer node = mAccountStateMap->peekNextItem(uHash);
if ((!node) || (node->getTag() < uBegin))
return SLE::pointer();
return boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
}

View File

@@ -330,7 +330,11 @@ public:
// Someone is offering X for Y, I try to pay Z, how much do I get?
// And what's left of the offer? And how much do I actually pay?
static STAmount getClaimed(STAmount& offerOut, STAmount& offerIn, STAmount& paid);
static bool applyOffer(
const STAmount& saOfferFunds, const STAmount& saTakerFunds,
const STAmount& saOfferPays, const STAmount& saOfferGets,
const STAmount& saTakerPays, const STAmount& saTakerGets,
STAmount& saTakerPaid, STAmount& saTakerGot);
// Someone is offering X for Y, I need Z, how much do I pay
static STAmount getPay(const STAmount& offerOut, const STAmount& offerIn, const STAmount& needed);