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

This commit is contained in:
jed
2012-07-18 21:59:19 -07:00
4 changed files with 132 additions and 43 deletions

View File

@@ -6,6 +6,7 @@
#include <boost/test/unit_test.hpp>
#include "Config.h"
#include "Log.h"
#include "SerializedTypes.h"
#include "utils.h"
@@ -744,7 +745,7 @@ uint64 STAmount::getRate(const STAmount& offerOut, const STAmount& offerIn)
// Taker gets all taker can pay for with saTakerFunds, limited by saOfferPays and saOfferFunds.
// --> saOfferFunds: Limit for saOfferPays
// --> saTakerFunds: Limit for saOfferGets
// --> saTakerFunds: Limit for saOfferGets : How much taker really wants. : Driver
// --> 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.
@@ -766,26 +767,39 @@ bool STAmount::applyOffer(
// Amount offer can pay out, limited by offer and funds.
STAmount saOfferPaysAvailable = saOfferFunds < saOfferPays ? saOfferFunds : saOfferPays;
// Amount offer needs to get to be complete, limited by offer funds.
// Amount offer can get in proportion, 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 (saTakerFunds >= saOfferGetsAvailable)
if (saOfferGets == saOfferGetsAvailable && saTakerFunds >= saOfferGets)
{
// Taker gets all of offer available.
saTakerPaid = saOfferGets; // Taker paid what offer could get.
saTakerGot = saOfferPays; // Taker got what offer could pay.
Log(lsINFO) << "applyOffer: took all outright";
}
else if (saTakerFunds >= saOfferGetsAvailable)
{
// 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.
Log(lsINFO) << "applyOffer: took all available";
}
else
{
// 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());
Log(lsINFO) << "applyOffer: saTakerGot=" << saTakerGot.getFullText();
Log(lsINFO) << "applyOffer: saOfferPaysAvailable=" << saOfferPaysAvailable.getFullText();
}
// 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;
return saTakerGot >= saOfferPays;
}
STAmount STAmount::getPay(const STAmount& offerOut, const STAmount& offerIn, const STAmount& needed)
@@ -838,6 +852,23 @@ STAmount STAmount::deserialize(SerializerIterator& it)
return ret;
}
std::string STAmount::getFullText() const
{
if (mIsNative)
{
return str(boost::format("%s " SYSTEM_CURRENCY_CODE) % getText());
}
else
{
return str(boost::format("%s %s/%s %dE%d" )
% getText()
% getHumanCurrency()
% NewcoinAddress::createHumanAccountID(mIssuer)
% getMantissa()
% getExponent());
}
}
Json::Value STAmount::getJson(int) const
{
Json::Value elem(Json::objectValue);
@@ -851,7 +882,8 @@ Json::Value STAmount::getJson(int) const
if (!mIssuer.isZero())
elem["issuer"] = NewcoinAddress::createHumanAccountID(mIssuer);
}else
}
else
{
elem=getText();
}
@@ -1037,10 +1069,22 @@ BOOST_AUTO_TEST_CASE( CustomCurrency_test )
if (STAmount(currency,31,-1).getText() != "3.1") BOOST_FAIL("STAmount fail");
if (STAmount(currency,31,-2).getText() != "0.31") BOOST_FAIL("STAmount fail");
if (STAmount::multiply(STAmount(currency, 20) , STAmount(3), currency).getText() != "60")
if (STAmount::multiply(STAmount(currency, 20), STAmount(3), currency).getText() != "60")
BOOST_FAIL("STAmount multiply fail");
if (STAmount::multiply(STAmount(currency, 20) , STAmount(3), uint160()).getText() != "60")
if (STAmount::multiply(STAmount(currency, 20), STAmount(3), uint160()).getText() != "60")
BOOST_FAIL("STAmount multiply fail");
if (STAmount::multiply(STAmount(20), STAmount(3), currency).getText() != "60")
BOOST_FAIL("STAmount multiply fail");
if (STAmount::multiply(STAmount(20), STAmount(3), uint160()).getText() != "60")
BOOST_FAIL("STAmount multiply fail");
if (STAmount::divide(STAmount(currency, 60) , STAmount(3), currency).getText() != "20")
BOOST_FAIL("STAmount divide fail");
if (STAmount::divide(STAmount(currency, 60) , STAmount(3), uint160()).getText() != "20")
BOOST_FAIL("STAmount divide fail");
if (STAmount::divide(STAmount(currency, 60) , STAmount(currency, 3), currency).getText() != "20")
BOOST_FAIL("STAmount divide fail");
if (STAmount::divide(STAmount(currency, 60) , STAmount(currency, 3), uint160()).getText() != "20")
BOOST_FAIL("STAmount divide fail");
BOOST_TEST_MESSAGE("Amount CC Complete");
}

