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:
@@ -1131,15 +1131,13 @@ 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)
|
||||
{
|
||||
// It is an error for currency or issuer not to be specified for valid json.
|
||||
|
||||
elem["value"] = getText();
|
||||
elem["currency"] = getHumanCurrency();
|
||||
|
||||
if (!mIssuer.isZero())
|
||||
elem["issuer"] = NewcoinAddress::createHumanAccountID(mIssuer);
|
||||
|
||||
elem["issuer"] = NewcoinAddress::createHumanAccountID(mIssuer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -208,17 +208,25 @@ void Application::startNewLedger()
|
||||
|
||||
void Application::loadOldLedger()
|
||||
{
|
||||
Ledger::pointer lastLedger = Ledger::getSQL("SELECT * from Ledgers order by LedgerSeq desc limit 1;");
|
||||
|
||||
if (!lastLedger)
|
||||
try
|
||||
{
|
||||
std::cout << "No Ledger found?" << std::endl;
|
||||
Ledger::pointer lastLedger = Ledger::getSQL("SELECT * from Ledgers order by LedgerSeq desc limit 1;");
|
||||
|
||||
if (!lastLedger)
|
||||
{
|
||||
std::cout << "No Ledger found?" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
lastLedger->setClosed();
|
||||
|
||||
Ledger::pointer openLedger = boost::make_shared<Ledger>(false, boost::ref(*lastLedger));
|
||||
mMasterLedger.switchLedgers(lastLedger, openLedger);
|
||||
mNetOps.setLastCloseTime(lastLedger->getCloseTimeNC());
|
||||
}
|
||||
catch (SHAMapMissingNode& mn)
|
||||
{
|
||||
Log(lsFATAL) << "Cannot load ledger. " << mn;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
lastLedger->setClosed();
|
||||
Ledger::pointer openLedger = boost::make_shared<Ledger>(false, boost::ref(*lastLedger));
|
||||
mMasterLedger.switchLedgers(lastLedger, openLedger);
|
||||
mNetOps.setLastCloseTime(lastLedger->getCloseTimeNC());
|
||||
}
|
||||
// vim:ts=4
|
||||
|
||||
@@ -24,7 +24,8 @@ SETUP_LOG();
|
||||
Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(startAmount), mLedgerSeq(1),
|
||||
mCloseTime(0), mParentCloseTime(0), mCloseResolution(LEDGER_TIME_ACCURACY), mCloseFlags(0),
|
||||
mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false),
|
||||
mTransactionMap(new SHAMap(smtTRANSACTION)), mAccountStateMap(new SHAMap(smtFREE))
|
||||
mTransactionMap(boost::make_shared<SHAMap>(smtTRANSACTION)),
|
||||
mAccountStateMap(boost::make_shared<SHAMap>(smtSTATE))
|
||||
{
|
||||
// special case: put coins in root account
|
||||
AccountState::pointer startAccount = boost::make_shared<AccountState>(masterID);
|
||||
@@ -38,13 +39,21 @@ Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(s
|
||||
}
|
||||
|
||||
Ledger::Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
||||
uint64 totCoins, uint32 closeTime, uint32 parentCloseTime, int closeFlags, int closeResolution, uint32 ledgerSeq,bool isMutable)
|
||||
uint64 totCoins, uint32 closeTime, uint32 parentCloseTime, int closeFlags, int closeResolution, uint32 ledgerSeq)
|
||||
: mParentHash(parentHash), mTransHash(transHash), mAccountHash(accountHash), mTotCoins(totCoins),
|
||||
mLedgerSeq(ledgerSeq), mCloseTime(closeTime), mParentCloseTime(parentCloseTime),
|
||||
mCloseResolution(closeResolution), mCloseFlags(closeFlags),
|
||||
mClosed(false), mValidHash(false), mAccepted(false), mImmutable(isMutable)
|
||||
{
|
||||
mClosed(false), mValidHash(false), mAccepted(false), mImmutable(true),
|
||||
mTransactionMap(boost::make_shared<SHAMap>(smtTRANSACTION, transHash)),
|
||||
mAccountStateMap(boost::make_shared<SHAMap>(smtSTATE, accountHash))
|
||||
{ // This will throw if the root nodes are not available locally
|
||||
updateHash();
|
||||
if (mTransHash.isNonZero())
|
||||
mTransactionMap->fetchRoot(mTransHash);
|
||||
if (mAccountHash.isNonZero())
|
||||
mAccountStateMap->fetchRoot(mAccountHash);
|
||||
mTransactionMap->setImmutable();
|
||||
mAccountStateMap->setImmutable();
|
||||
}
|
||||
|
||||
Ledger::Ledger(Ledger& ledger, bool isMutable) : mTotCoins(ledger.mTotCoins), mLedgerSeq(ledger.mLedgerSeq),
|
||||
@@ -62,7 +71,8 @@ Ledger::Ledger(bool /* dummy */, Ledger& prevLedger) :
|
||||
mTotCoins(prevLedger.mTotCoins), mLedgerSeq(prevLedger.mLedgerSeq + 1),
|
||||
mParentCloseTime(prevLedger.mCloseTime), mCloseResolution(prevLedger.mCloseResolution),
|
||||
mCloseFlags(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false),
|
||||
mTransactionMap(new SHAMap(smtTRANSACTION)), mAccountStateMap(prevLedger.mAccountStateMap->snapShot(true))
|
||||
mTransactionMap(boost::make_shared<SHAMap>(smtTRANSACTION)),
|
||||
mAccountStateMap(prevLedger.mAccountStateMap->snapShot(true))
|
||||
{ // Create a new ledger that follows this one
|
||||
prevLedger.updateHash();
|
||||
mParentHash = prevLedger.getHash();
|
||||
@@ -328,10 +338,11 @@ void Ledger::saveAcceptedLedger(Ledger::ref ledger)
|
||||
ledger->mAccountHash.GetHex() % ledger->mTransHash.GetHex()));
|
||||
|
||||
// write out dirty nodes
|
||||
while(ledger->mTransactionMap->flushDirty(256, hotTRANSACTION_NODE, ledger->mLedgerSeq))
|
||||
{ ; }
|
||||
while(ledger->mAccountStateMap->flushDirty(256, hotACCOUNT_NODE, ledger->mLedgerSeq))
|
||||
{ ; }
|
||||
int fc;
|
||||
while ((fc = ledger->mTransactionMap->flushDirty(256, hotTRANSACTION_NODE, ledger->mLedgerSeq)) > 0)
|
||||
{ cLog(lsINFO) << "Flushed " << fc << " dirty transaction nodes"; }
|
||||
while ((fc = ledger->mAccountStateMap->flushDirty(256, hotACCOUNT_NODE, ledger->mLedgerSeq)) > 0)
|
||||
{ cLog(lsINFO) << "Flushed " << fc << " dirty state nodes"; }
|
||||
ledger->disarmDirty();
|
||||
|
||||
SHAMap& txSet = *ledger->peekTransactionMap();
|
||||
@@ -425,7 +436,7 @@ Ledger::pointer Ledger::getSQL(const std::string& sql)
|
||||
}
|
||||
|
||||
Ledger::pointer ret = Ledger::pointer(new Ledger(prevHash, transHash, accountHash, totCoins,
|
||||
closingTime, prevClosingTime, closeFlags, closeResolution, ledgerSeq, true));
|
||||
closingTime, prevClosingTime, closeFlags, closeResolution, ledgerSeq));
|
||||
if (ret->getHash() != ledgerHash)
|
||||
{
|
||||
if (sLog(lsERROR))
|
||||
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
|
||||
Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
||||
uint64 totCoins, uint32 closeTime, uint32 parentCloseTime, int closeFlags, int closeResolution,
|
||||
uint32 ledgerSeq, bool immutable); // used for database ledgers
|
||||
uint32 ledgerSeq); // used for database ledgers
|
||||
|
||||
Ledger(const std::vector<unsigned char>& rawLedger);
|
||||
|
||||
|
||||
@@ -96,6 +96,45 @@ LedgerAcquire::LedgerAcquire(const uint256& hash) : PeerSet(hash, LEDGER_ACQUIRE
|
||||
#endif
|
||||
}
|
||||
|
||||
bool LedgerAcquire::tryLocal()
|
||||
{ // return value: true = no more work to do
|
||||
HashedObject::pointer node = theApp->getHashedObjectStore().retrieve(mHash);
|
||||
if (!node)
|
||||
return false;
|
||||
|
||||
mLedger = boost::make_shared<Ledger>(strCopy(node->getData()));
|
||||
assert(mLedger->getHash() == mHash);
|
||||
mHaveBase = true;
|
||||
|
||||
if (!mLedger->getTransHash())
|
||||
mHaveTransactions = true;
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
mLedger->peekTransactionMap()->fetchRoot(mLedger->getTransHash());
|
||||
}
|
||||
catch (SHAMapMissingNode&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (!mLedger->getAccountHash())
|
||||
mHaveState = true;
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
mLedger->peekAccountStateMap()->fetchRoot(mLedger->getAccountHash());
|
||||
}
|
||||
catch (SHAMapMissingNode&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return mHaveTransactions && mHaveState;
|
||||
}
|
||||
|
||||
void LedgerAcquire::onTimer()
|
||||
{
|
||||
if (getTimeouts() > 6)
|
||||
@@ -124,7 +163,7 @@ void LedgerAcquire::done()
|
||||
setComplete();
|
||||
mLock.lock();
|
||||
triggers = mOnComplete;
|
||||
mOnComplete.empty();
|
||||
mOnComplete.clear();
|
||||
mLock.unlock();
|
||||
|
||||
if (mLedger)
|
||||
|
||||
@@ -94,6 +94,7 @@ public:
|
||||
bool takeAsNode(const std::list<SHAMapNode>& IDs, const std::list<std::vector<unsigned char> >& data);
|
||||
bool takeAsRootNode(const std::vector<unsigned char>& data);
|
||||
void trigger(Peer::ref, bool timer);
|
||||
bool tryLocal();
|
||||
};
|
||||
|
||||
class LedgerAcquireMaster
|
||||
|
||||
@@ -585,7 +585,6 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
|
||||
if (!mAcquiringLedger->isComplete())
|
||||
{ // add more peers
|
||||
int count = 0;
|
||||
std::vector<Peer::pointer> peers=theApp->getConnectionPool().getPeerVector();
|
||||
BOOST_FOREACH(Peer::ref it, peerList)
|
||||
{
|
||||
if (it->getClosedLedgerHash() == closedLedger)
|
||||
|
||||
@@ -69,6 +69,6 @@ CKey::pointer PubKeyCache::store(const NewcoinAddress& id, const CKey::pointer&
|
||||
void PubKeyCache::clear()
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
mCache.empty();
|
||||
mCache.clear();
|
||||
}
|
||||
// vim:ts=4
|
||||
|
||||
@@ -1816,21 +1816,25 @@ void RippleCalc::pathNext(const PathState::pointer& pspCur, const int iPaths, co
|
||||
lesCurrent.bumpSeq(); // Begin ledger varance.
|
||||
|
||||
pspCur->terStatus = calcNodeFwd(0, pspCur, bMultiQuality);
|
||||
}
|
||||
|
||||
tLog(tesSUCCESS == pspCur->terStatus, lsDEBUG)
|
||||
if (tesSUCCESS == pspCur->terStatus)
|
||||
{
|
||||
tLog(!pspCur->saInPass || !pspCur->saOutPass, lsDEBUG)
|
||||
<< boost::str(boost::format("saOutPass=%s saInPass=%s")
|
||||
% pspCur->saOutPass.getFullText()
|
||||
% pspCur->saInPass.getFullText());
|
||||
|
||||
// Make sure we have a quality.
|
||||
assert(tesSUCCESS != pspCur->terStatus || (!!pspCur->saOutPass && !!pspCur->saInPass));
|
||||
assert(!!pspCur->saOutPass && !!pspCur->saInPass);
|
||||
|
||||
pspCur->uQuality = tesSUCCESS == pspCur->terStatus
|
||||
? STAmount::getRate(pspCur->saOutPass, pspCur->saInPass) // Calculate relative quality.
|
||||
: 0; // Mark path as inactive.
|
||||
pspCur->uQuality = STAmount::getRate(pspCur->saOutPass, pspCur->saInPass); // Calculate relative quality.
|
||||
|
||||
cLog(lsINFO) << "Path after forward: " << pspCur->getJson();
|
||||
}
|
||||
else
|
||||
{
|
||||
pspCur->uQuality = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Stand alone calculation not implemented, does not calculate required input.
|
||||
@@ -1968,12 +1972,27 @@ TER RippleCalc::rippleCalc(
|
||||
|
||||
nothing();
|
||||
}
|
||||
else if ((!bLimitQuality || pspCur->uQuality <= uQualityLimit) // Quality is not limted or increment has allowed quality.
|
||||
|| !pspBest // Best is not yet set.
|
||||
|| PathState::lessPriority(pspBest, pspCur)) // Current is better than set.
|
||||
{
|
||||
lesActive.swapWith(pspCur->lesEntries); // For the path, save ledger state.
|
||||
pspBest = pspCur;
|
||||
else {
|
||||
tLog(!pspCur->saInPass || !pspCur->saOutPass, lsDEBUG)
|
||||
<< boost::str(boost::format("calcOfferFirst: better: uQuality=%016lX saInPass=%s saOutPass=%s")
|
||||
% pspCur->uQuality
|
||||
% pspCur->saInPass.getFullText()
|
||||
% pspCur->saOutPass.getFullText());
|
||||
|
||||
assert(!!pspCur->saInPass && !!pspCur->saOutPass);
|
||||
|
||||
if ((!bLimitQuality || pspCur->uQuality <= uQualityLimit) // Quality is not limted or increment has allowed quality.
|
||||
|| !pspBest // Best is not yet set.
|
||||
|| PathState::lessPriority(pspBest, pspCur)) // Current is better than set.
|
||||
{
|
||||
cLog(lsDEBUG) << boost::str(boost::format("calcOfferFirst: better: uQuality=%016lX saInPass=%s saOutPass=%s")
|
||||
% pspCur->uQuality
|
||||
% pspCur->saInPass.getFullText()
|
||||
% pspCur->saOutPass.getFullText());
|
||||
|
||||
lesActive.swapWith(pspCur->lesEntries); // For the path, save ledger state.
|
||||
pspBest = pspCur;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1982,6 +2001,11 @@ TER RippleCalc::rippleCalc(
|
||||
{
|
||||
// Apply best path.
|
||||
|
||||
cLog(lsDEBUG) << boost::str(boost::format("calcOfferFirst: best: uQuality=%016lX saInPass=%s saOutPass=%s")
|
||||
% pspBest->uQuality
|
||||
% pspBest->saInPass.getFullText()
|
||||
% pspBest->saOutPass.getFullText());
|
||||
|
||||
// Record best pass' offers that became unfunded for deletion on success.
|
||||
vuUnfundedBecame.insert(vuUnfundedBecame.end(), pspBest->vUnfundedBecame.begin(), pspBest->vUnfundedBecame.end());
|
||||
|
||||
@@ -1991,7 +2015,7 @@ TER RippleCalc::rippleCalc(
|
||||
saInAct += pspBest->saInPass;
|
||||
saOutAct += pspBest->saOutPass;
|
||||
|
||||
if (temUNCERTAIN == terResult && saOutAct == saDstAmountReq)
|
||||
if (saOutAct == saDstAmountReq)
|
||||
{
|
||||
// Done. Delivered requested amount.
|
||||
|
||||
|
||||
@@ -690,7 +690,10 @@ SHAMapTreeNode::pointer SHAMap::fetchNodeExternal(const SHAMapNode& id, const ui
|
||||
|
||||
HashedObject::pointer obj(theApp->getHashedObjectStore().retrieve(hash));
|
||||
if (!obj)
|
||||
{
|
||||
Log(lsTRACE) << "fetchNodeExternal: missing " << hash;
|
||||
throw SHAMapMissingNode(mType, id, hash);
|
||||
}
|
||||
assert(Serializer::getSHA512Half(obj->getData()) == hash);
|
||||
|
||||
try
|
||||
@@ -708,6 +711,13 @@ SHAMapTreeNode::pointer SHAMap::fetchNodeExternal(const SHAMapNode& id, const ui
|
||||
}
|
||||
}
|
||||
|
||||
void SHAMap::fetchRoot(const uint256& hash)
|
||||
{
|
||||
root = fetchNodeExternal(SHAMapNode(), hash);
|
||||
root->makeInner();
|
||||
mTNByID[*root] = root;
|
||||
}
|
||||
|
||||
void SHAMap::armDirty()
|
||||
{ // begin saving dirty nodes
|
||||
++mSeq;
|
||||
@@ -725,6 +735,8 @@ int SHAMap::flushDirty(int maxNodes, HashedObjectType t, uint32 seq)
|
||||
boost::unordered_map<SHAMapNode, SHAMapTreeNode::pointer>::iterator it = dirtyNodes.begin();
|
||||
while (it != dirtyNodes.end())
|
||||
{
|
||||
tLog(mType == smtTRANSACTION, lsDEBUG) << "TX node write " << it->first;
|
||||
tLog(mType == smtSTATE, lsDEBUG) << "STATE node write " << it->first;
|
||||
s.erase();
|
||||
it->second->addRaw(s, snfPREFIX);
|
||||
theApp->getHashedObjectStore().store(t, seq, s.peekData(), s.getSHA512Half());
|
||||
|
||||
@@ -273,6 +273,8 @@ public:
|
||||
bool hasTargetIndex() const { return !mTargetIndex.isZero(); }
|
||||
};
|
||||
|
||||
extern std::ostream& operator<<(std::ostream&, const SHAMapMissingNode&);
|
||||
|
||||
class SHAMap
|
||||
{
|
||||
public:
|
||||
@@ -330,6 +332,7 @@ public:
|
||||
ScopedLock Lock() const { return ScopedLock(mLock); }
|
||||
|
||||
bool hasNode(const SHAMapNode& id);
|
||||
void fetchRoot(const uint256& hash);
|
||||
|
||||
// normal hash access functions
|
||||
bool hasItem(const uint256& id);
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
std::string SHAMapNode::getString() const
|
||||
{
|
||||
if ((mDepth == 0) && (mNodeID.isZero()))
|
||||
return "NodeID(root)";
|
||||
|
||||
return str(boost::format("NodeID(%s,%s)")
|
||||
% boost::lexical_cast<std::string>(mDepth)
|
||||
% mNodeID.GetHex());
|
||||
@@ -507,4 +510,17 @@ bool SHAMapTreeNode::setChildHash(int m, const uint256 &hash)
|
||||
return updateHash();
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const SHAMapMissingNode& mn)
|
||||
{
|
||||
if (mn.getMapType() == smtTRANSACTION)
|
||||
out << "Missing/TXN(" << mn.getNodeID() << ")";
|
||||
else if (mn.getMapType() == smtSTATE)
|
||||
out << "Missing/STA(" << mn.getNodeID() << ")";
|
||||
else
|
||||
out << "Missing/" << mn.getNodeID();
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -120,8 +120,8 @@ std::auto_ptr<SerializedType> STObject::makeDeserializedObject(SerializedTypeID
|
||||
|
||||
void STObject::set(const std::vector<SOElement::ptr>& type)
|
||||
{
|
||||
mData.empty();
|
||||
mType.empty();
|
||||
mData.clear();
|
||||
mType.clear();
|
||||
|
||||
BOOST_FOREACH(const SOElement::ptr& elem, type)
|
||||
{
|
||||
@@ -138,7 +138,7 @@ bool STObject::setType(const std::vector<SOElement::ptr> &type)
|
||||
boost::ptr_vector<SerializedType> newData;
|
||||
bool valid = true;
|
||||
|
||||
mType.empty();
|
||||
mType.clear();
|
||||
BOOST_FOREACH(const SOElement::ptr& elem, type)
|
||||
{
|
||||
bool match = false;
|
||||
@@ -204,7 +204,7 @@ bool STObject::isFieldAllowed(SField::ref field)
|
||||
|
||||
bool STObject::set(SerializerIterator& sit, int depth)
|
||||
{ // return true = terminated with end-of-object
|
||||
mData.empty();
|
||||
mData.clear();
|
||||
while (!sit.empty())
|
||||
{
|
||||
int type, field;
|
||||
|
||||
Reference in New Issue
Block a user