mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
@@ -45,11 +45,16 @@ bool STAmount::currencyFromString(uint160& uDstCurrency, const std::string& sCur
|
||||
}
|
||||
|
||||
// XXX Broken for custom currencies?
|
||||
std::string STAmount::getCurrencyHuman() const
|
||||
std::string STAmount::getHumanCurrency() const
|
||||
{
|
||||
return createHumanCurrency(mCurrency);
|
||||
}
|
||||
|
||||
std::string STAmount::createHumanCurrency(const uint160& uCurrency)
|
||||
{
|
||||
std::string sCurrency;
|
||||
|
||||
if (mIsNative)
|
||||
if (uCurrency.isZero())
|
||||
{
|
||||
return SYSTEM_CURRENCY_CODE;
|
||||
}
|
||||
@@ -57,7 +62,7 @@ std::string STAmount::getCurrencyHuman() const
|
||||
{
|
||||
Serializer s(160/8);
|
||||
|
||||
s.add160(mCurrency);
|
||||
s.add160(uCurrency);
|
||||
|
||||
SerializerIterator sit(s);
|
||||
|
||||
@@ -664,9 +669,6 @@ STAmount STAmount::multiply(const STAmount& v1, const STAmount& v2, const uint16
|
||||
uint64 value1 = v1.mValue, value2 = v2.mValue;
|
||||
int offset1 = v1.mOffset, offset2 = v2.mOffset;
|
||||
|
||||
int finOffset = offset1 + offset2;
|
||||
if ((finOffset > 80) || (finOffset < 22))
|
||||
throw std::runtime_error("multiplication produces out of range result");
|
||||
|
||||
if (v1.mIsNative)
|
||||
{
|
||||
@@ -698,11 +700,15 @@ STAmount STAmount::multiply(const STAmount& v1, const STAmount& v2, const uint16
|
||||
--offset2;
|
||||
}
|
||||
|
||||
int finOffset = offset1 + offset2;
|
||||
if ((finOffset > 80) || (finOffset < -96))
|
||||
throw std::runtime_error("multiplication produces out of range result");
|
||||
|
||||
// Compute (numerator*10 * denominator*10) / 10^18 with rounding
|
||||
CBigNum v;
|
||||
if ((BN_add_word(&v, value1) != 1) ||
|
||||
(BN_mul_word(&v, value2) != 1) ||
|
||||
(BN_div_word(&v, 1000000000000000000ul) == ((BN_ULONG) -1)))
|
||||
(BN_div_word(&v, 100000000000000ul) == ((BN_ULONG) -1)))
|
||||
{
|
||||
throw std::runtime_error("internal bn error");
|
||||
}
|
||||
@@ -836,13 +842,15 @@ Json::Value STAmount::getJson(int) const
|
||||
{
|
||||
Json::Value elem(Json::objectValue);
|
||||
|
||||
|
||||
|
||||
// This is a hack, many places don't specify a currency. STAmount is used just as a value.
|
||||
if (!mIsNative)
|
||||
{
|
||||
elem["value"] = getText();
|
||||
elem["currency"] = getCurrencyHuman();
|
||||
elem["currency"] = getHumanCurrency();
|
||||
|
||||
if (!mIssuer.isZero())
|
||||
elem["issuer"] = NewcoinAddress::createHumanAccountID(mIssuer);
|
||||
|
||||
}else
|
||||
{
|
||||
elem=getText();
|
||||
@@ -1028,6 +1036,12 @@ BOOST_AUTO_TEST_CASE( CustomCurrency_test )
|
||||
if (STAmount(currency,31,1).getText() != "310") BOOST_FAIL("STAmount fail");
|
||||
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")
|
||||
BOOST_FAIL("STAmount multiply fail");
|
||||
if (STAmount::multiply(STAmount(currency, 20) , STAmount(3), uint160()).getText() != "60")
|
||||
BOOST_FAIL("STAmount multiply fail");
|
||||
|
||||
BOOST_TEST_MESSAGE("Amount CC Complete");
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ Json::Value callRPC(const std::string& strMethod, const Json::Value& params)
|
||||
std::string strPost = createHTTPPost(strRequest, mapRequestHeaders);
|
||||
stream << strPost << std::flush;
|
||||
|
||||
std::cout << "post " << strPost << std::endl;
|
||||
// std::cout << "post " << strPost << std::endl;
|
||||
|
||||
// Receive reply
|
||||
std::map<std::string, std::string> mapHeaders;
|
||||
|
||||
@@ -106,9 +106,9 @@ void Config::setup(const std::string& strConf)
|
||||
if (ec)
|
||||
throw std::runtime_error(str(boost::format("Can not create %s") % DATA_DIR));
|
||||
|
||||
std::cerr << "CONFIG FILE: " << CONFIG_FILE << std::endl;
|
||||
std::cerr << "CONFIG DIR: " << CONFIG_DIR << std::endl;
|
||||
std::cerr << "DATA DIR: " << DATA_DIR << std::endl;
|
||||
// std::cerr << "CONFIG FILE: " << CONFIG_FILE << std::endl;
|
||||
// std::cerr << "CONFIG DIR: " << CONFIG_DIR << std::endl;
|
||||
// std::cerr << "DATA DIR: " << DATA_DIR << std::endl;
|
||||
|
||||
//
|
||||
// Defaults
|
||||
@@ -190,7 +190,7 @@ void Config::load()
|
||||
if (smtTmp)
|
||||
{
|
||||
IPS = *smtTmp;
|
||||
sectionEntriesPrint(&IPS, SECTION_IPS);
|
||||
// sectionEntriesPrint(&IPS, SECTION_IPS);
|
||||
}
|
||||
|
||||
(void) sectionSingleB(secConfig, SECTION_VALIDATORS_SITE, VALIDATORS_SITE);
|
||||
|
||||
@@ -230,11 +230,6 @@ bool Ledger::addTransaction(const uint256& txID, const Serializer& txn)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Ledger::hasTransaction(const uint256& transID) const
|
||||
{
|
||||
return mTransactionMap->hasItem(transID);
|
||||
}
|
||||
|
||||
Transaction::pointer Ledger::getTransaction(const uint256& transID) const
|
||||
{
|
||||
SHAMapItem::pointer item = mTransactionMap->peekItem(transID);
|
||||
|
||||
14
src/Ledger.h
14
src/Ledger.h
@@ -151,7 +151,7 @@ public:
|
||||
bool isAcquiringAS(void);
|
||||
|
||||
// Transaction Functions
|
||||
bool hasTransaction(const uint256& TransID) const;
|
||||
bool hasTransaction(const uint256& TransID) const { return mTransactionMap->hasItem(TransID); }
|
||||
Transaction::pointer getTransaction(const uint256& transID) const;
|
||||
|
||||
// high-level functions
|
||||
@@ -167,12 +167,12 @@ public:
|
||||
|
||||
// next/prev function
|
||||
SLE::pointer getSLE(const uint256& uHash);
|
||||
SLE::pointer getFirstSLE();
|
||||
SLE::pointer getLastSLE();
|
||||
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
|
||||
uint256 getFirstLedgerIndex();
|
||||
uint256 getLastLedgerIndex();
|
||||
uint256 getNextLedgerIndex(const uint256& uHash); // first node >hash
|
||||
uint256 getNextLedgerIndex(const uint256& uHash, const uint256& uEnd); // first node >hash, <end
|
||||
uint256 getPrevLedgerIndex(const uint256& uHash); // last node <hash
|
||||
uint256 getPrevLedgerIndex(const uint256& uHash, const uint256& uBegin); // last node <hash, >begin
|
||||
|
||||
// index calculation functions
|
||||
static uint256 getAccountRootIndex(const uint160& uAccountID);
|
||||
|
||||
@@ -180,7 +180,7 @@ bool LCTransaction::updatePosition(int percentTime, bool proposing)
|
||||
{
|
||||
#ifdef LC_DEBUG
|
||||
Log(lsTRACE) << "No change (" << (mOurPosition ? "YES" : "NO") << ") : weight "
|
||||
<< weight << ", seconds " << seconds;
|
||||
<< weight << ", percent " << percentTime;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -191,14 +191,14 @@ bool LCTransaction::updatePosition(int percentTime, bool proposing)
|
||||
|
||||
LedgerConsensus::LedgerConsensus(const uint256& prevLCLHash, Ledger::pointer previousLedger, uint32 closeTime)
|
||||
: mState(lcsPRE_CLOSE), mCloseTime(closeTime), mPrevLedgerHash(prevLCLHash), mPreviousLedger(previousLedger),
|
||||
mCurrentSeconds(0), mClosePercent(0), mHaveCloseTimeConsensus(false)
|
||||
mCurrentMSeconds(0), mClosePercent(0), mHaveCloseTimeConsensus(false)
|
||||
{
|
||||
mValSeed = theConfig.VALIDATION_SEED;
|
||||
Log(lsDEBUG) << "Creating consensus object";
|
||||
Log(lsTRACE) << "LCL:" << previousLedger->getHash().GetHex() <<", ct=" << closeTime;
|
||||
mPreviousProposers = theApp->getOPs().getPreviousProposers();
|
||||
mPreviousSeconds = theApp->getOPs().getPreviousSeconds();
|
||||
assert(mPreviousSeconds);
|
||||
mPreviousMSeconds = theApp->getOPs().getPreviousConvergeTime();
|
||||
assert(mPreviousMSeconds);
|
||||
|
||||
mCloseResolution = ContinuousLedgerTiming::getNextLedgerTimeResolution(
|
||||
previousLedger->getCloseResolution(), previousLedger->getCloseAgree(), previousLedger->getLedgerSeq() + 1);
|
||||
@@ -226,11 +226,11 @@ LedgerConsensus::LedgerConsensus(const uint256& prevLCLHash, Ledger::pointer pre
|
||||
}
|
||||
}
|
||||
|
||||
void LedgerConsensus::takeInitialPosition(Ledger::pointer initialLedger)
|
||||
void LedgerConsensus::takeInitialPosition(Ledger& initialLedger)
|
||||
{
|
||||
SHAMap::pointer initialSet = initialLedger->peekTransactionMap()->snapShot(false);
|
||||
SHAMap::pointer initialSet = initialLedger.peekTransactionMap()->snapShot(false);
|
||||
uint256 txSet = initialSet->getHash();
|
||||
assert (!mHaveCorrectLCL || (initialLedger->getParentHash() == mPreviousLedger->getHash()));
|
||||
assert (!mHaveCorrectLCL || (initialLedger.getParentHash() == mPreviousLedger->getHash()));
|
||||
|
||||
// if any peers have taken a contrary position, process disputes
|
||||
boost::unordered_set<uint256> found;
|
||||
@@ -248,11 +248,12 @@ void LedgerConsensus::takeInitialPosition(Ledger::pointer initialLedger)
|
||||
|
||||
if (mValidating)
|
||||
mOurPosition = boost::make_shared<LedgerProposal>
|
||||
(mValSeed, initialLedger->getParentHash(), txSet, mCloseTime);
|
||||
(mValSeed, initialLedger.getParentHash(), txSet, mCloseTime);
|
||||
else
|
||||
mOurPosition = boost::make_shared<LedgerProposal>(initialLedger->getParentHash(), txSet, mCloseTime);
|
||||
mOurPosition = boost::make_shared<LedgerProposal>(initialLedger.getParentHash(), txSet, mCloseTime);
|
||||
mapComplete(txSet, initialSet, false);
|
||||
if (mProposing) propose(std::vector<uint256>(), std::vector<uint256>());
|
||||
if (mProposing)
|
||||
propose(std::vector<uint256>(), std::vector<uint256>());
|
||||
}
|
||||
|
||||
void LedgerConsensus::createDisputes(SHAMap::pointer m1, SHAMap::pointer m2)
|
||||
@@ -339,18 +340,18 @@ void LedgerConsensus::adjustCount(SHAMap::pointer map, const std::vector<uint160
|
||||
}
|
||||
}
|
||||
|
||||
void LedgerConsensus::statusChange(newcoin::NodeEvent event, Ledger::pointer ledger)
|
||||
void LedgerConsensus::statusChange(newcoin::NodeEvent event, Ledger& ledger)
|
||||
{ // Send a node status change message to our peers
|
||||
newcoin::TMStatusChange s;
|
||||
if (!mHaveCorrectLCL)
|
||||
s.set_newevent(newcoin::neLOST_SYNC);
|
||||
else
|
||||
s.set_newevent(event);
|
||||
s.set_ledgerseq(ledger->getLedgerSeq());
|
||||
s.set_ledgerseq(ledger.getLedgerSeq());
|
||||
s.set_networktime(theApp->getOPs().getNetworkTimeNC());
|
||||
uint256 hash = ledger->getParentHash();
|
||||
uint256 hash = ledger.getParentHash();
|
||||
s.set_ledgerhashprevious(hash.begin(), hash.size());
|
||||
hash = ledger->getHash();
|
||||
hash = ledger.getHash();
|
||||
s.set_ledgerhash(hash.begin(), hash.size());
|
||||
PackedMessage::pointer packet = boost::make_shared<PackedMessage>(s, newcoin::mtSTATUS_CHANGE);
|
||||
theApp->getConnectionPool().relayMessage(NULL, packet);
|
||||
@@ -367,26 +368,25 @@ void LedgerConsensus::statePreClose()
|
||||
bool anyTransactions = theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap()->getHash().isNonZero();
|
||||
int proposersClosed = mPeerPositions.size();
|
||||
|
||||
int sinceClose = theApp->getOPs().getNetworkTimeNC() - theApp->getOPs().getLastCloseNetTime();
|
||||
// This ledger is open. This computes how long since the last ledger closed
|
||||
int sinceClose = 1000 * (theApp->getOPs().getNetworkTimeNC() - theApp->getOPs().getLastCloseNetTime());
|
||||
|
||||
if (sinceClose >= ContinuousLedgerTiming::shouldClose(anyTransactions, mPreviousProposers, proposersClosed,
|
||||
mPreviousSeconds, sinceClose))
|
||||
{ // it is time to close the ledger (swap default and wobble ledgers)
|
||||
Log(lsINFO) << "CLC:: closing ledger";
|
||||
mPreviousMSeconds, sinceClose))
|
||||
{ // it is time to close the ledger
|
||||
Log(lsINFO) << "CLC: closing ledger";
|
||||
mState = lcsESTABLISH;
|
||||
mConsensusStartTime = boost::posix_time::second_clock::universal_time();
|
||||
mCloseTime = theApp->getOPs().getNetworkTimeNC();
|
||||
theApp->getOPs().setLastCloseNetTime(mCloseTime);
|
||||
statusChange(newcoin::neCLOSING_LEDGER, mPreviousLedger);
|
||||
Ledger::pointer initial = theApp->getMasterLedger().closeLedger();
|
||||
assert (initial->getParentHash() == mPreviousLedger->getHash());
|
||||
takeInitialPosition(initial);
|
||||
statusChange(newcoin::neCLOSING_LEDGER, *mPreviousLedger);
|
||||
takeInitialPosition(*theApp->getMasterLedger().closeLedger());
|
||||
}
|
||||
}
|
||||
|
||||
void LedgerConsensus::stateEstablish()
|
||||
{ // we are establishing consensus
|
||||
if (mCurrentSeconds < LEDGER_MIN_CONSENSUS)
|
||||
if (mCurrentMSeconds < LEDGER_MIN_CONSENSUS)
|
||||
return;
|
||||
updateOurPositions();
|
||||
if (!mHaveCloseTimeConsensus)
|
||||
@@ -406,9 +406,7 @@ void LedgerConsensus::stateFinished()
|
||||
// logic of calculating next ledger advances us out of this state
|
||||
|
||||
// CHECKME: Should we count proposers that didn't converge to our consensus set?
|
||||
int convergeTime = (boost::posix_time::second_clock::universal_time() - mConsensusStartTime).seconds();
|
||||
if (convergeTime <= 0) convergeTime = 1;
|
||||
theApp->getOPs().newLCL(mPeerPositions.size(), convergeTime, mNewLedgerHash);
|
||||
theApp->getOPs().newLCL(mPeerPositions.size(), mCurrentMSeconds, mNewLedgerHash);
|
||||
}
|
||||
|
||||
void LedgerConsensus::stateAccepted()
|
||||
@@ -433,14 +431,15 @@ void LedgerConsensus::timerEntry()
|
||||
else Log(lsINFO) << "We still don't have it";
|
||||
}
|
||||
|
||||
mCurrentSeconds = (mCloseTime != 0) ? (theApp->getOPs().getNetworkTimeNC() - mCloseTime) : 0;
|
||||
mClosePercent = mCurrentSeconds * 100 / mPreviousSeconds;
|
||||
mCurrentMSeconds = (mCloseTime == 0) ? 0 :
|
||||
(boost::posix_time::second_clock::universal_time() - mConsensusStartTime).total_milliseconds();
|
||||
mClosePercent = mCurrentMSeconds * 100 / mPreviousMSeconds;
|
||||
|
||||
switch (mState)
|
||||
{
|
||||
case lcsPRE_CLOSE: statePreClose(); return;
|
||||
case lcsESTABLISH: stateEstablish(); return;
|
||||
case lcsFINISHED: stateFinished(); return;
|
||||
case lcsPRE_CLOSE: statePreClose(); if (mState != lcsESTABLISH) return;
|
||||
case lcsESTABLISH: stateEstablish(); if (mState != lcsFINISHED) return;
|
||||
case lcsFINISHED: stateFinished(); if (mState != lcsACCEPTED) return;
|
||||
case lcsACCEPTED: stateAccepted(); return;
|
||||
}
|
||||
assert(false);
|
||||
@@ -527,7 +526,7 @@ bool LedgerConsensus::haveConsensus()
|
||||
}
|
||||
int currentValidations = theApp->getValidations().getCurrentValidationCount(mPreviousLedger->getCloseTimeNC());
|
||||
return ContinuousLedgerTiming::haveConsensus(mPreviousProposers, agree + disagree, agree, currentValidations,
|
||||
mPreviousSeconds, mCurrentSeconds);
|
||||
mPreviousMSeconds, mCurrentMSeconds);
|
||||
}
|
||||
|
||||
SHAMap::pointer LedgerConsensus::getTransactionTree(const uint256& hash, bool doAcquire)
|
||||
@@ -535,6 +534,19 @@ SHAMap::pointer LedgerConsensus::getTransactionTree(const uint256& hash, bool do
|
||||
boost::unordered_map<uint256, SHAMap::pointer>::iterator it = mComplete.find(hash);
|
||||
if (it == mComplete.end())
|
||||
{ // we have not completed acquiring this ledger
|
||||
|
||||
if (mState == lcsPRE_CLOSE)
|
||||
{
|
||||
SHAMap::pointer currentMap = theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap();
|
||||
if (currentMap->getHash() == hash)
|
||||
{
|
||||
Log(lsINFO) << "node proposes our open transaction set";
|
||||
currentMap = currentMap->snapShot(false);
|
||||
mapComplete(hash, currentMap, false);
|
||||
return currentMap;
|
||||
}
|
||||
}
|
||||
|
||||
if (doAcquire)
|
||||
{
|
||||
TransactionAcquire::pointer& acquiring = mAcquiring[hash];
|
||||
@@ -735,29 +747,32 @@ void LedgerConsensus::applyTransaction(TransactionEngine& engine, SerializedTran
|
||||
#endif
|
||||
}
|
||||
|
||||
void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer ledger,
|
||||
void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer applyLedger, Ledger::pointer checkLedger,
|
||||
CanonicalTXSet& failedTransactions, bool final)
|
||||
{
|
||||
TransactionEngineParams parms = final ? (tepNO_CHECK_FEE | tepUPDATE_TOTAL) : tepNONE;
|
||||
TransactionEngine engine(ledger);
|
||||
TransactionEngine engine(applyLedger);
|
||||
|
||||
for (SHAMapItem::pointer item = set->peekFirstItem(); !!item; item = set->peekNextItem(item->getTag()))
|
||||
{
|
||||
Log(lsINFO) << "Processing candidate transaction: " << item->getTag().GetHex();
|
||||
#ifndef TRUST_NETWORK
|
||||
try
|
||||
if (!checkLedger->hasTransaction(item->getTag()))
|
||||
{
|
||||
#endif
|
||||
SerializerIterator sit(item->peekSerializer());
|
||||
SerializedTransaction::pointer txn = boost::make_shared<SerializedTransaction>(boost::ref(sit));
|
||||
applyTransaction(engine, txn, ledger, failedTransactions, final);
|
||||
Log(lsINFO) << "Processing candidate transaction: " << item->getTag().GetHex();
|
||||
#ifndef TRUST_NETWORK
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log(lsWARNING) << " Throws";
|
||||
}
|
||||
try
|
||||
{
|
||||
#endif
|
||||
SerializerIterator sit(item->peekSerializer());
|
||||
SerializedTransaction::pointer txn = boost::make_shared<SerializedTransaction>(boost::ref(sit));
|
||||
applyTransaction(engine, txn, applyLedger, failedTransactions, final);
|
||||
#ifndef TRUST_NETWORK
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log(lsWARNING) << " Throws";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int successes;
|
||||
@@ -800,7 +815,7 @@ void LedgerConsensus::accept(SHAMap::pointer set)
|
||||
newLCL->armDirty();
|
||||
|
||||
CanonicalTXSet failedTransactions(set->getHash());
|
||||
applyTransactions(set, newLCL, failedTransactions, true);
|
||||
applyTransactions(set, newLCL, newLCL, failedTransactions, true);
|
||||
newLCL->setClosed();
|
||||
|
||||
uint32 closeTime = mOurPosition->getCloseTime();
|
||||
@@ -815,7 +830,7 @@ void LedgerConsensus::accept(SHAMap::pointer set)
|
||||
newLCL->updateHash();
|
||||
uint256 newLCLHash = newLCL->getHash();
|
||||
Log(lsTRACE) << "newLCL " << newLCLHash.GetHex();
|
||||
statusChange(newcoin::neACCEPTED_LEDGER, newLCL);
|
||||
statusChange(newcoin::neACCEPTED_LEDGER, *newLCL);
|
||||
if (mValidating)
|
||||
{
|
||||
assert (theApp->getOPs().getNetworkTimeNC() > newLCL->getCloseTimeNC());
|
||||
@@ -843,6 +858,7 @@ void LedgerConsensus::accept(SHAMap::pointer set)
|
||||
{ // we voted NO
|
||||
try
|
||||
{
|
||||
Log(lsINFO) << "Test applying disputed transaction that did not get in";
|
||||
SerializerIterator sit(it->second->peekTransaction());
|
||||
SerializedTransaction::pointer txn = boost::make_shared<SerializedTransaction>(boost::ref(sit));
|
||||
applyTransaction(engine, txn, newOL, failedTransactions, false);
|
||||
@@ -854,7 +870,8 @@ void LedgerConsensus::accept(SHAMap::pointer set)
|
||||
}
|
||||
}
|
||||
|
||||
applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(), newOL,
|
||||
Log(lsINFO) << "Applying transactions from current ledger";
|
||||
applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(), newOL, newLCL,
|
||||
failedTransactions, false);
|
||||
theApp->getMasterLedger().pushLedger(newLCL, newOL);
|
||||
mNewLedgerHash = newLCL->getHash();
|
||||
|
||||
@@ -86,12 +86,12 @@ protected:
|
||||
NewcoinAddress mValSeed;
|
||||
bool mProposing, mValidating, mHaveCorrectLCL;
|
||||
|
||||
int mCurrentSeconds, mClosePercent, mCloseResolution;
|
||||
int mCurrentMSeconds, mClosePercent, mCloseResolution;
|
||||
bool mHaveCloseTimeConsensus;
|
||||
|
||||
boost::posix_time::ptime mConsensusStartTime;
|
||||
int mPreviousProposers;
|
||||
int mPreviousSeconds;
|
||||
int mPreviousMSeconds;
|
||||
|
||||
// Convergence tracking, trusted peers indexed by hash of public key
|
||||
boost::unordered_map<uint160, LedgerProposal::pointer> mPeerPositions;
|
||||
@@ -125,14 +125,14 @@ protected:
|
||||
void addPosition(LedgerProposal&, bool ours);
|
||||
void removePosition(LedgerProposal&, bool ours);
|
||||
void sendHaveTxSet(const uint256& set, bool direct);
|
||||
void applyTransactions(SHAMap::pointer transactionSet, Ledger::pointer targetLedger,
|
||||
void applyTransactions(SHAMap::pointer transactionSet, Ledger::pointer targetLedger, Ledger::pointer checkLedger,
|
||||
CanonicalTXSet& failedTransactions, bool final);
|
||||
void applyTransaction(TransactionEngine& engine, SerializedTransaction::pointer txn, Ledger::pointer targetLedger,
|
||||
CanonicalTXSet& failedTransactions, bool final);
|
||||
|
||||
// manipulating our own position
|
||||
void statusChange(newcoin::NodeEvent, Ledger::pointer ledger);
|
||||
void takeInitialPosition(Ledger::pointer initialLedger);
|
||||
void statusChange(newcoin::NodeEvent, Ledger& ledger);
|
||||
void takeInitialPosition(Ledger& initialLedger);
|
||||
void updateOurPositions();
|
||||
int getThreshold();
|
||||
void beginAccept();
|
||||
|
||||
@@ -53,52 +53,44 @@ SLE::pointer Ledger::getSLE(const uint256& uHash)
|
||||
return boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
|
||||
}
|
||||
|
||||
SLE::pointer Ledger::getFirstSLE()
|
||||
uint256 Ledger::getFirstLedgerIndex()
|
||||
{
|
||||
SHAMapItem::pointer node = mAccountStateMap->peekFirstItem();
|
||||
if (!node)
|
||||
return SLE::pointer();
|
||||
return boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
|
||||
return node ? node->getTag() : uint256();
|
||||
}
|
||||
|
||||
SLE::pointer Ledger::getLastSLE()
|
||||
uint256 Ledger::getLastLedgerIndex()
|
||||
{
|
||||
SHAMapItem::pointer node = mAccountStateMap->peekLastItem();
|
||||
if (!node)
|
||||
return SLE::pointer();
|
||||
return boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
|
||||
return node ? node->getTag() : uint256();
|
||||
}
|
||||
|
||||
SLE::pointer Ledger::getNextSLE(const uint256& uHash)
|
||||
uint256 Ledger::getNextLedgerIndex(const uint256& uHash)
|
||||
{
|
||||
SHAMapItem::pointer node = mAccountStateMap->peekNextItem(uHash);
|
||||
if (!node)
|
||||
return SLE::pointer();
|
||||
return boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
|
||||
return node ? node->getTag() : uint256();
|
||||
}
|
||||
|
||||
SLE::pointer Ledger::getNextSLE(const uint256& uHash, const uint256& uEnd)
|
||||
uint256 Ledger::getNextLedgerIndex(const uint256& uHash, const uint256& uEnd)
|
||||
{
|
||||
SHAMapItem::pointer node = mAccountStateMap->peekNextItem(uHash);
|
||||
if ((!node) || (node->getTag() > uEnd))
|
||||
return SLE::pointer();
|
||||
return boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
|
||||
return uint256();
|
||||
return node->getTag();
|
||||
}
|
||||
|
||||
SLE::pointer Ledger::getPrevSLE(const uint256& uHash)
|
||||
uint256 Ledger::getPrevLedgerIndex(const uint256& uHash)
|
||||
{
|
||||
SHAMapItem::pointer node = mAccountStateMap->peekPrevItem(uHash);
|
||||
if (!node)
|
||||
return SLE::pointer();
|
||||
return boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
|
||||
return node ? node->getTag() : uint256();
|
||||
}
|
||||
|
||||
SLE::pointer Ledger::getPrevSLE(const uint256& uHash, const uint256& uBegin)
|
||||
uint256 Ledger::getPrevLedgerIndex(const uint256& uHash, const uint256& uBegin)
|
||||
{
|
||||
SHAMapItem::pointer node = mAccountStateMap->peekNextItem(uHash);
|
||||
if ((!node) || (node->getTag() < uBegin))
|
||||
return SLE::pointer();
|
||||
return boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
|
||||
return uint256();
|
||||
return node->getTag();
|
||||
}
|
||||
|
||||
SLE::pointer Ledger::getASNode(LedgerStateParms& parms, const uint256& nodeID,
|
||||
|
||||
@@ -16,15 +16,15 @@ int ContinuousLedgerTiming::shouldClose(
|
||||
bool anyTransactions,
|
||||
int previousProposers, // proposers in the last closing
|
||||
int proposersClosed, // proposers who have currently closed this ledgers
|
||||
int previousSeconds, // seconds the previous ledger took to reach consensus
|
||||
int currentSeconds) // seconds since the previous ledger closed
|
||||
int previousMSeconds, // seconds the previous ledger took to reach consensus
|
||||
int currentMSeconds) // seconds since the previous ledger closed
|
||||
{
|
||||
assert((previousSeconds > 0) && (previousSeconds < 600));
|
||||
assert((currentSeconds >= 0) && (currentSeconds < 600));
|
||||
assert((previousMSeconds > 0) && (previousMSeconds < 600000));
|
||||
assert((currentMSeconds >= 0) && (currentMSeconds < 600000));
|
||||
|
||||
#if 0
|
||||
Log(lsTRACE) << boost::str(boost::format("CLC::shouldClose Trans=%s, Prop: %d/%d, Secs: %d (last:%d)") %
|
||||
(anyTransactions ? "yes" : "no") % previousProposers % proposersClosed % currentSeconds % previousSeconds);
|
||||
(anyTransactions ? "yes" : "no") % previousProposers % proposersClosed % currentMSeconds % previousMSeconds);
|
||||
#endif
|
||||
|
||||
if (!anyTransactions)
|
||||
@@ -32,24 +32,26 @@ int ContinuousLedgerTiming::shouldClose(
|
||||
if (proposersClosed > (previousProposers / 4)) // did we miss a transaction?
|
||||
{
|
||||
Log(lsTRACE) << "no transactions, many proposers: now";
|
||||
return currentSeconds;
|
||||
return currentMSeconds;
|
||||
}
|
||||
if (previousSeconds > (LEDGER_IDLE_INTERVAL + 2)) // the last ledger was very slow to close
|
||||
if (previousMSeconds > (1000 * (LEDGER_IDLE_INTERVAL + 2))) // the last ledger was very slow to close
|
||||
{
|
||||
Log(lsTRACE) << "slow to close";
|
||||
return previousSeconds - 1;
|
||||
if (previousMSeconds < 2000)
|
||||
return previousMSeconds;
|
||||
return previousMSeconds - 1000;
|
||||
}
|
||||
return LEDGER_IDLE_INTERVAL; // normal idle
|
||||
return LEDGER_IDLE_INTERVAL * 1000; // normal idle
|
||||
}
|
||||
|
||||
if (previousSeconds == LEDGER_IDLE_INTERVAL) // coming out of idle, close now
|
||||
if (previousMSeconds == (1000 * LEDGER_IDLE_INTERVAL)) // coming out of idle, close now
|
||||
{
|
||||
Log(lsTRACE) << "leaving idle, close now";
|
||||
return currentSeconds;
|
||||
return currentMSeconds;
|
||||
}
|
||||
|
||||
Log(lsTRACE) << "close now";
|
||||
return currentSeconds; // this ledger should close now
|
||||
return currentMSeconds; // this ledger should close now
|
||||
}
|
||||
|
||||
// Returns whether we have a consensus or not. If so, we expect all honest nodes
|
||||
@@ -70,7 +72,7 @@ bool ContinuousLedgerTiming::haveConsensus(
|
||||
|
||||
if (currentProposers < (previousProposers * 3 / 4))
|
||||
{ // Less than 3/4 of the last ledger's proposers are present, we may need more time
|
||||
if (currentAgreeTime < (previousAgreeTime + 2))
|
||||
if (currentAgreeTime < (previousAgreeTime + LEDGER_MIN_CONSENSUS))
|
||||
{
|
||||
Log(lsTRACE) << "too fast, not enough proposers";
|
||||
return false;
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
// The number of seconds a validation remains current
|
||||
# define LEDGER_MAX_INTERVAL 60
|
||||
|
||||
// The number of seconds we wait minimum to ensure participation
|
||||
# define LEDGER_MIN_CONSENSUS 2
|
||||
// The number of milliseconds we wait minimum to ensure participation
|
||||
# define LEDGER_MIN_CONSENSUS 2000
|
||||
|
||||
// Initial resolution of ledger close time
|
||||
# define LEDGER_TIME_ACCURACY 30
|
||||
@@ -19,6 +19,9 @@
|
||||
// How often to decrease resolution
|
||||
# define LEDGER_RES_DECREASE 1
|
||||
|
||||
// How often we check state or change positions (in milliseconds)
|
||||
# define LEDGER_GRANULARITY 1000
|
||||
|
||||
// Avalanche tuning
|
||||
#define AV_INIT_CONSENSUS_PCT 50 // percentage of nodes on our UNL that must vote yes
|
||||
|
||||
|
||||
@@ -44,6 +44,24 @@ uint32 NetworkOPs::getCurrentLedgerID()
|
||||
return mLedgerMaster->getCurrentLedger()->getLedgerSeq();
|
||||
}
|
||||
|
||||
// Sterilize transaction through serialization.
|
||||
void NetworkOPs::submitTransaction(Transaction::pointer tpTrans)
|
||||
{
|
||||
Serializer s;
|
||||
|
||||
tpTrans->getSTransaction()->add(s);
|
||||
|
||||
std::vector<unsigned char> vucTransaction = s.getData();
|
||||
|
||||
SerializerIterator sit(s);
|
||||
|
||||
Transaction::pointer tpTransNew = Transaction::sharedTransaction(s.getData(), true);
|
||||
|
||||
assert(tpTransNew);
|
||||
|
||||
(void) NetworkOPs::processTransaction(tpTransNew);
|
||||
}
|
||||
|
||||
Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans, uint32 tgtLedger, Peer* source)
|
||||
{
|
||||
Transaction::pointer dbtx = theApp->getMasterTransaction().fetch(trans->getID(), true);
|
||||
@@ -280,7 +298,7 @@ RippleState::pointer NetworkOPs::accessRippleState(const uint256& uLedger, const
|
||||
|
||||
void NetworkOPs::setStateTimer()
|
||||
{ // set timer early if ledger is closing
|
||||
mNetTimer.expires_from_now(boost::posix_time::seconds(1));
|
||||
mNetTimer.expires_from_now(boost::posix_time::milliseconds(LEDGER_GRANULARITY));
|
||||
mNetTimer.async_wait(boost::bind(&NetworkOPs::checkState, this, boost::asio::placeholders::error));
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,11 @@ public:
|
||||
uint256 getCurrentLedger()
|
||||
{ return mLedgerMaster->getCurrentLedger()->getHash(); }
|
||||
|
||||
// transaction operations
|
||||
//
|
||||
// Transaction operations
|
||||
//
|
||||
void submitTransaction(Transaction::pointer tpTrans);
|
||||
|
||||
Transaction::pointer processTransaction(Transaction::pointer transaction, uint32 targetLedger = 0,
|
||||
Peer* source = NULL);
|
||||
Transaction::pointer findTransactionByID(const uint256& transactionID);
|
||||
@@ -182,7 +186,7 @@ public:
|
||||
void setStateTimer();
|
||||
void newLCL(int proposers, int convergeTime, const uint256& ledgerHash);
|
||||
int getPreviousProposers() { return mLastCloseProposers; }
|
||||
int getPreviousSeconds() { return mLastCloseConvergeTime; }
|
||||
int getPreviousConvergeTime() { return mLastCloseConvergeTime; }
|
||||
uint32 getLastCloseNetTime() { return mLastCloseNetTime; }
|
||||
void setLastCloseNetTime(uint32 t) { mLastCloseNetTime = t; }
|
||||
Json::Value getServerInfo();
|
||||
|
||||
@@ -463,7 +463,7 @@ Json::Value RPCServer::doAccountEmailSet(const Json::Value ¶ms)
|
||||
uint256(),
|
||||
NewcoinAddress());
|
||||
|
||||
(void) mNetOps->processTransaction(trans);
|
||||
(void) mNetOps->submitTransaction(trans);
|
||||
|
||||
obj["transaction"] = trans->getSTransaction()->getJson(0);
|
||||
obj["status"] = trans->getStatus();
|
||||
@@ -572,7 +572,7 @@ Json::Value RPCServer::doAccountMessageSet(const Json::Value& params) {
|
||||
uint256(),
|
||||
naMessagePubKey);
|
||||
|
||||
(void) mNetOps->processTransaction(trans);
|
||||
(void) mNetOps->submitTransaction(trans);
|
||||
|
||||
obj["transaction"] = trans->getSTransaction()->getJson(0);
|
||||
obj["status"] = trans->getStatus();
|
||||
@@ -624,7 +624,7 @@ Json::Value RPCServer::doAccountWalletSet(const Json::Value& params) {
|
||||
uWalletLocator,
|
||||
NewcoinAddress());
|
||||
|
||||
(void) mNetOps->processTransaction(trans);
|
||||
(void) mNetOps->submitTransaction(trans);
|
||||
|
||||
obj["transaction"] = trans->getSTransaction()->getJson(0);
|
||||
obj["status"] = trans->getStatus();
|
||||
@@ -822,7 +822,7 @@ Json::Value RPCServer::doNicknameSet(const Json::Value& params)
|
||||
saMinimumOffer,
|
||||
vucSignature);
|
||||
|
||||
(void) mNetOps->processTransaction(trans);
|
||||
(void) mNetOps->submitTransaction(trans);
|
||||
|
||||
obj["transaction"] = trans->getSTransaction()->getJson(0);
|
||||
obj["status"] = trans->getStatus();
|
||||
@@ -897,7 +897,7 @@ Json::Value RPCServer::doOfferCreate(const Json::Value ¶ms)
|
||||
saTakerGets,
|
||||
uExpiration);
|
||||
|
||||
(void) mNetOps->processTransaction(trans);
|
||||
(void) mNetOps->submitTransaction(trans);
|
||||
|
||||
obj["transaction"] = trans->getSTransaction()->getJson(0);
|
||||
obj["status"] = trans->getStatus();
|
||||
@@ -940,7 +940,7 @@ Json::Value RPCServer::doOfferCancel(const Json::Value ¶ms)
|
||||
0, // YYY No source tag
|
||||
uSequence);
|
||||
|
||||
(void) mNetOps->processTransaction(trans);
|
||||
(void) mNetOps->submitTransaction(trans);
|
||||
|
||||
obj["transaction"] = trans->getSTransaction()->getJson(0);
|
||||
obj["status"] = trans->getStatus();
|
||||
@@ -1026,7 +1026,7 @@ Json::Value RPCServer::doPasswordFund(const Json::Value ¶ms)
|
||||
0, // YYY No source tag
|
||||
naDstAccountID);
|
||||
|
||||
(void) mNetOps->processTransaction(trans);
|
||||
(void) mNetOps->submitTransaction(trans);
|
||||
|
||||
obj["transaction"] = trans->getSTransaction()->getJson(0);
|
||||
obj["status"] = trans->getStatus();
|
||||
@@ -1112,7 +1112,7 @@ Json::Value RPCServer::doPasswordSet(const Json::Value& params)
|
||||
naRegular0Public.getAccountPublic(),
|
||||
vucGeneratorSig);
|
||||
|
||||
(void) mNetOps->processTransaction(trns);
|
||||
(void) mNetOps->submitTransaction(trns);
|
||||
|
||||
Json::Value obj(Json::objectValue);
|
||||
|
||||
@@ -1186,7 +1186,7 @@ Json::Value RPCServer::doRippleLineSet(const Json::Value& params)
|
||||
saLimitAmount,
|
||||
uAcceptRate);
|
||||
|
||||
(void) mNetOps->processTransaction(trans);
|
||||
(void) mNetOps->submitTransaction(trans);
|
||||
|
||||
obj["transaction"] = trans->getSTransaction()->getJson(0);
|
||||
obj["status"] = trans->getStatus();
|
||||
@@ -1274,7 +1274,7 @@ Json::Value RPCServer::doRippleLinesGet(const Json::Value ¶ms)
|
||||
// Amount reported is positive if current account hold's other account's IOUs.
|
||||
// Amount reported is negative if other account hold's current account's IOUs.
|
||||
jPeer["balance"] = saBalance.getText();
|
||||
jPeer["currency"] = saBalance.getCurrencyHuman();
|
||||
jPeer["currency"] = saBalance.getHumanCurrency();
|
||||
jPeer["limit"] = saLimit.getText();
|
||||
jPeer["limit_peer"] = saLimitPeer.getText();
|
||||
|
||||
@@ -1424,7 +1424,7 @@ Json::Value RPCServer::doSend(const Json::Value& params)
|
||||
saDstAmount); // Initial funds in XNS.
|
||||
}
|
||||
|
||||
(void) mNetOps->processTransaction(trans);
|
||||
(void) mNetOps->submitTransaction(trans);
|
||||
|
||||
obj["transaction"] = trans->getSTransaction()->getJson(0);
|
||||
obj["status"] = trans->getStatus();
|
||||
@@ -1434,9 +1434,9 @@ Json::Value RPCServer::doSend(const Json::Value& params)
|
||||
obj["srcAccountID"] = naSrcAccountID.humanAccountID();
|
||||
obj["dstAccountID"] = naDstAccountID.humanAccountID();
|
||||
obj["srcAmount"] = saSrcAmount.getText();
|
||||
obj["srcISO"] = saSrcAmount.getCurrencyHuman();
|
||||
obj["srcISO"] = saSrcAmount.getHumanCurrency();
|
||||
obj["dstAmount"] = saDstAmount.getText();
|
||||
obj["dstISO"] = saDstAmount.getCurrencyHuman();
|
||||
obj["dstISO"] = saDstAmount.getHumanCurrency();
|
||||
|
||||
return obj;
|
||||
}
|
||||
@@ -1810,7 +1810,7 @@ Json::Value RPCServer::doWalletAdd(const Json::Value& params)
|
||||
naNewAccountPublic,
|
||||
vucSignature);
|
||||
|
||||
(void) mNetOps->processTransaction(trans);
|
||||
(void) mNetOps->submitTransaction(trans);
|
||||
|
||||
obj["transaction"] = trans->getSTransaction()->getJson(0);
|
||||
obj["status"] = trans->getStatus();
|
||||
@@ -1885,7 +1885,7 @@ Json::Value RPCServer::doWalletClaim(const Json::Value& params)
|
||||
naRegular0Public.getAccountPublic(),
|
||||
vucGeneratorSig);
|
||||
|
||||
(void) mNetOps->processTransaction(trns);
|
||||
(void) mNetOps->submitTransaction(trns);
|
||||
|
||||
Json::Value obj(Json::objectValue);
|
||||
|
||||
@@ -1963,7 +1963,7 @@ Json::Value RPCServer::doWalletCreate(const Json::Value& params)
|
||||
naDstAccountID,
|
||||
saInitialFunds); // Initial funds in XNC.
|
||||
|
||||
(void) mNetOps->processTransaction(trans);
|
||||
(void) mNetOps->submitTransaction(trans);
|
||||
|
||||
obj["transaction"] = trans->getSTransaction()->getJson(0);
|
||||
obj["status"] = trans->getStatus();
|
||||
|
||||
@@ -170,7 +170,7 @@ SHAMapTreeNode* SHAMap::walkToPointer(const uint256& id)
|
||||
{
|
||||
int branch = inNode->selectBranch(id);
|
||||
const uint256& nextHash = inNode->getChildHash(branch);
|
||||
if (!nextHash) return NULL;
|
||||
if (nextHash.isZero()) return NULL;
|
||||
inNode = getNodePointer(inNode->getChildNodeID(branch), nextHash);
|
||||
if (!inNode)
|
||||
throw SHAMapMissingNode(inNode->getChildNodeID(branch), nextHash);
|
||||
@@ -437,7 +437,7 @@ bool SHAMap::delItem(const uint256& id)
|
||||
|
||||
SHAMapTreeNode::pointer leaf=stack.top();
|
||||
stack.pop();
|
||||
if( !leaf || !leaf->hasItem() || (leaf->peekItem()->getTag()!=id) )
|
||||
if (!leaf || !leaf->hasItem() || (leaf->peekItem()->getTag() != id))
|
||||
return false;
|
||||
|
||||
SHAMapTreeNode::TNType type=leaf->getType();
|
||||
@@ -446,19 +446,19 @@ bool SHAMap::delItem(const uint256& id)
|
||||
assert(false);
|
||||
|
||||
uint256 prevHash;
|
||||
while(!stack.empty())
|
||||
while (!stack.empty())
|
||||
{
|
||||
SHAMapTreeNode::pointer node=stack.top();
|
||||
stack.pop();
|
||||
returnNode(node, true);
|
||||
assert(node->isInner());
|
||||
|
||||
if(!node->setChildHash(node->selectBranch(id), prevHash))
|
||||
if (!node->setChildHash(node->selectBranch(id), prevHash))
|
||||
{
|
||||
assert(false);
|
||||
return true;
|
||||
}
|
||||
if(!node->isRoot())
|
||||
if (!node->isRoot())
|
||||
{ // we may have made this a node with 1 or 0 children
|
||||
int bc=node->getBranchCount();
|
||||
if(bc==0)
|
||||
@@ -467,7 +467,7 @@ bool SHAMap::delItem(const uint256& id)
|
||||
std::cerr << "delItem makes empty node" << std::endl;
|
||||
#endif
|
||||
prevHash=uint256();
|
||||
if(!mTNByID.erase(*node))
|
||||
if (!mTNByID.erase(*node))
|
||||
assert(false);
|
||||
}
|
||||
else if(bc==1)
|
||||
|
||||
@@ -271,7 +271,7 @@ public:
|
||||
int64 getSNValue() const;
|
||||
void setSNValue(int64);
|
||||
|
||||
std::string getCurrencyHuman() const;
|
||||
std::string getHumanCurrency() const;
|
||||
|
||||
bool isNative() const { return mIsNative; }
|
||||
bool isZero() const { return mValue == 0; }
|
||||
@@ -344,6 +344,7 @@ public:
|
||||
static STAmount convertToInternalAmount(uint64 displayAmount, uint64 totalNow, uint64 totalInit,
|
||||
const char* name = NULL);
|
||||
|
||||
static std::string createHumanCurrency(const uint160& uCurrency);
|
||||
static STAmount deserialize(SerializerIterator&);
|
||||
static bool currencyFromString(uint160& uDstCurrency, const std::string& sCurrency);
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ Transaction::Transaction(
|
||||
|
||||
Log(lsINFO) << str(boost::format("Transaction: account: %s") % naSourceAccount.humanAccountID());
|
||||
Log(lsINFO) << str(boost::format("Transaction: mAccountFrom: %s") % mAccountFrom.humanAccountID());
|
||||
|
||||
mTransaction->setSigningPubKey(mFromPubKey);
|
||||
mTransaction->setSourceAccount(mAccountFrom);
|
||||
mTransaction->setSequence(uSeq);
|
||||
|
||||
@@ -98,7 +98,7 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std
|
||||
STAmount TransactionEngine::rippleHolds(const uint160& uAccountID, const uint160& uCurrency, const uint160& uIssuerID)
|
||||
{
|
||||
STAmount saBalance;
|
||||
SLE::pointer sleRippleState = mLedger->getRippleState(Ledger::getRippleStateIndex(uAccountID, uIssuerID, uCurrency));
|
||||
SLE::pointer sleRippleState = entryCache(ltRIPPLE_STATE, Ledger::getRippleStateIndex(uAccountID, uIssuerID, uCurrency));
|
||||
|
||||
if (sleRippleState)
|
||||
{
|
||||
@@ -117,13 +117,22 @@ STAmount TransactionEngine::accountHolds(const uint160& uAccountID, const uint16
|
||||
|
||||
if (uCurrency.isZero())
|
||||
{
|
||||
SLE::pointer sleAccount = mLedger->getAccountRoot(uAccountID);
|
||||
SLE::pointer sleAccount = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uAccountID));
|
||||
|
||||
saAmount = sleAccount->getIValueFieldAmount(sfBalance);
|
||||
|
||||
Log(lsINFO) << "accountHolds: stamps: " << saAmount.getText();
|
||||
}
|
||||
else
|
||||
{
|
||||
saAmount = rippleHolds(uAccountID, uCurrency, uIssuerID);
|
||||
|
||||
Log(lsINFO) << "accountHolds: "
|
||||
<< saAmount.getText()
|
||||
<< " : "
|
||||
<< STAmount::createHumanCurrency(uCurrency)
|
||||
<< "/"
|
||||
<< NewcoinAddress::createHumanAccountID(uIssuerID);
|
||||
}
|
||||
|
||||
return saAmount;
|
||||
@@ -134,6 +143,12 @@ STAmount TransactionEngine::accountFunds(const uint160& uAccountID, const STAmou
|
||||
{
|
||||
STAmount saFunds;
|
||||
|
||||
Log(lsINFO) << "accountFunds: uAccountID="
|
||||
<< NewcoinAddress::createHumanAccountID(uAccountID);
|
||||
Log(lsINFO) << "accountFunds: saDefault.isNative()=" << saDefault.isNative();
|
||||
Log(lsINFO) << "accountFunds: saDefault.getIssuer()="
|
||||
<< NewcoinAddress::createHumanAccountID(saDefault.getIssuer());
|
||||
|
||||
if (!saDefault.isNative() && saDefault.getIssuer() == uAccountID)
|
||||
{
|
||||
saFunds = saDefault;
|
||||
@@ -144,7 +159,14 @@ STAmount TransactionEngine::accountFunds(const uint160& uAccountID, const STAmou
|
||||
{
|
||||
saFunds = accountHolds(uAccountID, saDefault.getCurrency(), saDefault.getIssuer());
|
||||
|
||||
Log(lsINFO) << "accountFunds: offer funds: " << saFunds.getText();
|
||||
Log(lsINFO) << "accountFunds: offer funds: uAccountID ="
|
||||
<< NewcoinAddress::createHumanAccountID(uAccountID)
|
||||
<< " : "
|
||||
<< saFunds.getText()
|
||||
<< "/"
|
||||
<< saDefault.getHumanCurrency()
|
||||
<< "/"
|
||||
<< NewcoinAddress::createHumanAccountID(saDefault.getIssuer());
|
||||
}
|
||||
|
||||
return saFunds;
|
||||
@@ -157,7 +179,7 @@ STAmount TransactionEngine::rippleTransit(const uint160& uSenderID, const uint16
|
||||
|
||||
if (uSenderID != uIssuerID && uReceiverID != uIssuerID)
|
||||
{
|
||||
SLE::pointer sleIssuerAccount = mLedger->getAccountRoot(uIssuerID);
|
||||
SLE::pointer sleIssuerAccount = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uIssuerID));
|
||||
uint32 uTransitRate;
|
||||
|
||||
if (sleIssuerAccount->getIFieldPresent(sfTransferRate))
|
||||
@@ -189,7 +211,7 @@ STAmount TransactionEngine::rippleSend(const uint160& uSenderID, const uint160&
|
||||
|
||||
bool bFlipped = uSenderID > uReceiverID;
|
||||
uint256 uIndex = Ledger::getRippleStateIndex(uSenderID, uReceiverID, saAmount.getCurrency());
|
||||
SLE::pointer sleRippleState = mLedger->getRippleState(uIndex);
|
||||
SLE::pointer sleRippleState = entryCache(ltRIPPLE_STATE, uIndex);
|
||||
|
||||
if (!sleRippleState)
|
||||
{
|
||||
@@ -248,8 +270,8 @@ STAmount TransactionEngine::accountSend(const uint160& uSenderID, const uint160&
|
||||
|
||||
if (saAmount.isNative())
|
||||
{
|
||||
SLE::pointer sleSender = mLedger->getAccountRoot(uSenderID);
|
||||
SLE::pointer sleReceiver = mLedger->getAccountRoot(uReceiverID);
|
||||
SLE::pointer sleSender = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uSenderID));
|
||||
SLE::pointer sleReceiver = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uReceiverID));
|
||||
|
||||
sleSender->setIFieldAmount(sfBalance, sleSender->getIValueFieldAmount(sfBalance) - saAmount);
|
||||
sleReceiver->setIFieldAmount(sfBalance, sleReceiver->getIValueFieldAmount(sfBalance) + saAmount);
|
||||
@@ -294,8 +316,7 @@ TransactionEngineResult TransactionEngine::dirAdd(
|
||||
{
|
||||
SLE::pointer sleNode;
|
||||
STVector256 svIndexes;
|
||||
LedgerStateParms lspRoot = lepNONE;
|
||||
SLE::pointer sleRoot = mLedger->getDirNode(lspRoot, uRootIndex);
|
||||
SLE::pointer sleRoot = entryCache(ltDIR_NODE, uRootIndex);
|
||||
|
||||
if (!sleRoot)
|
||||
{
|
||||
@@ -312,8 +333,7 @@ TransactionEngineResult TransactionEngine::dirAdd(
|
||||
if (uNodeDir)
|
||||
{
|
||||
// Try adding to last node.
|
||||
lspRoot = lepNONE;
|
||||
sleNode = mLedger->getDirNode(lspRoot, Ledger::getDirNodeIndex(uRootIndex, uNodeDir));
|
||||
sleNode = entryCache(ltDIR_NODE, Ledger::getDirNodeIndex(uRootIndex, uNodeDir));
|
||||
|
||||
assert(sleNode);
|
||||
}
|
||||
@@ -348,8 +368,7 @@ TransactionEngineResult TransactionEngine::dirAdd(
|
||||
{
|
||||
// Previous node is not root node.
|
||||
|
||||
lspRoot = lepNONE;
|
||||
SLE::pointer slePrevious = mLedger->getDirNode(lspRoot, Ledger::getDirNodeIndex(uRootIndex, uNodeDir-1));
|
||||
SLE::pointer slePrevious = entryCache(ltDIR_NODE, Ledger::getDirNodeIndex(uRootIndex, uNodeDir-1));
|
||||
|
||||
slePrevious->setIFieldU64(sfIndexNext, uNodeDir);
|
||||
entryModify(slePrevious);
|
||||
@@ -390,8 +409,7 @@ TransactionEngineResult TransactionEngine::dirDelete(
|
||||
const uint256& uLedgerIndex)
|
||||
{
|
||||
uint64 uNodeCur = uNodeDir;
|
||||
LedgerStateParms lspNode = lepNONE;
|
||||
SLE::pointer sleNode = mLedger->getDirNode(lspNode, uNodeCur ? Ledger::getDirNodeIndex(uRootIndex, uNodeCur) : uRootIndex);
|
||||
SLE::pointer sleNode = entryCache(ltDIR_NODE, uNodeCur ? Ledger::getDirNodeIndex(uRootIndex, uNodeCur) : uRootIndex);
|
||||
|
||||
assert(sleNode);
|
||||
|
||||
@@ -458,8 +476,7 @@ TransactionEngineResult TransactionEngine::dirDelete(
|
||||
else
|
||||
{
|
||||
// Have only a root node and a last node.
|
||||
LedgerStateParms lspLast = lepNONE;
|
||||
SLE::pointer sleLast = mLedger->getDirNode(lspLast, Ledger::getDirNodeIndex(uRootIndex, uNodeNext));
|
||||
SLE::pointer sleLast = entryCache(ltDIR_NODE, Ledger::getDirNodeIndex(uRootIndex, uNodeNext));
|
||||
|
||||
assert(sleLast);
|
||||
|
||||
@@ -483,13 +500,11 @@ TransactionEngineResult TransactionEngine::dirDelete(
|
||||
{
|
||||
// Not root and not last node. Can delete node.
|
||||
|
||||
LedgerStateParms lspPrevious = lepNONE;
|
||||
SLE::pointer slePrevious = mLedger->getDirNode(lspPrevious, uNodePrevious ? Ledger::getDirNodeIndex(uRootIndex, uNodePrevious) : uRootIndex);
|
||||
SLE::pointer slePrevious = entryCache(ltDIR_NODE, uNodePrevious ? Ledger::getDirNodeIndex(uRootIndex, uNodePrevious) : uRootIndex);
|
||||
|
||||
assert(slePrevious);
|
||||
|
||||
LedgerStateParms lspNext = lepNONE;
|
||||
SLE::pointer sleNext = mLedger->getDirNode(lspNext, uNodeNext ? Ledger::getDirNodeIndex(uRootIndex, uNodeNext) : uRootIndex);
|
||||
SLE::pointer sleNext = entryCache(ltDIR_NODE, uNodeNext ? Ledger::getDirNodeIndex(uRootIndex, uNodeNext) : uRootIndex);
|
||||
|
||||
assert(slePrevious);
|
||||
assert(sleNext);
|
||||
@@ -527,8 +542,7 @@ TransactionEngineResult TransactionEngine::dirDelete(
|
||||
else
|
||||
{
|
||||
// Last and only node besides the root.
|
||||
LedgerStateParms lspRoot = lepNONE;
|
||||
SLE::pointer sleRoot = mLedger->getDirNode(lspRoot, uRootIndex);
|
||||
SLE::pointer sleRoot = entryCache(ltDIR_NODE, uRootIndex);
|
||||
|
||||
assert(sleRoot);
|
||||
|
||||
@@ -556,8 +570,7 @@ TransactionEngineResult TransactionEngine::dirDelete(
|
||||
// <-- uEntryNode
|
||||
void TransactionEngine::dirFirst(const uint256& uRootIndex, uint256& uEntryIndex, uint64& uEntryNode)
|
||||
{
|
||||
LedgerStateParms lspRoot = lepNONE;
|
||||
SLE::pointer sleRoot = mLedger->getDirNode(lspRoot, uRootIndex);
|
||||
SLE::pointer sleRoot = entryCache(ltDIR_NODE, uRootIndex);
|
||||
|
||||
STVector256 svIndexes = sleRoot->getIFieldV256(sfIndexes);
|
||||
std::vector<uint256>& vuiIndexes = svIndexes.peekValue();
|
||||
@@ -566,8 +579,7 @@ void TransactionEngine::dirFirst(const uint256& uRootIndex, uint256& uEntryIndex
|
||||
{
|
||||
uEntryNode = sleRoot->getIFieldU64(sfIndexNext);
|
||||
|
||||
LedgerStateParms lspNext = lepNONE;
|
||||
SLE::pointer sleNext = mLedger->getDirNode(lspNext, Ledger::getDirNodeIndex(uRootIndex, uEntryNode));
|
||||
SLE::pointer sleNext = entryCache(ltDIR_NODE, Ledger::getDirNodeIndex(uRootIndex, uEntryNode));
|
||||
uEntryIndex = sleNext->getIFieldV256(sfIndexes).peekValue()[0];
|
||||
}
|
||||
else
|
||||
@@ -600,8 +612,7 @@ TransactionEngineResult TransactionEngine::setAuthorized(const SerializedTransac
|
||||
// Create generator.
|
||||
uint160 hGeneratorID = naAccountPublic.getAccountID();
|
||||
|
||||
LedgerStateParms qry = lepNONE;
|
||||
SLE::pointer sleGen = mLedger->getGenerator(qry, hGeneratorID);
|
||||
SLE::pointer sleGen = entryCache(ltGENERATOR_MAP, Ledger::getGeneratorIndex(hGeneratorID));
|
||||
if (!sleGen)
|
||||
{
|
||||
// Create the generator.
|
||||
@@ -630,6 +641,37 @@ TransactionEngineResult TransactionEngine::setAuthorized(const SerializedTransac
|
||||
return terSUCCESS;
|
||||
}
|
||||
|
||||
SLE::pointer TransactionEngine::entryCache(LedgerEntryType letType, const uint256& uIndex)
|
||||
{
|
||||
SLE::pointer sleEntry;
|
||||
|
||||
if (!uIndex.isZero())
|
||||
{
|
||||
entryMap::const_iterator it = mEntries.find(uIndex);
|
||||
|
||||
switch (it == mEntries.end() ? taaNONE : it->second.second)
|
||||
{
|
||||
case taaNONE:
|
||||
sleEntry = mLedger->getSLE(uIndex);
|
||||
if (sleEntry)
|
||||
mEntries[uIndex] = std::make_pair(sleEntry, taaCACHED); // Add to cache.
|
||||
break;
|
||||
|
||||
case taaCREATE:
|
||||
case taaCACHED:
|
||||
case taaMODIFY:
|
||||
sleEntry = it->second.first; // Get from cache.
|
||||
break;
|
||||
|
||||
case taaDELETE:
|
||||
assert(false); // Unexpected case.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return sleEntry;
|
||||
}
|
||||
|
||||
SLE::pointer TransactionEngine::entryCreate(LedgerEntryType letType, const uint256& uIndex)
|
||||
{
|
||||
assert(!uIndex.isZero());
|
||||
@@ -653,16 +695,17 @@ void TransactionEngine::entryDelete(SLE::pointer sleEntry)
|
||||
switch (it == mEntries.end() ? taaNONE : it->second.second)
|
||||
{
|
||||
case taaCREATE:
|
||||
assert(false); // Unexpected case.
|
||||
assert(false); // Unexpected case.
|
||||
break;
|
||||
|
||||
case taaCACHED:
|
||||
case taaMODIFY:
|
||||
case taaNONE:
|
||||
mEntries[uIndex] = std::make_pair(sleEntry, taaDELETE); // Upgrade.
|
||||
break;
|
||||
|
||||
case taaDELETE:
|
||||
nothing(); // No change.
|
||||
nothing(); // No change.
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -676,16 +719,17 @@ void TransactionEngine::entryModify(SLE::pointer sleEntry)
|
||||
switch (it == mEntries.end() ? taaNONE : it->second.second)
|
||||
{
|
||||
case taaDELETE:
|
||||
assert(false); // Unexpected case.
|
||||
assert(false); // Unexpected case.
|
||||
break;
|
||||
|
||||
case taaCACHED:
|
||||
case taaNONE:
|
||||
mEntries[uIndex] = std::make_pair(sleEntry, taaMODIFY); // Upgrade.
|
||||
break;
|
||||
|
||||
case taaCREATE:
|
||||
case taaMODIFY:
|
||||
nothing(); // No change.
|
||||
nothing(); // No change.
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -703,6 +747,9 @@ void TransactionEngine::txnWrite()
|
||||
assert(false);
|
||||
break;
|
||||
|
||||
case taaCACHED:
|
||||
break;
|
||||
|
||||
case taaCREATE:
|
||||
{
|
||||
Log(lsINFO) << "applyTransaction: taaCREATE: " << sleEntry->getText();
|
||||
@@ -733,6 +780,21 @@ void TransactionEngine::txnWrite()
|
||||
}
|
||||
}
|
||||
|
||||
// This is for when a transaction fails from the issuer's point of view and the current changes need to be cleared so other
|
||||
// actions can be applied to the ledger.
|
||||
void TransactionEngine::entryReset(const SerializedTransaction& txn)
|
||||
{
|
||||
mEntries.clear(); // Lose old SLE modifications.
|
||||
mTxnAccount = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(mTxnAccountID)); // Get new SLE.
|
||||
|
||||
entryModify(mTxnAccount);
|
||||
|
||||
STAmount saPaid = txn.getTransactionFee();
|
||||
STAmount saSrcBalance = mTxnAccount->getIValueFieldAmount(sfBalance);
|
||||
|
||||
mTxnAccount->setIFieldAmount(sfBalance, saSrcBalance - saPaid);
|
||||
}
|
||||
|
||||
TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn,
|
||||
TransactionEngineParams params)
|
||||
{
|
||||
@@ -811,8 +873,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
||||
|
||||
case ttNICKNAME_SET:
|
||||
{
|
||||
LedgerStateParms qry = lepNONE;
|
||||
SLE::pointer sleNickname = mLedger->getNickname(qry, txn.getITFieldH256(sfNickname));
|
||||
SLE::pointer sleNickname = entryCache(ltNICKNAME, txn.getITFieldH256(sfNickname));
|
||||
|
||||
if (!sleNickname)
|
||||
saCost = theConfig.FEE_NICKNAME_CREATE;
|
||||
@@ -880,7 +941,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
||||
|
||||
boost::recursive_mutex::scoped_lock sl(mLedger->mLock);
|
||||
|
||||
mTxnAccount = mLedger->getAccountRoot(mTxnAccountID);
|
||||
mTxnAccount = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(mTxnAccountID));
|
||||
|
||||
// Find source account
|
||||
// If are only forwarding, due to resource limitations, we might verifying only some transactions, this would be probablistic.
|
||||
@@ -1118,28 +1179,6 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
||||
|
||||
Log(lsINFO) << "applyTransaction: terResult=" << strToken << " : " << terResult << " : " << strHuman;
|
||||
|
||||
#if 0
|
||||
if (terSUCCESS == terResult)
|
||||
{
|
||||
// Transaction failed. Process possible unfunded offers.
|
||||
// XXX Make sure this stop changed cached entries:
|
||||
mEntries.clear(); // Drop old modifications.
|
||||
|
||||
BOOST_FOREACH(const uint256& uOfferIndex, mUnfunded)
|
||||
{
|
||||
SLE::pointer sleOffer = mLedger->getOffer(uOfferIndex);
|
||||
uint160 uOfferID = sleOffer->getIValueFieldAccount(sfAccount).getAccountID();
|
||||
STAmount saOfferFunds = sleOffer->getIValueFieldAmount(sfTakerGets);
|
||||
|
||||
if (!accountFunds(uOfferID, saOfferFunds).isPositive())
|
||||
{
|
||||
offerDelete(sleOffer, uOfferIndex, uOfferID);
|
||||
bWrite = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (terSUCCESS == terResult)
|
||||
{
|
||||
txnWrite();
|
||||
@@ -1263,7 +1302,7 @@ TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransacti
|
||||
return tenDST_IS_SRC;
|
||||
}
|
||||
|
||||
SLE::pointer sleDst = mLedger->getAccountRoot(uDstAccountID);
|
||||
SLE::pointer sleDst = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uDstAccountID));
|
||||
if (!sleDst)
|
||||
{
|
||||
Log(lsINFO) << "doCreditSet: Delay transaction: Destination account does not exist.";
|
||||
@@ -1279,7 +1318,7 @@ TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransacti
|
||||
bool bAddIndex = false;
|
||||
bool bDelIndex = false;
|
||||
|
||||
SLE::pointer sleRippleState = mLedger->getRippleState(mTxnAccountID, uDstAccountID, uCurrency);
|
||||
SLE::pointer sleRippleState = entryCache(ltRIPPLE_STATE, Ledger::getRippleStateIndex(mTxnAccountID, uDstAccountID, uCurrency));
|
||||
if (sleRippleState)
|
||||
{
|
||||
// A line exists in one or more directions.
|
||||
@@ -1366,8 +1405,7 @@ TransactionEngineResult TransactionEngine::doNicknameSet(const SerializedTransac
|
||||
bool bMinOffer = txn.getITFieldPresent(sfMinimumOffer);
|
||||
STAmount saMinOffer = bMinOffer ? txn.getITFieldAmount(sfAmount) : STAmount();
|
||||
|
||||
LedgerStateParms qry = lepNONE;
|
||||
SLE::pointer sleNickname = mLedger->getNickname(qry, uNickname);
|
||||
SLE::pointer sleNickname = entryCache(ltNICKNAME, uNickname);
|
||||
|
||||
if (sleNickname)
|
||||
{
|
||||
@@ -1412,7 +1450,7 @@ TransactionEngineResult TransactionEngine::doPasswordFund(const SerializedTransa
|
||||
uint160 uDstAccountID = txn.getITFieldAccount(sfDestination);
|
||||
SLE::pointer sleDst = mTxnAccountID == uDstAccountID
|
||||
? mTxnAccount
|
||||
: mLedger->getAccountRoot(uDstAccountID);
|
||||
: entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uDstAccountID));
|
||||
if (!sleDst)
|
||||
{
|
||||
// Destination account does not exist.
|
||||
@@ -1622,7 +1660,7 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
|
||||
}
|
||||
else if (!saDstAmount.isPositive())
|
||||
{
|
||||
Log(lsINFO) << "doPayment: Invalid transaction: bad amount: " << saDstAmount.getCurrencyHuman() << " " << saDstAmount.getText();
|
||||
Log(lsINFO) << "doPayment: Invalid transaction: bad amount: " << saDstAmount.getHumanCurrency() << " " << saDstAmount.getText();
|
||||
|
||||
return tenBAD_AMOUNT;
|
||||
}
|
||||
@@ -1637,7 +1675,7 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
|
||||
return tenREDUNDANT;
|
||||
}
|
||||
|
||||
SLE::pointer sleDst = mLedger->getAccountRoot(uDstAccountID);
|
||||
SLE::pointer sleDst = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uDstAccountID));
|
||||
if (!sleDst)
|
||||
{
|
||||
// Destination account does not exist.
|
||||
@@ -1703,7 +1741,7 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
|
||||
// Try direct ripple first.
|
||||
if (!bNoRippleDirect && mTxnAccountID != uDstAccountID && uSrcCurrency == uDstCurrency)
|
||||
{
|
||||
SLE::pointer sleRippleState = mLedger->getRippleState(mTxnAccountID, uDstAccountID, uDstCurrency);
|
||||
SLE::pointer sleRippleState = entryCache(ltRIPPLE_STATE, Ledger::getRippleStateIndex(mTxnAccountID, uDstAccountID, uDstCurrency));
|
||||
|
||||
if (sleRippleState)
|
||||
{
|
||||
@@ -1804,6 +1842,28 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// XXX Or additionally queue unfundeds for removal on failure.
|
||||
if (terSUCCESS == terResult)
|
||||
{
|
||||
// Transaction failed. Process possible unfunded offers.
|
||||
entryReset(txn);
|
||||
|
||||
BOOST_FOREACH(const uint256& uOfferIndex, mUnfunded)
|
||||
{
|
||||
SLE::pointer sleOffer = mLedger->getOffer(uOfferIndex);
|
||||
uint160 uOfferID = sleOffer->getIValueFieldAccount(sfAccount).getAccountID();
|
||||
STAmount saOfferFunds = sleOffer->getIValueFieldAmount(sfTakerGets);
|
||||
|
||||
if (!accountFunds(uOfferID, saOfferFunds).isPositive())
|
||||
{
|
||||
offerDelete(sleOffer, uOfferIndex, uOfferID);
|
||||
bWrite = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Log(lsINFO) << "doPayment: Delay transaction: No ripple paths could be satisfied.";
|
||||
|
||||
return terBAD_RIPPLE;
|
||||
@@ -1826,7 +1886,7 @@ TransactionEngineResult TransactionEngine::doWalletAdd(const SerializedTransacti
|
||||
return tenBAD_ADD_AUTH;
|
||||
}
|
||||
|
||||
SLE::pointer sleDst = mLedger->getAccountRoot(uDstAccountID);
|
||||
SLE::pointer sleDst = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uDstAccountID));
|
||||
|
||||
if (sleDst)
|
||||
{
|
||||
@@ -1879,8 +1939,6 @@ TransactionEngineResult TransactionEngine::doInvoice(const SerializedTransaction
|
||||
// <-- saTakerGot: What taker got not including fees. To reduce an offer.
|
||||
// <-- terResult: terSUCCESS or terNO_ACCOUNT
|
||||
// Note: All SLE modifications must always occur even on failure.
|
||||
// XXX The tricky part - make sure all adjusted balances should stick for the errors found or make an undo.
|
||||
// XXX Or additionally queue unfundeds for removal on failure.
|
||||
TransactionEngineResult TransactionEngine::takeOffers(
|
||||
bool bPassive,
|
||||
const uint256& uBookBase,
|
||||
@@ -1917,7 +1975,7 @@ TransactionEngineResult TransactionEngine::takeOffers(
|
||||
{
|
||||
// Taker has needs.
|
||||
|
||||
sleOfferDir = mLedger->getNextSLE(uTipIndex, uBookEnd);
|
||||
sleOfferDir = entryCache(ltDIR_NODE, mLedger->getNextLedgerIndex(uTipIndex, uBookEnd));
|
||||
if (sleOfferDir)
|
||||
{
|
||||
Log(lsINFO) << "takeOffers: possible counter offer found";
|
||||
@@ -1951,7 +2009,7 @@ TransactionEngineResult TransactionEngine::takeOffers(
|
||||
|
||||
dirFirst(uTipIndex, uOfferIndex, uOfferNode);
|
||||
|
||||
SLE::pointer sleOffer = mLedger->getSLE(uOfferIndex);
|
||||
SLE::pointer sleOffer = entryCache(ltOFFER, uOfferIndex);
|
||||
|
||||
Log(lsINFO) << "takeOffers: considering offer : " << sleOffer->getJson(0);
|
||||
|
||||
@@ -1978,9 +2036,9 @@ TransactionEngineResult TransactionEngine::takeOffers(
|
||||
else
|
||||
{
|
||||
// Get offer funds available.
|
||||
uint160 uPaysIssuerID = sleOffer->getIValueFieldAccount(sfPaysIssuer).getAccountID();
|
||||
|
||||
saOfferPays.setIssuer(uPaysIssuerID);
|
||||
if (sleOffer->getIFieldPresent(sfPaysIssuer))
|
||||
saOfferPays.setIssuer(sleOffer->getIValueFieldAccount(sfPaysIssuer).getAccountID());
|
||||
|
||||
STAmount saOfferFunds = accountFunds(uOfferOwnerID, saOfferPays);
|
||||
STAmount saTakerFunds = accountFunds(uTakerAccountID, saTakerPays);
|
||||
@@ -2050,12 +2108,17 @@ TransactionEngineResult TransactionEngine::takeOffers(
|
||||
|
||||
TransactionEngineResult TransactionEngine::doOfferCreate(const SerializedTransaction& txn)
|
||||
{
|
||||
Log(lsWARNING) << "doOfferCreate> " << txn.getJson(0);
|
||||
uint32 txFlags = txn.getFlags();
|
||||
bool bPassive = !!(txFlags & tfPassive);
|
||||
STAmount saTakerPays = txn.getITFieldAmount(sfTakerPays);
|
||||
STAmount saTakerGets = txn.getITFieldAmount(sfTakerGets);
|
||||
uint160 uPaysIssuerID = txn.getITFieldAccount(sfPaysIssuer);
|
||||
uint160 uGetsIssuerID = txn.getITFieldAccount(sfGetsIssuer);
|
||||
STAmount saTakerPays = txn.getITFieldAmount(sfTakerPays);
|
||||
saTakerPays.setIssuer(uPaysIssuerID);
|
||||
Log(lsWARNING) << "doOfferCreate: saTakerPays=" << saTakerPays.getJson(0);
|
||||
STAmount saTakerGets = txn.getITFieldAmount(sfTakerGets);
|
||||
saTakerGets.setIssuer(uGetsIssuerID);
|
||||
Log(lsWARNING) << "doOfferCreate: saTakerGets=" << saTakerGets.getJson(0);
|
||||
uint32 uExpiration = txn.getITFieldU32(sfExpiration);
|
||||
bool bHaveExpiration = txn.getITFieldPresent(sfExpiration);
|
||||
uint32 uSequence = txn.getSequence();
|
||||
@@ -2110,7 +2173,7 @@ TransactionEngineResult TransactionEngine::doOfferCreate(const SerializedTransac
|
||||
|
||||
terResult = tenBAD_ISSUER;
|
||||
}
|
||||
else if (!accountFunds(mTxnAccountID, saTakerPays).isPositive())
|
||||
else if (!accountFunds(mTxnAccountID, saTakerGets).isPositive())
|
||||
{
|
||||
Log(lsWARNING) << "doOfferCreate: delay: offers must be funded";
|
||||
|
||||
@@ -2119,7 +2182,7 @@ TransactionEngineResult TransactionEngine::doOfferCreate(const SerializedTransac
|
||||
|
||||
if (terSUCCESS == terResult && !saTakerPays.isNative())
|
||||
{
|
||||
SLE::pointer sleTakerPays = mLedger->getAccountRoot(uPaysIssuerID);
|
||||
SLE::pointer sleTakerPays = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uPaysIssuerID));
|
||||
|
||||
if (!sleTakerPays)
|
||||
{
|
||||
@@ -2137,9 +2200,9 @@ TransactionEngineResult TransactionEngine::doOfferCreate(const SerializedTransac
|
||||
|
||||
Log(lsINFO) << str(boost::format("doOfferCreate: take against book: %s : %s/%s -> %s/%s")
|
||||
% uTakeBookBase.ToString()
|
||||
% saTakerGets.getCurrencyHuman()
|
||||
% saTakerGets.getHumanCurrency()
|
||||
% NewcoinAddress::createHumanAccountID(saTakerGets.getIssuer())
|
||||
% saTakerPays.getCurrencyHuman()
|
||||
% saTakerPays.getHumanCurrency()
|
||||
% NewcoinAddress::createHumanAccountID(saTakerPays.getIssuer()));
|
||||
|
||||
// Take using the parameters of the offer.
|
||||
@@ -2155,6 +2218,8 @@ TransactionEngineResult TransactionEngine::doOfferCreate(const SerializedTransac
|
||||
);
|
||||
|
||||
Log(lsWARNING) << "doOfferCreate: takeOffers=" << terResult;
|
||||
Log(lsWARNING) << "doOfferCreate: takeOffers: saOfferPaid=" << saOfferPaid.getText();
|
||||
Log(lsWARNING) << "doOfferCreate: takeOffers: saOfferGot=" << saOfferGot.getText();
|
||||
|
||||
if (terSUCCESS == terResult)
|
||||
{
|
||||
@@ -2163,14 +2228,18 @@ TransactionEngineResult TransactionEngine::doOfferCreate(const SerializedTransac
|
||||
}
|
||||
}
|
||||
|
||||
// Log(lsWARNING) << "doOfferCreate: takeOffers: saTakerPays=" << saTakerPays.getText();
|
||||
// Log(lsWARNING) << "doOfferCreate: takeOffers: saTakerGets=" << saTakerGets.getText();
|
||||
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: mTxnAccountID=" << NewcoinAddress::createHumanAccountID(mTxnAccountID);
|
||||
Log(lsWARNING) << "doOfferCreate: takeOffers: funds=" << accountFunds(mTxnAccountID, saTakerGets).getText();
|
||||
|
||||
// Log(lsWARNING) << "doOfferCreate: takeOffers: uPaysIssuerID=" << NewcoinAddress::createHumanAccountID(uPaysIssuerID);
|
||||
// Log(lsWARNING) << "doOfferCreate: takeOffers: uGetsIssuerID=" << NewcoinAddress::createHumanAccountID(uGetsIssuerID);
|
||||
|
||||
if (terSUCCESS == terResult
|
||||
&& !saTakerGets.isZero() // Still offering something.
|
||||
&& !saTakerPays.isZero() // Still wanting something.
|
||||
&& !saTakerGets.isZero() // Still offering something.
|
||||
&& accountFunds(mTxnAccountID, saTakerGets).isPositive()) // Still funded.
|
||||
{
|
||||
// We need to place the remainder of the offer into its order book.
|
||||
@@ -2184,9 +2253,9 @@ TransactionEngineResult TransactionEngine::doOfferCreate(const SerializedTransac
|
||||
|
||||
Log(lsINFO) << str(boost::format("doOfferCreate: adding to book: %s : %s/%s -> %s/%s")
|
||||
% uBookBase.ToString()
|
||||
% saTakerPays.getCurrencyHuman()
|
||||
% saTakerPays.getHumanCurrency()
|
||||
% NewcoinAddress::createHumanAccountID(saTakerPays.getIssuer())
|
||||
% saTakerGets.getCurrencyHuman()
|
||||
% saTakerGets.getHumanCurrency()
|
||||
% NewcoinAddress::createHumanAccountID(saTakerGets.getIssuer()));
|
||||
|
||||
uDirectory = Ledger::getQualityIndex(uBookBase, uRate); // Use original rate.
|
||||
@@ -2201,8 +2270,8 @@ TransactionEngineResult TransactionEngine::doOfferCreate(const SerializedTransac
|
||||
// Log(lsWARNING) << "doOfferCreate: uGetsIssuerID=" << NewcoinAddress::createHumanAccountID(uGetsIssuerID);
|
||||
// Log(lsWARNING) << "doOfferCreate: saTakerPays.isNative()=" << saTakerPays.isNative();
|
||||
// Log(lsWARNING) << "doOfferCreate: saTakerGets.isNative()=" << saTakerGets.isNative();
|
||||
// Log(lsWARNING) << "doOfferCreate: uPaysCurrency=" << saTakerPays.getCurrencyHuman();
|
||||
// Log(lsWARNING) << "doOfferCreate: uGetsCurrency=" << saTakerGets.getCurrencyHuman();
|
||||
// Log(lsWARNING) << "doOfferCreate: uPaysCurrency=" << saTakerPays.getHumanCurrency();
|
||||
// Log(lsWARNING) << "doOfferCreate: uGetsCurrency=" << saTakerGets.getHumanCurrency();
|
||||
|
||||
sleOffer->setIFieldAccount(sfAccount, mTxnAccountID);
|
||||
sleOffer->setIFieldU32(sfSequence, uSequence);
|
||||
@@ -2234,7 +2303,7 @@ TransactionEngineResult TransactionEngine::doOfferCancel(const SerializedTransac
|
||||
TransactionEngineResult terResult;
|
||||
uint32 uSequence = txn.getITFieldU32(sfOfferSequence);
|
||||
uint256 uOfferIndex = Ledger::getOfferIndex(mTxnAccountID, uSequence);
|
||||
SLE::pointer sleOffer = mLedger->getOffer(uOfferIndex);
|
||||
SLE::pointer sleOffer = entryCache(ltOFFER, uOfferIndex);
|
||||
|
||||
if (sleOffer)
|
||||
{
|
||||
|
||||
@@ -93,9 +93,10 @@ enum TransactionEngineParams
|
||||
enum TransactionAccountAction
|
||||
{
|
||||
taaNONE,
|
||||
taaCREATE,
|
||||
taaMODIFY,
|
||||
taaDELETE,
|
||||
taaCACHED, // Unmodified.
|
||||
taaMODIFY, // Modifed, must have previously been taaCACHED.
|
||||
taaDELETE, // Delete, must have previously been taaDELETE or taaMODIFY.
|
||||
taaCREATE, // Newly created.
|
||||
};
|
||||
|
||||
typedef std::pair<TransactionAccountAction, SerializedLedgerEntry::pointer> AffectedAccount;
|
||||
@@ -167,18 +168,21 @@ protected:
|
||||
boost::unordered_set<uint256> mUnfunded; // Indexes that were found unfunded.
|
||||
|
||||
SLE::pointer entryCreate(LedgerEntryType letType, const uint256& uIndex);
|
||||
SLE::pointer entryCache(LedgerEntryType letType, const uint256& uIndex);
|
||||
void entryDelete(SLE::pointer sleEntry);
|
||||
void entryModify(SLE::pointer sleEntry);
|
||||
|
||||
STAmount rippleHolds(const uint160& uAccountID, const uint160& uCurrency, const uint160& uIssuerID);
|
||||
STAmount rippleTransit(const uint160& uSenderID, const uint160& uReceiverID, const uint160& uIssuerID, const STAmount& saAmount);
|
||||
STAmount rippleSend(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount);
|
||||
void entryReset(const SerializedTransaction& txn);
|
||||
|
||||
STAmount accountHolds(const uint160& uAccountID, const uint160& uCurrency, const uint160& uIssuerID);
|
||||
STAmount accountSend(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount);
|
||||
STAmount accountFunds(const uint160& uAccountID, const STAmount& saDefault);
|
||||
STAmount rippleHolds(const uint160& uAccountID, const uint160& uCurrency, const uint160& uIssuerID);
|
||||
STAmount rippleTransit(const uint160& uSenderID, const uint160& uReceiverID, const uint160& uIssuerID, const STAmount& saAmount);
|
||||
STAmount rippleSend(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount);
|
||||
|
||||
void txnWrite();
|
||||
STAmount accountHolds(const uint160& uAccountID, const uint160& uCurrency, const uint160& uIssuerID);
|
||||
STAmount accountSend(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount);
|
||||
STAmount accountFunds(const uint160& uAccountID, const STAmount& saDefault);
|
||||
|
||||
void txnWrite();
|
||||
|
||||
TransactionEngineResult offerDelete(const SLE::pointer& sleOffer, const uint256& uOfferIndex, const uint160& uOwnerID);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user