View File

@@ -830,7 +830,8 @@ Json::Value RPCServer::doNicknameSet(const Json::Value& params)
return obj;
}
// offer_create <seed> <paying_account> <taker_pays_amount> <taker_pays_currency> <taker_pays_issuer> <takers_gets_amount> <takers_gets_currency> <takers_gets_issuer> <expires> [passive]
// offer_create <seed> <paying_account> <takers_gets_amount> <takers_gets_currency> <takers_gets_issuer> <taker_pays_amount> <taker_pays_currency> <taker_pays_issuer> <expires> [passive]
// *offering* for *wants*
Json::Value RPCServer::doOfferCreate(const Json::Value &params)
{
NewcoinAddress naSeed;
@@ -848,22 +849,22 @@ Json::Value RPCServer::doOfferCreate(const Json::Value &params)
{
return RPCError(rpcSRC_ACT_MALFORMED);
}
else if (!saTakerPays.setValue(params[2u].asString(), params[3u].asString()))
{
return RPCError(rpcPAYS_AMT_MALFORMED);
}
else if (!naTakerPaysID.setAccountID(params[4u].asString()))
{
return RPCError(rpcPAYS_ACT_MALFORMED);
}
else if (!saTakerGets.setValue(params[5u].asString(), params[6u].asString()))
else if (!saTakerGets.setValue(params[2u].asString(), params[3u].asString()))
{
return RPCError(rpcGETS_AMT_MALFORMED);
}
else if (!naTakerGetsID.setAccountID(params[7u].asString()))
else if (!naTakerGetsID.setAccountID(params[4u].asString()))
{
return RPCError(rpcGETS_ACT_MALFORMED);
}
else if (!saTakerPays.setValue(params[5u].asString(), params[6u].asString()))
{
return RPCError(rpcPAYS_AMT_MALFORMED);
}
else if (!naTakerPaysID.setAccountID(params[7u].asString()))
{
return RPCError(rpcPAYS_ACT_MALFORMED);
}
else if (params.size() == 10 && params[9u].asString() != "passive")
{
return RPCError(rpcINVALID_PARAMS);

View File

@@ -261,6 +261,7 @@ public:
SerializedTypeID getSType() const { return STI_AMOUNT; }
std::string getText() const;
std::string getRaw() const;
std::string getFullText() const;
void add(Serializer& s) const;
int getExponent() const { return mOffset; }

View File

@@ -12,9 +12,9 @@
#include "../json/writer.h"
#include "Config.h"
#include "Log.h"
#include "TransactionFormats.h"
#include "utils.h"
#include "Log.h"
// Small for testing, should likely be 32 or 64.
#define DIR_NODE_MAX 2
@@ -128,7 +128,7 @@ STAmount TransactionEngine::accountHolds(const uint160& uAccountID, const uint16
saAmount = rippleHolds(uAccountID, uCurrency, uIssuerID);
Log(lsINFO) << "accountHolds: "
<< saAmount.getText()
<< saAmount.getFullText()
<< " : "
<< STAmount::createHumanCurrency(uCurrency)
<< "/"
@@ -273,9 +273,26 @@ STAmount TransactionEngine::accountSend(const uint160& uSenderID, const uint160&
SLE::pointer sleSender = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uSenderID));
SLE::pointer sleReceiver = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uReceiverID));
Log(lsINFO) << str(boost::format("accountSend> %s (%s) -> %s (%s) : %s")
% NewcoinAddress::createHumanAccountID(uSenderID)
% (sleSender->getIValueFieldAmount(sfBalance)).getFullText()
% NewcoinAddress::createHumanAccountID(uReceiverID)
% (sleReceiver->getIValueFieldAmount(sfBalance)).getFullText()
% saAmount.getFullText());
sleSender->setIFieldAmount(sfBalance, sleSender->getIValueFieldAmount(sfBalance) - saAmount);
sleReceiver->setIFieldAmount(sfBalance, sleReceiver->getIValueFieldAmount(sfBalance) + saAmount);
Log(lsINFO) << str(boost::format("accountSend< %s (%s) -> %s (%s) : %s")
% NewcoinAddress::createHumanAccountID(uSenderID)
% (sleSender->getIValueFieldAmount(sfBalance)).getFullText()
% NewcoinAddress::createHumanAccountID(uReceiverID)
% (sleReceiver->getIValueFieldAmount(sfBalance)).getFullText()
% saAmount.getFullText());
entryModify(sleSender);
entryModify(sleReceiver);
saActualCost = saAmount;
}
else
@@ -1930,11 +1947,10 @@ TransactionEngineResult TransactionEngine::doInvoice(const SerializedTransaction
return tenUNKNOWN;
}
// Take as much as possible. Adjusts account balances.
// 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 wanted (w/ issuer)
// --> saTakerPays: What the taker offers (w/ issuer)
// --> saTakerGets: What the taker wanted (w/ issuer)
// --> saTakerFund: What taker can afford
// <-- saTakerPaid: What taker paid not including fees. To reduce an offer.
// <-- saTakerGot: What taker got not including fees. To reduce an offer.
// <-- terResult: terSUCCESS or terNO_ACCOUNT
@@ -2017,6 +2033,12 @@ TransactionEngineResult TransactionEngine::takeOffers(
STAmount saOfferPays = sleOffer->getIValueFieldAmount(sfTakerGets);
STAmount saOfferGets = sleOffer->getIValueFieldAmount(sfTakerPays);
if (sleOffer->getIFieldPresent(sfGetsIssuer))
saOfferPays.setIssuer(sleOffer->getIValueFieldAccount(sfGetsIssuer).getAccountID());
if (sleOffer->getIFieldPresent(sfPaysIssuer))
saOfferGets.setIssuer(sleOffer->getIValueFieldAccount(sfPaysIssuer).getAccountID());
if (sleOffer->getIFieldPresent(sfExpiration) && sleOffer->getIFieldU32(sfExpiration) <= mLedger->getParentCloseTimeNC())
{
// Offer is expired. Delete it.
@@ -2037,8 +2059,7 @@ TransactionEngineResult TransactionEngine::takeOffers(
{
// Get offer funds available.
if (sleOffer->getIFieldPresent(sfPaysIssuer))
saOfferPays.setIssuer(sleOffer->getIValueFieldAccount(sfPaysIssuer).getAccountID());
Log(lsINFO) << "takeOffers: saOfferPays=" << saOfferPays.getJson(0);
STAmount saOfferFunds = accountFunds(uOfferOwnerID, saOfferPays);
STAmount saTakerFunds = accountFunds(uTakerAccountID, saTakerPays);
@@ -2055,14 +2076,34 @@ TransactionEngineResult TransactionEngine::takeOffers(
}
else
{
STAmount saPay = saTakerPays - saTakerPaid;
if (saTakerFunds < saPay)
saPay = saTakerFunds;
STAmount saSubTakerPaid;
STAmount saSubTakerGot;
Log(lsINFO) << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText();
Log(lsINFO) << "takeOffers: applyOffer: saTakerPaid: " << saTakerPaid.getFullText();
Log(lsINFO) << "takeOffers: applyOffer: saTakerFunds: " << saTakerFunds.getFullText();
Log(lsINFO) << "takeOffers: applyOffer: saOfferFunds: " << saOfferFunds.getFullText();
Log(lsINFO) << "takeOffers: applyOffer: saPay: " << saPay.getFullText();
Log(lsINFO) << "takeOffers: applyOffer: saOfferPays: " << saOfferPays.getFullText();
Log(lsINFO) << "takeOffers: applyOffer: saOfferGets: " << saOfferGets.getFullText();
Log(lsINFO) << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText();
Log(lsINFO) << "takeOffers: applyOffer: saTakerGets: " << saTakerGets.getFullText();
bool bOfferDelete = STAmount::applyOffer(
saOfferFunds, saTakerFunds,
saOfferPays, saOfferGets,
saTakerPays, saTakerGets,
saSubTakerPaid, saSubTakerGot);
saOfferFunds,
saPay, // Driver XXX need to account for fees.
saOfferPays,
saOfferGets,
saTakerPays,
saTakerGets,
saSubTakerPaid,
saSubTakerGot);
Log(lsINFO) << "takeOffers: applyOffer: saSubTakerPaid: " << saSubTakerPaid.getFullText();
Log(lsINFO) << "takeOffers: applyOffer: saSubTakerGot: " << saSubTakerGot.getFullText();
// Adjust offer
if (bOfferDelete)
@@ -2115,10 +2156,10 @@ Log(lsWARNING) << "doOfferCreate> " << txn.getJson(0);
uint160 uGetsIssuerID = txn.getITFieldAccount(sfGetsIssuer);
STAmount saTakerPays = txn.getITFieldAmount(sfTakerPays);
saTakerPays.setIssuer(uPaysIssuerID);
Log(lsWARNING) << "doOfferCreate: saTakerPays=" << saTakerPays.getJson(0);
Log(lsWARNING) << "doOfferCreate: saTakerPays=" << saTakerPays.getFullText();
STAmount saTakerGets = txn.getITFieldAmount(sfTakerGets);
saTakerGets.setIssuer(uGetsIssuerID);
Log(lsWARNING) << "doOfferCreate: saTakerGets=" << saTakerGets.getJson(0);
Log(lsWARNING) << "doOfferCreate: saTakerGets=" << saTakerGets.getFullText();
uint32 uExpiration = txn.getITFieldU32(sfExpiration);
bool bHaveExpiration = txn.getITFieldPresent(sfExpiration);
uint32 uSequence = txn.getSequence();
@@ -2218,21 +2259,23 @@ Log(lsWARNING) << "doOfferCreate: saTakerGets=" << saTakerGets.getJson(0);
);
Log(lsWARNING) << "doOfferCreate: takeOffers=" << terResult;
Log(lsWARNING) << "doOfferCreate: takeOffers: saOfferPaid=" << saOfferPaid.getText();
Log(lsWARNING) << "doOfferCreate: takeOffers: saOfferGot=" << saOfferGot.getText();
Log(lsWARNING) << "doOfferCreate: takeOffers: saOfferPaid=" << saOfferPaid.getFullText();
Log(lsWARNING) << "doOfferCreate: takeOffers: saOfferGot=" << saOfferGot.getFullText();
Log(lsWARNING) << "doOfferCreate: takeOffers: saTakerPays=" << saTakerPays.getFullText();
Log(lsWARNING) << "doOfferCreate: takeOffers: saTakerGets=" << saTakerGets.getFullText();
if (terSUCCESS == terResult)
{
saTakerGets -= saOfferPaid; // Reduce payout to takers by what srcAccount just paid.
saTakerPays -= saOfferGot; // Reduce payin from takers by what offer just got.
saTakerGets -= saOfferPaid; // Reduce payout to takers by what srcAccount just paid.
}
}
Log(lsWARNING) << "doOfferCreate: takeOffers: saTakerPays=" << saTakerPays.getText();
Log(lsWARNING) << "doOfferCreate: takeOffers: saTakerGets=" << saTakerGets.getJson(0);
Log(lsWARNING) << "doOfferCreate: takeOffers: saTakerGets=" << NewcoinAddress::createHumanAccountID(saTakerGets.getIssuer());
Log(lsWARNING) << "doOfferCreate: takeOffers: saTakerPays=" << saTakerPays.getFullText();
Log(lsWARNING) << "doOfferCreate: takeOffers: saTakerGets=" << saTakerGets.getFullText();
Log(lsWARNING) << "doOfferCreate: takeOffers: saTakerGets=" << NewcoinAddress::createHumanAccountID(saTakerGets.getIssuer());
Log(lsWARNING) << "doOfferCreate: takeOffers: mTxnAccountID=" << NewcoinAddress::createHumanAccountID(mTxnAccountID);
Log(lsWARNING) << "doOfferCreate: takeOffers: funds=" << accountFunds(mTxnAccountID, saTakerGets).getText();
Log(lsWARNING) << "doOfferCreate: takeOffers: funds=" << accountFunds(mTxnAccountID, saTakerGets).getFullText();
// Log(lsWARNING) << "doOfferCreate: takeOffers: uPaysIssuerID=" << NewcoinAddress::createHumanAccountID(uPaysIssuerID);
// Log(lsWARNING) << "doOfferCreate: takeOffers: uGetsIssuerID=" << NewcoinAddress::createHumanAccountID(uGetsIssuerID);