diff --git a/src/Amount.cpp b/src/Amount.cpp index ac987ce567..068e1f8e43 100644 --- a/src/Amount.cpp +++ b/src/Amount.cpp @@ -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) diff --git a/src/Ledger.h b/src/Ledger.h index 9811a83516..66f351c42f 100644 --- a/src/Ledger.h +++ b/src/Ledger.h @@ -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, min + SLE::pointer getNextSLE(const uint256& uHash); // first node >hash + SLE::pointer getNextSLE(const uint256& uHash, const uint256& uEnd); // first 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 diff --git a/src/LedgerIndex.cpp b/src/LedgerIndex.cpp index 79ec76bd33..91365ef9b9 100644 --- a/src/LedgerIndex.cpp +++ b/src/LedgerIndex.cpp @@ -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"); diff --git a/src/LedgerNode.cpp b/src/LedgerNode.cpp index d7345d1224..bf580452e3 100644 --- a/src/LedgerNode.cpp +++ b/src/LedgerNode.cpp @@ -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(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(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(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(node->peekSerializer(), node->getTag()); } diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index 3d8bd3f7f5..3739473a6c 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -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);