Merge branch 'master' of github.com:jedmccaleb/NewCoin

This commit is contained in:
JoelKatz
2013-03-22 08:09:20 -07:00
5 changed files with 206 additions and 139 deletions

View File

@@ -328,6 +328,25 @@ Json::Value RPCParser::parseGetCounts(const Json::Value& jvParams)
return jvRequest;
}
// json <command> <json>
Json::Value RPCParser::parseJson(const Json::Value& jvParams)
{
Json::Reader reader;
Json::Value jvRequest;
cLog(lsTRACE) << "RPC method: " << jvParams[0u];
cLog(lsTRACE) << "RPC json: " << jvParams[1u];
if (reader.parse(jvParams[1u].asString(), jvRequest))
{
jvRequest["method"] = jvParams[0u];
return jvRequest;
}
return rpcError(rpcINVALID_PARAMS);
}
// ledger [id|index|current|closed|validated] [full]
Json::Value RPCParser::parseLedger(const Json::Value& jvParams)
{
@@ -631,6 +650,7 @@ Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams)
{ "connect", &RPCParser::parseConnect, 1, 2 },
{ "consensus_info", &RPCParser::parseAsIs, 0, 0 },
{ "get_counts", &RPCParser::parseGetCounts, 0, 1 },
{ "json", &RPCParser::parseJson, 2, 2 },
{ "ledger", &RPCParser::parseLedger, 0, 2 },
{ "ledger_accept", &RPCParser::parseAsIs, 0, 0 },
{ "ledger_closed", &RPCParser::parseAsIs, 0, 0 },

View File

@@ -23,9 +23,10 @@ protected:
#endif
Json::Value parseEvented(const Json::Value& jvParams);
Json::Value parseGetCounts(const Json::Value& jvParams);
Json::Value parseInternal(const Json::Value& jvParams);
Json::Value parseJson(const Json::Value& jvParams);
Json::Value parseLedger(const Json::Value& jvParams);
Json::Value parseLedgerId(const Json::Value& jvParams);
Json::Value parseInternal(const Json::Value& jvParams);
#if ENABLE_INSECURE
Json::Value parseLogin(const Json::Value& jvParams);
#endif

View File

@@ -7,6 +7,80 @@
SETUP_LOG();
// Make sure an offer is still valid. If not, mark it unfunded.
bool OfferCreateTransactor::bValidOffer(
SLE::ref sleOfferDir,
const uint256& uOfferIndex,
const uint160& uOfferOwnerID,
const STAmount& saOfferPays,
const STAmount& saOfferGets,
const uint160& uTakerAccountID,
boost::unordered_set<uint256>& usOfferUnfundedFound,
boost::unordered_set<uint256>& usOfferUnfundedBecame,
boost::unordered_set<uint160>& usAccountTouched,
STAmount& saOfferFunds) { // <--
bool bValid;
if (sleOfferDir->isFieldPresent(sfExpiration) && sleOfferDir->getFieldU32(sfExpiration) <= mEngine->getLedger()->getParentCloseTimeNC())
{
// Offer is expired. Expired offers are considered unfunded. Delete it.
cLog(lsINFO) << "bValidOffer: encountered expired offer";
usOfferUnfundedFound.insert(uOfferIndex);
bValid = false;
}
else if (uOfferOwnerID == uTakerAccountID)
{
// Would take own offer. Consider old offer expired. Delete it.
cLog(lsINFO) << "bValidOffer: encountered taker's own old offer";
usOfferUnfundedFound.insert(uOfferIndex);
bValid = false;
}
else if (!saOfferGets.isPositive() || !saOfferPays.isPositive())
{
// Offer has bad amounts. Consider offer expired. Delete it.
cLog(lsWARNING) << boost::str(boost::format("bValidOffer: BAD OFFER: saOfferPays=%s saOfferGets=%s")
% saOfferPays % saOfferGets);
usOfferUnfundedFound.insert(uOfferIndex);
}
else
{
cLog(lsINFO) << "bValidOffer: saOfferPays=" << saOfferPays.getFullText();
saOfferFunds = mEngine->getNodes().accountFunds(uOfferOwnerID, saOfferPays);
if (!saOfferFunds.isPositive())
{
// Offer is unfunded, possibly due to previous balance action.
cLog(lsINFO) << "bValidOffer: offer unfunded: delete";
boost::unordered_set<uint160>::iterator account = usAccountTouched.find(uOfferOwnerID);
if (account != usAccountTouched.end())
{
// Previously touched account.
usOfferUnfundedBecame.insert(uOfferIndex); // Delete unfunded offer on success.
}
else
{
// Never touched source account.
usOfferUnfundedFound.insert(uOfferIndex); // Delete found unfunded offer when possible.
}
bValid = false;
}
else
{
bValid = true;
}
}
return bValid;
}
// Take as much as possible. Adjusts account balances. Charges fees on top to taker.
// --> uBookBase: The order book to take against.
// --> saTakerPays: What the taker offers (w/ issuer)
@@ -28,7 +102,7 @@ TER OfferCreateTransactor::takeOffers(
bool& bUnfunded)
{
// The book has the most elements. Take the perspective of the book.
// Book is ordered for taker: taker pays / taker gets, < is better
// Book is ordered for taker: taker pays / taker gets (smaller is better)
// The order is for the other books currencys for get and pays are opposites.
// We want the same ratio for the respective currencies.
@@ -141,162 +215,121 @@ TER OfferCreateTransactor::takeOffers(
STAmount saOfferPays = sleOffer->getFieldAmount(sfTakerGets);
STAmount saOfferGets = sleOffer->getFieldAmount(sfTakerPays);
if (sleOffer->isFieldPresent(sfExpiration) && sleOffer->getFieldU32(sfExpiration) <= mEngine->getLedger()->getParentCloseTimeNC())
{
// Offer is expired. Expired offers are considered unfunded. Delete it.
cLog(lsINFO) << "takeOffers: encountered expired offer";
STAmount saOfferFunds; // Funds of offer owner to payout.
bool bValid;
usOfferUnfundedFound.insert(uOfferIndex);
}
else if (uOfferOwnerID == uTakerAccountID)
{
// Would take own offer. Consider old offer expired. Delete it.
cLog(lsINFO) << "takeOffers: encountered taker's own old offer";
bValid = bValidOffer(
sleOfferDir, uOfferIndex, uOfferOwnerID, saOfferPays, saOfferGets,
uTakerAccountID,
usOfferUnfundedFound, usOfferUnfundedBecame, usAccountTouched,
saOfferFunds);
usOfferUnfundedBecame.insert(uOfferIndex);
}
else if (!saOfferGets.isPositive() || !saOfferPays.isPositive())
{
// Offer has bad amounts. Consider offer expired. Delete it.
cLog(lsWARNING) << boost::str(boost::format("takeOffers: BAD OFFER: saOfferPays=%s saOfferGets=%s")
% saOfferPays % saOfferGets);
if (bValid) {
STAmount saSubTakerPaid;
STAmount saSubTakerGot;
STAmount saTakerIssuerFee;
STAmount saOfferIssuerFee;
STAmount saOfferRate = STAmount::setRate(uTipQuality);
usOfferUnfundedFound.insert(uOfferIndex);
}
else
{
// Get offer funds available.
cLog(lsINFO) << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerPaid: " << saTakerPaid.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerFunds: " << saTakerFunds.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saOfferFunds: " << saOfferFunds.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saOfferPays: " << saOfferPays.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saOfferGets: " << saOfferGets.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saOfferRate: " << saOfferRate.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saSubTakerPays: " << saSubTakerPays.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saSubTakerGets: " << saSubTakerGets.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerGets: " << saTakerGets.getFullText();
cLog(lsINFO) << "takeOffers: saOfferPays=" << saOfferPays.getFullText();
bool bOfferDelete = STAmount::applyOffer(
lesActive.rippleTransferRate(uTakerAccountID, uOfferOwnerID, uTakerPaysAccountID),
lesActive.rippleTransferRate(uOfferOwnerID, uTakerAccountID, uTakerGetsAccountID),
saOfferRate,
saOfferFunds,
saTakerFunds,
saOfferPays,
saOfferGets,
saSubTakerPays,
saSubTakerGets,
saSubTakerPaid,
saSubTakerGot,
saTakerIssuerFee,
saOfferIssuerFee);
STAmount saOfferFunds = lesActive.accountFunds(uOfferOwnerID, saOfferPays);
SLE::pointer sleOfferAccount; // Owner of offer.
cLog(lsINFO) << "takeOffers: applyOffer: saSubTakerPaid: " << saSubTakerPaid.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saSubTakerGot: " << saSubTakerGot.getFullText();
if (!saOfferFunds.isPositive()) // Includes zero.
// Adjust offer
// Offer owner will pay less. Subtract what taker just got.
sleOffer->setFieldAmount(sfTakerGets, saOfferPays -= saSubTakerGot);
// Offer owner will get less. Subtract what owner just paid.
sleOffer->setFieldAmount(sfTakerPays, saOfferGets -= saSubTakerPaid);
mEngine->entryModify(sleOffer);
if (bOfferDelete)
{
// Offer is unfunded, possibly due to previous balance action.
cLog(lsINFO) << "takeOffers: offer unfunded: delete";
// Offer now fully claimed or now unfunded.
cLog(lsINFO) << "takeOffers: Offer claimed: Delete.";
boost::unordered_set<uint160>::iterator account = usAccountTouched.find(uOfferOwnerID);
if (account != usAccountTouched.end())
usOfferUnfundedBecame.insert(uOfferIndex); // Delete unfunded offer on success.
// Offer owner's account is no longer pristine.
usAccountTouched.insert(uOfferOwnerID);
}
else if (saSubTakerGot)
{
cLog(lsINFO) << "takeOffers: Offer partial claim.";
if (!saOfferPays.isPositive() || !saOfferGets.isPositive())
{
// Previously touched account.
usOfferUnfundedBecame.insert(uOfferIndex); // Delete unfunded offer on success.
}
else
{
// Never touched source account.
usOfferUnfundedFound.insert(uOfferIndex); // Delete found unfunded offer when possible.
cLog(lsWARNING) << "takeOffers: ILLEGAL OFFER RESULT.";
bUnfunded = true;
terResult = bOpenLedger ? telFAILED_PROCESSING : tecFAILED_PROCESSING;
}
}
else
{
STAmount saSubTakerPaid;
STAmount saSubTakerGot;
STAmount saTakerIssuerFee;
STAmount saOfferIssuerFee;
STAmount saOfferRate = STAmount::setRate(uTipQuality);
// Taker got nothing, probably due to rounding. Consider taker unfunded.
cLog(lsINFO) << "takeOffers: No claim.";
cLog(lsINFO) << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerPaid: " << saTakerPaid.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerFunds: " << saTakerFunds.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saOfferFunds: " << saOfferFunds.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saOfferPays: " << saOfferPays.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saOfferGets: " << saOfferGets.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saOfferRate: " << saOfferRate.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saSubTakerPays: " << saSubTakerPays.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saSubTakerGets: " << saSubTakerGets.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerGets: " << saTakerGets.getFullText();
bUnfunded = true;
terResult = tesSUCCESS; // Done.
}
bool bOfferDelete = STAmount::applyOffer(
lesActive.rippleTransferRate(uTakerAccountID, uOfferOwnerID, uTakerPaysAccountID),
lesActive.rippleTransferRate(uOfferOwnerID, uTakerAccountID, uTakerGetsAccountID),
saOfferRate,
saOfferFunds,
saTakerFunds,
saOfferPays,
saOfferGets,
saSubTakerPays,
saSubTakerGets,
saSubTakerPaid,
saSubTakerGot,
saTakerIssuerFee,
saOfferIssuerFee);
assert(uTakerGetsAccountID == saSubTakerGot.getIssuer());
assert(uTakerPaysAccountID == saSubTakerPaid.getIssuer());
cLog(lsINFO) << "takeOffers: applyOffer: saSubTakerPaid: " << saSubTakerPaid.getFullText();
if (!bUnfunded)
{
// Distribute funds. The sends charge appropriate fees which are implied by offer.
terResult = lesActive.accountSend(uOfferOwnerID, uTakerAccountID, saSubTakerGot); // Offer owner pays taker.
if (tesSUCCESS == terResult)
terResult = lesActive.accountSend(uTakerAccountID, uOfferOwnerID, saSubTakerPaid); // Taker pays offer owner.
// Reduce amount considered paid by taker's rate (not actual cost).
STAmount saTakerCould = saTakerPays - saTakerPaid; // Taker could pay.
if (saTakerFunds < saTakerCould)
saTakerCould = saTakerFunds;
STAmount saTakerUsed = STAmount::multiply(saSubTakerGot, saTakerRate, saTakerPays);
cLog(lsINFO) << "takeOffers: applyOffer: saTakerCould: " << saTakerCould.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saSubTakerGot: " << saSubTakerGot.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerRate: " << saTakerRate.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerUsed: " << saTakerUsed.getFullText();
// Adjust offer
saTakerPaid += std::min(saTakerCould, saTakerUsed);
saTakerGot += saSubTakerGot;
// Offer owner will pay less. Subtract what taker just got.
sleOffer->setFieldAmount(sfTakerGets, saOfferPays -= saSubTakerGot);
// Offer owner will get less. Subtract what owner just paid.
sleOffer->setFieldAmount(sfTakerPays, saOfferGets -= saSubTakerPaid);
mEngine->entryModify(sleOffer);
if (bOfferDelete)
{
// Offer now fully claimed or now unfunded.
cLog(lsINFO) << "takeOffers: Offer claimed: Delete.";
usOfferUnfundedBecame.insert(uOfferIndex); // Delete unfunded offer on success.
// Offer owner's account is no longer pristine.
usAccountTouched.insert(uOfferOwnerID);
}
else if (saSubTakerGot)
{
cLog(lsINFO) << "takeOffers: Offer partial claim.";
if (!saOfferPays.isPositive() || !saOfferGets.isPositive())
{
cLog(lsWARNING) << "takeOffers: ILLEGAL OFFER RESULT.";
bUnfunded = true;
terResult = bOpenLedger ? telFAILED_PROCESSING : tecFAILED_PROCESSING;
}
}
else
{
// Taker got nothing, probably due to rounding. Consider taker unfunded.
cLog(lsINFO) << "takeOffers: No claim.";
bUnfunded = true;
terResult = tesSUCCESS; // Done.
}
assert(uTakerGetsAccountID == saSubTakerGot.getIssuer());
assert(uTakerPaysAccountID == saSubTakerPaid.getIssuer());
if (!bUnfunded)
{
// Distribute funds. The sends charge appropriate fees which are implied by offer.
terResult = lesActive.accountSend(uOfferOwnerID, uTakerAccountID, saSubTakerGot); // Offer owner pays taker.
if (tesSUCCESS == terResult)
terResult = lesActive.accountSend(uTakerAccountID, uOfferOwnerID, saSubTakerPaid); // Taker pays offer owner.
// Reduce amount considered paid by taker's rate (not actual cost).
STAmount saTakerCould = saTakerPays - saTakerPaid; // Taker could pay.
if (saTakerFunds < saTakerCould)
saTakerCould = saTakerFunds;
STAmount saTakerUsed = STAmount::multiply(saSubTakerGot, saTakerRate, saTakerPays);
cLog(lsINFO) << "takeOffers: applyOffer: saTakerCould: " << saTakerCould.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saSubTakerGot: " << saSubTakerGot.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerRate: " << saTakerRate.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerUsed: " << saTakerUsed.getFullText();
saTakerPaid += std::min(saTakerCould, saTakerUsed);
saTakerGot += saSubTakerGot;
if (tesSUCCESS == terResult)
terResult = temUNCERTAIN;
}
if (tesSUCCESS == terResult)
terResult = temUNCERTAIN;
}
}
}

View File

@@ -6,6 +6,18 @@
class OfferCreateTransactor : public Transactor
{
protected:
bool bValidOffer(
SLE::ref sleOfferDir,
const uint256& uOffer,
const uint160& uOfferOwnerID,
const STAmount& saOfferPays,
const STAmount& saOfferGets,
const uint160& uTakerAccountID,
boost::unordered_set<uint256>& usOfferUnfundedFound,
boost::unordered_set<uint256>& usOfferUnfundedBecame,
boost::unordered_set<uint160>& usAccountTouched,
STAmount& saOfferFunds);
TER takeOffers(
const bool bOpenLedger,
const bool bPassive,

View File

@@ -84,6 +84,7 @@ void printHelp(const po::options_description& desc)
cerr << " data_store <key> <value>" << endl;
#endif
cerr << " get_counts" << endl;
cerr << " json <method> <json>" << endl;
cerr << " ledger [<id>|current|closed|validated] [full]" << endl;
cerr << " ledger_accept" << endl;
cerr << " ledger_closed" << endl;