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

This commit is contained in:
Arthur Britto
2012-09-15 14:37:49 -07:00
39 changed files with 437 additions and 213 deletions

View File

@@ -9,6 +9,7 @@
#include "Ledger.h"
#include "Serializer.h"
#include "Log.h"
AccountState::AccountState(const NewcoinAddress& naAccountID) : mAccountID(naAccountID), mValid(false)
{
@@ -59,11 +60,8 @@ void AccountState::addJson(Json::Value& val)
void AccountState::dump()
{
Json::Value j(Json::objectValue);
addJson(j);
Json::StyledStreamWriter ssw;
ssw.write(std::cerr, j);
Log(lsINFO) << j;
}
// vim:ts=4

View File

@@ -78,6 +78,7 @@ public:
NetworkOPs& getOPs() { return mNetOps; }
boost::asio::io_service& getIOService() { return mIOService; }
boost::asio::io_service& getAuxService() { return mAuxService; }
LedgerMaster& getMasterLedger() { return mMasterLedger; }
LedgerAcquireMaster& getMasterLedgerAcquire() { return mMasterLedgerAcquire; }

View File

@@ -14,6 +14,7 @@ const char *TxnDBInit[] = {
LedgerSeq BIGINT UNSIGNED, \
Status CHARACTER(1), \
RawTxn BLOB \
TxnMeta BLOB \
);",
"CREATE TABLE PubKeys ( \
ID CHARACTER(35) PRIMARY KEY, \

View File

@@ -211,35 +211,51 @@ RippleState::pointer Ledger::accessRippleState(const uint256& uNode)
return boost::make_shared<RippleState>(sle);
}
bool Ledger::addTransaction(const Transaction::pointer& trans)
bool Ledger::addTransaction(const uint256& txID, const Serializer& txn)
{ // low-level - just add to table
assert(!mAccepted);
assert(trans->getID().isNonZero());
Serializer s;
trans->getSTransaction()->add(s);
SHAMapItem::pointer item = boost::make_shared<SHAMapItem>(trans->getID(), s.peekData());
if (!mTransactionMap->addGiveItem(item, true, false)) // FIXME: TX metadata
SHAMapItem::pointer item = boost::make_shared<SHAMapItem>(txID, txn.peekData());
if (!mTransactionMap->addGiveItem(item, true, false))
return false;
return true;
}
bool Ledger::addTransaction(const uint256& txID, const Serializer& txn)
bool Ledger::addTransaction(const uint256& txID, const Serializer& txn, const Serializer& md)
{ // low-level - just add to table
SHAMapItem::pointer item = boost::make_shared<SHAMapItem>(txID, txn.peekData());
if (!mTransactionMap->addGiveItem(item, true, false)) // FIXME: TX metadata
Serializer s(txn.getDataLength() + md.getDataLength() + 64);
s.addVL(txn.peekData());
s.addVL(md.peekData());
SHAMapItem::pointer item = boost::make_shared<SHAMapItem>(txID, s.peekData());
if (!mTransactionMap->addGiveItem(item, true, true))
return false;
return true;
}
Transaction::pointer Ledger::getTransaction(const uint256& transID) const
{
SHAMapItem::pointer item = mTransactionMap->peekItem(transID);
SHAMapTreeNode::TNType type;
SHAMapItem::pointer item = mTransactionMap->peekItem(transID, type);
if (!item) return Transaction::pointer();
Transaction::pointer txn = theApp->getMasterTransaction().fetch(transID, false);
if (txn) return txn;
if (txn)
return txn;
if (type == SHAMapTreeNode::tnTRANSACTION_NM)
txn = Transaction::sharedTransaction(item->getData(), true);
else if (type == SHAMapTreeNode::tnTRANSACTION_MD)
{
std::vector<unsigned char> txnData;
int txnLength;
if (!item->peekSerializer().getVL(txnData, 0, txnLength))
return Transaction::pointer();
txn = Transaction::sharedTransaction(txnData, false);
}
else
{
assert(false);
return Transaction::pointer();
}
txn = Transaction::sharedTransaction(item->getData(), true);
if (txn->getStatus() == NEW)
txn->setStatus(mClosed ? COMMITTED : INCLUDED, mLedgerSeq);
@@ -247,6 +263,39 @@ Transaction::pointer Ledger::getTransaction(const uint256& transID) const
return txn;
}
bool Ledger::getTransaction(const uint256& txID, Transaction::pointer& txn, TransactionMetaSet::pointer& meta)
{
SHAMapTreeNode::TNType type;
SHAMapItem::pointer item = mTransactionMap->peekItem(txID, type);
if (!item)
return false;
if (type == SHAMapTreeNode::tnTRANSACTION_NM)
{ // in tree with no metadata
txn = theApp->getMasterTransaction().fetch(txID, false);
meta = TransactionMetaSet::pointer();
if (!txn)
txn = Transaction::sharedTransaction(item->getData(), true);
}
else if (type == SHAMapTreeNode::tnTRANSACTION_MD)
{ // in tree with metadata
SerializerIterator it(item->getData());
txn = theApp->getMasterTransaction().fetch(txID, false);
if (!txn)
txn = Transaction::sharedTransaction(it.getVL(), true);
else
it.getVL(); // skip transaction
meta = boost::make_shared<TransactionMetaSet>(mLedgerSeq, it.getVL());
}
else
return false;
if (txn->getStatus() == NEW)
txn->setStatus(mClosed ? COMMITTED : INCLUDED, mLedgerSeq);
theApp->getMasterTransaction().canonicalize(txn, false);
return true;
}
bool Ledger::unitTest()
{
return true;
@@ -440,14 +489,38 @@ void Ledger::addJson(Json::Value& ret, int options)
if (mTransactionMap && (full || ((options & LEDGER_JSON_DUMP_TXNS) != 0)))
{
Json::Value txns(Json::arrayValue);
for (SHAMapItem::pointer item = mTransactionMap->peekFirstItem(); !!item;
item = mTransactionMap->peekNextItem(item->getTag()))
SHAMapTreeNode::TNType type;
for (SHAMapItem::pointer item = mTransactionMap->peekFirstItem(type); !!item;
item = mTransactionMap->peekNextItem(item->getTag(), type))
{
if (full)
{
SerializerIterator sit(item->peekSerializer());
SerializedTransaction txn(sit);
txns.append(txn.getJson(0));
if (type == SHAMapTreeNode::tnTRANSACTION_NM)
{
SerializerIterator sit(item->peekSerializer());
SerializedTransaction txn(sit);
txns.append(txn.getJson(0));
}
else if (type == SHAMapTreeNode::tnTRANSACTION_MD)
{
SerializerIterator sit(item->peekSerializer());
Serializer sTxn(sit.getVL());
Serializer sMeta(sit.getVL());
SerializerIterator tsit(sTxn);
SerializedTransaction txn(tsit);
TransactionMetaSet meta(mLedgerSeq, sit.getVL());
Json::Value txJson = txn.getJson(0);
txJson["metaData"] = meta.getJson(0);
txns.append(txJson);
}
else
{
Json::Value error = Json::objectValue;
error[item->getTag().GetHex()] = type;
txns.append(error);
}
}
else txns.append(item->getTag().GetHex());
}

View File

@@ -11,6 +11,7 @@
#include "../json/value.h"
#include "Transaction.h"
#include "TransactionMeta.h"
#include "AccountState.h"
#include "RippleState.h"
#include "NicknameState.h"
@@ -56,7 +57,7 @@ public:
TR_PASTASEQ = 6, // account is past this transaction
TR_PREASEQ = 7, // account is missing transactions before this
TR_BADLSEQ = 8, // ledger too early
TR_TOOSMALL = 9, // amount is less than Tx fee
TR_TOOSMALL = 9, // amount is less than Tx fee
};
// ledger close flags
@@ -82,8 +83,6 @@ private:
protected:
bool addTransaction(const Transaction::pointer&);
bool addTransaction(const uint256& id, const Serializer& txn);
static Ledger::pointer getSQL(const std::string& sqlStatement);
@@ -152,8 +151,11 @@ public:
bool isAcquiringAS(void);
// Transaction Functions
bool addTransaction(const uint256& id, const Serializer& txn);
bool addTransaction(const uint256& id, const Serializer& txn, const Serializer& metaData);
bool hasTransaction(const uint256& TransID) const { return mTransactionMap->hasItem(TransID); }
Transaction::pointer getTransaction(const uint256& transID) const;
bool getTransaction(const uint256& transID, Transaction::pointer& txn, TransactionMetaSet::pointer& txMeta);
// high-level functions
AccountState::pointer getAccountState(const NewcoinAddress& acctID);

View File

@@ -84,9 +84,8 @@ void PeerSet::TimerEntry(boost::weak_ptr<PeerSet> wptr, const boost::system::err
if (result == boost::asio::error::operation_aborted)
return;
boost::shared_ptr<PeerSet> ptr = wptr.lock();
if (!ptr)
return;
ptr->invokeOnTimer();
if (ptr)
ptr->invokeOnTimer();
}
LedgerAcquire::LedgerAcquire(const uint256& hash) : PeerSet(hash, LEDGER_ACQUIRE_TIMEOUT),
@@ -109,7 +108,7 @@ void LedgerAcquire::onTimer()
boost::weak_ptr<PeerSet> LedgerAcquire::pmDowncast()
{
return boost::shared_polymorphic_downcast<PeerSet, LedgerAcquire>(shared_from_this());
return boost::shared_polymorphic_downcast<PeerSet>(shared_from_this());
}
void LedgerAcquire::done()

View File

@@ -78,6 +78,7 @@ protected:
public:
LedgerAcquire(const uint256& hash);
virtual ~LedgerAcquire() { ; }
bool isBase() const { return mHaveBase; }
bool isAcctStComplete() const { return mHaveState; }

View File

@@ -25,24 +25,26 @@ typedef std::pair<const uint256, LCTransaction::pointer> u256_lct_pair;
TransactionAcquire::TransactionAcquire(const uint256& hash) : PeerSet(hash, TX_ACQUIRE_TIMEOUT), mHaveRoot(false)
{
mMap = boost::make_shared<SHAMap>();
mMap->setSynching();
mMap = boost::make_shared<SHAMap>(hash);
}
void TransactionAcquire::done()
{
if (mFailed)
{
Log(lsWARNING) << "Failed to acqiure TXs " << mHash;
Log(lsWARNING) << "Failed to acquire TXs " << mHash;
theApp->getOPs().mapComplete(mHash, SHAMap::pointer());
}
else
{
mMap->setImmutable();
theApp->getOPs().mapComplete(mHash, mMap);
}
}
boost::weak_ptr<PeerSet> TransactionAcquire::pmDowncast()
{
return boost::shared_polymorphic_downcast<PeerSet, TransactionAcquire>(shared_from_this());
return boost::shared_polymorphic_downcast<PeerSet>(shared_from_this());
}
void TransactionAcquire::trigger(Peer::ref peer, bool timer)
@@ -109,7 +111,8 @@ bool TransactionAcquire::takeNodes(const std::list<SHAMapNode>& nodeIDs,
}
if (!mMap->addRootNode(getHash(), *nodeDatait, snfWIRE))
return false;
else mHaveRoot = true;
else
mHaveRoot = true;
}
else if (!mMap->addKnownNode(*nodeIDit, *nodeDatait, &sf))
return false;
@@ -174,37 +177,41 @@ void LCTransaction::unVote(const uint160& peer)
}
}
bool LCTransaction::updatePosition(int percentTime, bool proposing)
bool LCTransaction::updateVote(int percentTime, bool proposing)
{
if (mOurPosition && (mNays == 0))
if (mOurVote && (mNays == 0))
return false;
if (!mOurPosition && (mYays == 0))
if (!mOurVote && (mYays == 0))
return false;
bool newPosition;
int weight;
if (proposing) // give ourselves full weight
{
// This is basically the percentage of nodes voting 'yes' (including us)
int weight = (mYays * 100 + (mOurPosition ? 100 : 0)) / (mNays + mYays + 1);
weight = (mYays * 100 + (mOurVote ? 100 : 0)) / (mNays + mYays + 1);
// To prevent avalanche stalls, we increase the needed weight slightly over time
if (percentTime < AV_MID_CONSENSUS_TIME) newPosition = weight > AV_INIT_CONSENSUS_PCT;
else if (percentTime < AV_LATE_CONSENSUS_TIME) newPosition = weight > AV_MID_CONSENSUS_PCT;
else newPosition = weight > AV_LATE_CONSENSUS_PCT;
}
else // don't let us outweight a proposing node, just recognize consensus
else // don't let us outweigh a proposing node, just recognize consensus
{
weight = -1;
newPosition = mYays > mNays;
}
if (newPosition == mOurPosition)
if (newPosition == mOurVote)
{
#ifdef LC_DEBUG
Log(lsTRACE) << "No change (" << (mOurPosition ? "YES" : "NO") << ") : weight "
Log(lsTRACE) << "No change (" << (mOurVote ? "YES" : "NO") << ") : weight "
<< weight << ", percent " << percentTime;
#endif
return false;
}
mOurPosition = newPosition;
Log(lsTRACE) << "We now vote " << (mOurPosition ? "YES" : "NO") << " on " << mTransactionID;
mOurVote = newPosition;
Log(lsTRACE) << "We now vote " << (mOurVote ? "YES" : "NO") << " on " << mTransactionID;
return true;
}
@@ -333,6 +340,7 @@ void LedgerConsensus::handleLCL(const uint256& lclHash)
mPeerPositions.clear();
mDisputes.clear();
mDeadNodes.clear();
playbackProposals();
return;
}
@@ -357,9 +365,9 @@ void LedgerConsensus::takeInitialPosition(Ledger& initialLedger)
{
uint256 set = it.second->getCurrentHash();
if (found.insert(set).second)
{
boost::unordered_map<uint256, SHAMap::pointer>::iterator iit = mComplete.find(set);
if (iit != mComplete.end())
{ // OPTIMIZEME: Don't process the same set more than once
boost::unordered_map<uint256, SHAMap::pointer>::iterator iit = mAcquired.find(set);
if (iit != mAcquired.end())
createDisputes(initialSet, iit->second);
}
}
@@ -374,7 +382,7 @@ void LedgerConsensus::takeInitialPosition(Ledger& initialLedger)
propose();
}
void LedgerConsensus::createDisputes(const SHAMap::pointer& m1, const SHAMap::pointer& m2)
void LedgerConsensus::createDisputes(SHAMap::ref m1, SHAMap::ref m2)
{
SHAMap::SHAMapDiff differences;
m1->compare(m2, differences, 16384);
@@ -394,33 +402,36 @@ void LedgerConsensus::createDisputes(const SHAMap::pointer& m1, const SHAMap::po
}
}
void LedgerConsensus::mapComplete(const uint256& hash, const SHAMap::pointer& map, bool acquired)
void LedgerConsensus::mapComplete(const uint256& hash, SHAMap::ref map, bool acquired)
{
if (acquired)
Log(lsINFO) << "We have acquired TXS " << hash;
mAcquiring.erase(hash);
if (!map)
{ // this is an invalid/corrupt map
mComplete[hash] = map;
mAcquired[hash] = map;
mAcquiring.erase(hash);
Log(lsWARNING) << "A trusted node directed us to acquire an invalid TXN map";
return;
}
assert(hash == map->getHash());
if (mComplete.find(hash) != mComplete.end())
if (mAcquired.find(hash) != mAcquired.end())
return; // we already have this map
if (mOurPosition && (map->getHash() != mOurPosition->getCurrentHash()))
if (mOurPosition && (!mOurPosition->isBowOut()) && (hash != mOurPosition->getCurrentHash()))
{ // this could create disputed transactions
boost::unordered_map<uint256, SHAMap::pointer>::iterator it2 = mComplete.find(mOurPosition->getCurrentHash());
if (it2 != mComplete.end())
boost::unordered_map<uint256, SHAMap::pointer>::iterator it2 = mAcquired.find(mOurPosition->getCurrentHash());
if (it2 != mAcquired.end())
{
assert((it2->first == mOurPosition->getCurrentHash()) && it2->second);
createDisputes(it2->second, map);
}
else assert(false); // We don't have our own position?!
else
assert(false); // We don't have our own position?!
}
mComplete[map->getHash()] = map;
mAcquired[hash] = map;
mAcquiring.erase(hash);
// Adjust tracking for each peer that takes this position
std::vector<uint160> peers;
@@ -446,7 +457,7 @@ void LedgerConsensus::sendHaveTxSet(const uint256& hash, bool direct)
theApp->getConnectionPool().relayMessage(NULL, packet);
}
void LedgerConsensus::adjustCount(const SHAMap::pointer& map, const std::vector<uint160>& peers)
void LedgerConsensus::adjustCount(SHAMap::ref map, const std::vector<uint160>& peers)
{ // Adjust the counts on all disputed transactions based on the set of peers taking this position
BOOST_FOREACH(u256_lct_pair& it, mDisputes)
{
@@ -594,14 +605,15 @@ void LedgerConsensus::updateOurPositions()
BOOST_FOREACH(u256_lct_pair& it, mDisputes)
{
if (it.second->updatePosition(mClosePercent, mProposing))
if (it.second->updateVote(mClosePercent, mProposing))
{
if (!changes)
{
ourPosition = mComplete[mOurPosition->getCurrentHash()]->snapShot(true);
ourPosition = mAcquired[mOurPosition->getCurrentHash()]->snapShot(true);
assert(ourPosition);
changes = true;
}
if (it.second->getOurPosition()) // now a yes
if (it.second->getOurVote()) // now a yes
{
ourPosition->addItem(SHAMapItem(it.first, it.second->peekTransaction()), true, false);
// addedTx.push_back(it.first);
@@ -662,41 +674,53 @@ void LedgerConsensus::updateOurPositions()
((closeTime != (roundCloseTime(mOurPosition->getCloseTime()))) ||
(mOurPosition->isStale(ourCutoff))))
{ // close time changed or our position is stale
ourPosition = mComplete[mOurPosition->getCurrentHash()]->snapShot(true);
ourPosition = mAcquired[mOurPosition->getCurrentHash()]->snapShot(true);
assert(ourPosition);
changes = true;
}
if (changes)
{
uint256 newHash = ourPosition->getHash();
mOurPosition->changePosition(newHash, closeTime);
if (mProposing)
propose();
mapComplete(newHash, ourPosition, false);
Log(lsINFO) << "Position change: CTime " << closeTime << ", tx " << newHash;
if (mOurPosition->changePosition(newHash, closeTime))
{
if (mProposing)
propose();
mapComplete(newHash, ourPosition, false);
}
}
}
bool LedgerConsensus::haveConsensus()
{
{ // FIXME: Should check for a supermajority on each disputed transaction
// counting unacquired TX sets as disagreeing
int agree = 0, disagree = 0;
uint256 ourPosition = mOurPosition->getCurrentHash();
BOOST_FOREACH(u160_prop_pair& it, mPeerPositions)
{
if (it.second->getCurrentHash() == ourPosition)
++agree;
else
++disagree;
if (!it.second->isBowOut())
{
if (it.second->getCurrentHash() == ourPosition)
++agree;
else
++disagree;
}
}
int currentValidations = theApp->getValidations().getCurrentValidationCount(mPreviousLedger->getCloseTimeNC());
int currentValidations = theApp->getValidations().getNodesAfter(mPrevLedgerHash);
#ifdef LC_DEBUG
Log(lsINFO) << "Checking for TX consensus: agree=" << agree << ", disagree=" << disagree;
#endif
return ContinuousLedgerTiming::haveConsensus(mPreviousProposers, agree + disagree, agree, currentValidations,
mPreviousMSeconds, mCurrentMSeconds);
}
SHAMap::pointer LedgerConsensus::getTransactionTree(const uint256& hash, bool doAcquire)
{
boost::unordered_map<uint256, SHAMap::pointer>::iterator it = mComplete.find(hash);
if (it == mComplete.end())
boost::unordered_map<uint256, SHAMap::pointer>::iterator it = mAcquired.find(hash);
if (it == mAcquired.end())
{ // we have not completed acquiring this ledger
if (mState == lcsPRE_CLOSE)
@@ -780,10 +804,11 @@ void LedgerConsensus::addDisputedTransaction(const uint256& txID, const std::vec
bool ourPosition = false;
if (mOurPosition)
{
boost::unordered_map<uint256, SHAMap::pointer>::iterator mit = mComplete.find(mOurPosition->getCurrentHash());
if (mit != mComplete.end())
boost::unordered_map<uint256, SHAMap::pointer>::iterator mit = mAcquired.find(mOurPosition->getCurrentHash());
if (mit != mAcquired.end())
ourPosition = mit->second->hasItem(txID);
else assert(false); // We don't have our own position?
else
assert(false); // We don't have our own position?
}
LCTransaction::pointer txn = boost::make_shared<LCTransaction>(txID, tx, ourPosition);
@@ -792,8 +817,8 @@ void LedgerConsensus::addDisputedTransaction(const uint256& txID, const std::vec
BOOST_FOREACH(u160_prop_pair& pit, mPeerPositions)
{
boost::unordered_map<uint256, SHAMap::pointer>::const_iterator cit =
mComplete.find(pit.second->getCurrentHash());
if (cit != mComplete.end() && cit->second)
mAcquired.find(pit.second->getCurrentHash());
if (cit != mAcquired.end() && cit->second)
txn->setVote(pit.first, cit->second->hasItem(txID));
}
}
@@ -867,13 +892,15 @@ bool LedgerConsensus::peerGaveNodes(Peer::ref peer, const uint256& setHash,
const std::list<SHAMapNode>& nodeIDs, const std::list< std::vector<unsigned char> >& nodeData)
{
boost::unordered_map<uint256, TransactionAcquire::pointer>::iterator acq = mAcquiring.find(setHash);
if (acq == mAcquiring.end()) return false;
return acq->second->takeNodes(nodeIDs, nodeData, peer);
if (acq == mAcquiring.end())
return false;
TransactionAcquire::pointer set = acq->second; // We must keep the set around during the function
return set->takeNodes(nodeIDs, nodeData, peer);
}
void LedgerConsensus::beginAccept()
{
SHAMap::pointer consensusSet = mComplete[mOurPosition->getCurrentHash()];
SHAMap::pointer consensusSet = mAcquired[mOurPosition->getCurrentHash()];
if (!consensusSet)
{
Log(lsFATAL) << "We don't have a consensus set";
@@ -882,8 +909,7 @@ void LedgerConsensus::beginAccept()
}
theApp->getOPs().newLCL(mPeerPositions.size(), mCurrentMSeconds, mNewLedgerHash);
boost::thread thread(boost::bind(&LedgerConsensus::Saccept, shared_from_this(), consensusSet));
thread.detach();
theApp->getIOService().post(boost::bind(&LedgerConsensus::Saccept, shared_from_this(), consensusSet));
}
void LedgerConsensus::Saccept(boost::shared_ptr<LedgerConsensus> This, SHAMap::pointer txSet)
@@ -954,7 +980,7 @@ void LedgerConsensus::applyTransaction(TransactionEngine& engine, const Serializ
#endif
}
void LedgerConsensus::applyTransactions(const SHAMap::pointer& set, Ledger::ref applyLedger,
void LedgerConsensus::applyTransactions(SHAMap::ref set, Ledger::ref applyLedger,
Ledger::ref checkLedger, CanonicalTXSet& failedTransactions, bool openLgr)
{
TransactionEngineParams parms = openLgr ? tapOPEN_LEDGER : tapNONE;
@@ -1016,7 +1042,7 @@ uint32 LedgerConsensus::roundCloseTime(uint32 closeTime)
return closeTime - (closeTime % mCloseResolution);
}
void LedgerConsensus::accept(const SHAMap::pointer& set)
void LedgerConsensus::accept(SHAMap::ref set)
{
assert(set->getHash() == mOurPosition->getCurrentHash());
@@ -1070,7 +1096,7 @@ void LedgerConsensus::accept(const SHAMap::pointer& set)
TransactionEngine engine(newOL);
BOOST_FOREACH(u256_lct_pair& it, mDisputes)
{
if (!it.second->getOurPosition())
if (!it.second->getOurVote())
{ // we voted NO
try
{

View File

@@ -37,11 +37,11 @@ protected:
public:
TransactionAcquire(const uint256& hash);
virtual ~TransactionAcquire() { ; }
SHAMap::pointer getMap() { return mMap; }
bool takeNodes(const std::list<SHAMapNode>& IDs, const std::list< std::vector<unsigned char> >& data,
Peer::ref);
bool takeNodes(const std::list<SHAMapNode>& IDs, const std::list< std::vector<unsigned char> >& data, Peer::ref);
};
class LCTransaction
@@ -49,24 +49,24 @@ class LCTransaction
protected:
uint256 mTransactionID;
int mYays, mNays;
bool mOurPosition;
bool mOurVote;
Serializer transaction;
boost::unordered_map<uint160, bool> mVotes;
public:
typedef boost::shared_ptr<LCTransaction> pointer;
LCTransaction(const uint256 &txID, const std::vector<unsigned char>& tx, bool ourPosition) :
mTransactionID(txID), mYays(0), mNays(0), mOurPosition(ourPosition), transaction(tx) { ; }
LCTransaction(const uint256 &txID, const std::vector<unsigned char>& tx, bool ourVote) :
mTransactionID(txID), mYays(0), mNays(0), mOurVote(ourVote), transaction(tx) { ; }
const uint256& getTransactionID() const { return mTransactionID; }
bool getOurPosition() const { return mOurPosition; }
bool getOurVote() const { return mOurVote; }
Serializer& peekTransaction() { return transaction; }
void setVote(const uint160& peer, bool votesYes);
void unVote(const uint160& peer);
bool updatePosition(int percentTime, bool proposing);
bool updateVote(int percentTime, bool proposing);
};
enum LCState
@@ -100,7 +100,7 @@ protected:
boost::unordered_map<uint160, LedgerProposal::pointer> mPeerPositions;
// Transaction Sets, indexed by hash of transaction tree
boost::unordered_map<uint256, SHAMap::pointer> mComplete;
boost::unordered_map<uint256, SHAMap::pointer> mAcquired;
boost::unordered_map<uint256, TransactionAcquire::pointer> mAcquiring;
// Peer sets
@@ -120,21 +120,21 @@ protected:
// final accept logic
static void Saccept(boost::shared_ptr<LedgerConsensus> This, SHAMap::pointer txSet);
void accept(const SHAMap::pointer& txSet);
void accept(SHAMap::ref txSet);
void weHave(const uint256& id, Peer::ref avoidPeer);
void startAcquiring(const TransactionAcquire::pointer&);
SHAMap::pointer find(const uint256& hash);
void createDisputes(const SHAMap::pointer&, const SHAMap::pointer&);
void createDisputes(SHAMap::ref, SHAMap::ref);
void addDisputedTransaction(const uint256&, const std::vector<unsigned char>& transaction);
void adjustCount(const SHAMap::pointer& map, const std::vector<uint160>& peers);
void adjustCount(SHAMap::ref map, const std::vector<uint160>& peers);
void propose();
void addPosition(LedgerProposal&, bool ours);
void removePosition(LedgerProposal&, bool ours);
void sendHaveTxSet(const uint256& set, bool direct);
void applyTransactions(const SHAMap::pointer& transactionSet, Ledger::ref targetLedger,
void applyTransactions(SHAMap::ref transactionSet, Ledger::ref targetLedger,
Ledger::ref checkLedger, CanonicalTXSet& failedTransactions, bool openLgr);
void applyTransaction(TransactionEngine& engine, const SerializedTransaction::pointer& txn,
Ledger::ref targetLedger, CanonicalTXSet& failedTransactions, bool openLgr);
@@ -162,7 +162,7 @@ public:
SHAMap::pointer getTransactionTree(const uint256& hash, bool doAcquire);
TransactionAcquire::pointer getAcquiring(const uint256& hash);
void mapComplete(const uint256& hash, const SHAMap::pointer& map, bool acquired);
void mapComplete(const uint256& hash, SHAMap::ref map, bool acquired);
void checkLCL();
void handleLCL(const uint256& lclHash);

View File

@@ -257,6 +257,8 @@ Json::Value LedgerEntrySet::getJson(int) const
}
ret["nodes" ] = nodes;
ret["metaData"] = mSet.getJson(0);
return ret;
}
@@ -292,9 +294,13 @@ SLE::pointer LedgerEntrySet::getForMod(const uint256& node, Ledger::ref ledger,
bool LedgerEntrySet::threadTx(TransactionMetaNode& metaNode, const NewcoinAddress& threadTo, Ledger::ref ledger,
boost::unordered_map<uint256, SLE::pointer>& newMods)
{
Log(lsTRACE) << "Thread to " << threadTo.getAccountID();
SLE::pointer sle = getForMod(Ledger::getAccountRootIndex(threadTo.getAccountID()), ledger, newMods);
if (!sle)
{
assert(false);
return false;
}
return threadTx(metaNode, sle, ledger, newMods);
}
@@ -325,7 +331,7 @@ bool LedgerEntrySet::threadOwners(TransactionMetaNode& metaNode, SLE::ref node,
return false;
}
void LedgerEntrySet::calcRawMeta(Serializer& s, Ledger::ref origLedger)
void LedgerEntrySet::calcRawMeta(Serializer& s)
{ // calculate the raw meta data and return it. This must be called before the set is committed
// Entries modified only as a result of building the transaction metadata
@@ -350,21 +356,25 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, Ledger::ref origLedger)
nType = TMNCreatedNode;
break;
default:
// ignore these
default: // ignore these
break;
}
if (nType == TMNEndOfMetadata)
continue;
SLE::pointer origNode = origLedger->getSLE(it->first);
SLE::pointer origNode = mLedger->getSLE(it->first);
if (origNode && (origNode->getType() == ltDIR_NODE)) // No metadata for dir nodes
continue;
SLE::pointer curNode = it->second.mEntry;
TransactionMetaNode &metaNode = mSet.getAffectedNode(it->first, nType);
if (nType == TMNDeletedNode)
{
threadOwners(metaNode, origNode, origLedger, newMod);
assert(origNode);
threadOwners(metaNode, origNode, mLedger, newMod);
if (origNode->getIFieldPresent(sfAmount))
{ // node has an amount, covers ripple state nodes
@@ -396,16 +406,20 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, Ledger::ref origLedger)
}
if (nType == TMNCreatedNode) // if created, thread to owner(s)
threadOwners(metaNode, curNode, origLedger, newMod);
{
assert(!origNode);
threadOwners(metaNode, curNode, mLedger, newMod);
}
if ((nType == TMNCreatedNode) || (nType == TMNModifiedNode))
{
if (curNode->isThreadedType()) // always thread to self
threadTx(metaNode, curNode, origLedger, newMod);
threadTx(metaNode, curNode, mLedger, newMod);
}
if (nType == TMNModifiedNode)
{
assert(origNode);
if (origNode->getIFieldPresent(sfAmount))
{ // node has an amount, covers account root nodes and ripple nodes
STAmount amount = origNode->getIValueFieldAmount(sfAmount);
@@ -429,7 +443,11 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, Ledger::ref origLedger)
// add any new modified nodes to the modification set
for (boost::unordered_map<uint256, SLE::pointer>::iterator it = newMod.begin(), end = newMod.end();
it != end; ++it)
entryCache(it->second);
entryModify(it->second);
#ifdef DEBUG
Log(lsINFO) << "Metadata:" << mSet.getJson(0);
#endif
mSet.addRaw(s);
}

View File

@@ -120,7 +120,7 @@ public:
STAmount accountFunds(const uint160& uAccountID, const STAmount& saDefault);
Json::Value getJson(int) const;
void calcRawMeta(Serializer&, Ledger::ref originalLedger);
void calcRawMeta(Serializer&);
// iterator functions
bool isEmpty() const { return mEntries.empty(); }

View File

@@ -80,8 +80,7 @@ Ledger::pointer LedgerMaster::closeLedger()
return closingLedger;
}
TER LedgerMaster::doTransaction(const SerializedTransaction& txn, uint32 targetLedger,
TransactionEngineParams params)
TER LedgerMaster::doTransaction(const SerializedTransaction& txn, TransactionEngineParams params)
{
TER result = mEngine.applyTransaction(txn, params);
theApp->getOPs().pubTransaction(mEngine.getLedger(), txn, result);

View File

@@ -45,8 +45,7 @@ public:
void runStandAlone() { mFinalizedLedger = mCurrentLedger; }
TER doTransaction(const SerializedTransaction& txn, uint32 targetLedger,
TransactionEngineParams params);
TER doTransaction(const SerializedTransaction& txn, TransactionEngineParams params);
void pushLedger(Ledger::ref newLedger);
void pushLedger(Ledger::ref newLCL, Ledger::ref newOL);

View File

@@ -54,17 +54,20 @@ bool LedgerProposal::checkSign(const std::string& signature, const uint256& sign
return mPublicKey.verifyNodePublic(signingHash, signature);
}
void LedgerProposal::changePosition(const uint256& newPosition, uint32 closeTime)
bool LedgerProposal::changePosition(const uint256& newPosition, uint32 closeTime)
{
if (mProposeSeq == seqLeave)
return false;
mCurrentHash = newPosition;
mCloseTime = closeTime;
mTime = boost::posix_time::second_clock::universal_time();
++mProposeSeq;
return true;
}
void LedgerProposal::bowOut()
{
mCurrentHash = uint256();
mTime = boost::posix_time::second_clock::universal_time();
mProposeSeq = seqLeave;
}

View File

@@ -59,11 +59,12 @@ public:
void setSignature(const std::string& signature) { mSignature = signature; }
bool hasSignature() { return !mSignature.empty(); }
bool isPrevLedger(const uint256& pl) { return mPreviousLedger == pl; }
bool isBowOut() { return mProposeSeq == seqLeave; }
const boost::posix_time::ptime getCreateTime() { return mTime; }
bool isStale(boost::posix_time::ptime cutoff) { return mTime <= cutoff; }
void changePosition(const uint256& newPosition, uint32 newCloseTime);
bool changePosition(const uint256& newPosition, uint32 newCloseTime);
void bowOut();
Json::Value getJson() const;
};

View File

@@ -28,6 +28,10 @@
// How often we check state or change positions (in milliseconds)
# define LEDGER_GRANULARITY 1000
// The percentage of active trusted validators that must be able to
// keep up with the network or we consider the network overloaded
# define LEDGER_NET_RATIO 70
// How long we consider a proposal fresh
# define PROPOSE_FRESHNESS 20

View File

@@ -6,6 +6,9 @@
#include <boost/thread/recursive_mutex.hpp>
#include <boost/filesystem.hpp>
// Ensure that we don't get value.h without writer.h
#include "../json/json.h"
enum LogSeverity
{
lsTRACE = 0,

View File

@@ -93,7 +93,7 @@ Transaction::pointer NetworkOPs::submitTransaction(const Transaction::pointer& t
return tpTransNew;
}
Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans, uint32 tgtLedger, Peer* source)
Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans, Peer* source)
{
Transaction::pointer dbtx = theApp->getMasterTransaction().fetch(trans->getID(), true);
if (dbtx) return dbtx;
@@ -105,7 +105,7 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
return trans;
}
TER r = mLedgerMaster->doTransaction(*trans->getSTransaction(), tgtLedger, tapOPEN_LEDGER);
TER r = mLedgerMaster->doTransaction(*trans->getSTransaction(), tapOPEN_LEDGER);
if (r == tefFAILURE) throw Fault(IO_ERROR);
if (r == terPRE_SEQ)
@@ -140,7 +140,6 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
tx.set_rawtransaction(&s.getData().front(), s.getLength());
tx.set_status(newcoin::tsCURRENT);
tx.set_receivetimestamp(getNetworkTimeNC());
tx.set_ledgerindexpossible(trans->getLedger());
PackedMessage::pointer packet = boost::make_shared<PackedMessage>(tx, newcoin::mtTRANSACTION);
theApp->getConnectionPool().relayMessage(source, packet);
@@ -157,7 +156,6 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
tx.set_rawtransaction(&s.getData().front(), s.getLength());
tx.set_status(newcoin::tsCURRENT);
tx.set_receivetimestamp(getNetworkTimeNC());
tx.set_ledgerindexpossible(tgtLedger);
PackedMessage::pointer packet = boost::make_shared<PackedMessage>(tx, newcoin::mtTRANSACTION);
theApp->getConnectionPool().relayMessage(source, packet);
}
@@ -213,7 +211,11 @@ SLE::pointer NetworkOPs::getGenerator(const uint256& uLedger, const uint160& uGe
{
LedgerStateParms qry = lepNONE;
return mLedgerMaster->getLedgerByHash(uLedger)->getGenerator(qry, uGeneratorID);
Ledger::pointer ledger = mLedgerMaster->getLedgerByHash(uLedger);
if (!ledger)
return SLE::pointer();
else
return ledger->getGenerator(qry, uGeneratorID);
}
//
@@ -714,7 +716,7 @@ bool NetworkOPs::hasTXSet(const boost::shared_ptr<Peer>& peer, const uint256& se
return mConsensus->peerHasSet(peer, set, status);
}
void NetworkOPs::mapComplete(const uint256& hash, const SHAMap::pointer& map)
void NetworkOPs::mapComplete(const uint256& hash, SHAMap::ref map)
{
if (mConsensus)
mConsensus->mapComplete(hash, map, true);

View File

@@ -116,8 +116,7 @@ public:
//
Transaction::pointer submitTransaction(const Transaction::pointer& tpTrans);
Transaction::pointer processTransaction(Transaction::pointer transaction, uint32 targetLedger = 0,
Peer* source = NULL);
Transaction::pointer processTransaction(Transaction::pointer transaction, Peer* source = NULL);
Transaction::pointer findTransactionByID(const uint256& transactionID);
int findTransactionsBySource(const uint256& uLedger, std::list<Transaction::pointer>&, const NewcoinAddress& sourceAccount,
uint32 minSeq, uint32 maxSeq);
@@ -172,7 +171,7 @@ public:
bool recvValidation(const SerializedValidation::pointer& val);
SHAMap::pointer getTXMap(const uint256& hash);
bool hasTXSet(const boost::shared_ptr<Peer>& peer, const uint256& set, newcoin::TxSetStatus status);
void mapComplete(const uint256& hash, const SHAMap::pointer& map);
void mapComplete(const uint256& hash, SHAMap::ref map);
// network state machine
void checkState(const boost::system::error_code& result);

View File

@@ -12,6 +12,8 @@ public:
virtual bool work(Interpreter* interpreter)=0;
virtual int getFee();
virtual ~Operation() { ; }
};
// this is just an Int in the code

View File

@@ -702,13 +702,7 @@ void Peer::recvTransaction(newcoin::TMTransaction& packet)
}
#endif
uint32 targetLedger = 0;
if (packet.has_ledgerindexfinal())
targetLedger = packet.ledgerindexfinal();
else if (packet.has_ledgerindexpossible())
targetLedger = packet.ledgerindexpossible();
tx = theApp->getOPs().processTransaction(tx, targetLedger, this);
tx = theApp->getOPs().processTransaction(tx, this);
if(tx->getStatus() != INCLUDED)
{ // transaction wasn't accepted into ledger

View File

@@ -39,14 +39,14 @@ std::size_t hash_value(const uint160& u)
}
SHAMap::SHAMap(uint32 seq) : mSeq(seq), mState(Modifying)
SHAMap::SHAMap(uint32 seq) : mSeq(seq), mState(smsModifying)
{
root = boost::make_shared<SHAMapTreeNode>(mSeq, SHAMapNode(0, uint256()));
root->makeInner();
mTNByID[*root] = root;
}
SHAMap::SHAMap(const uint256& hash) : mSeq(0), mState(Synching)
SHAMap::SHAMap(const uint256& hash) : mSeq(0), mState(smsSynching)
{ // FIXME: Need to acquire root node
root = boost::make_shared<SHAMapTreeNode>(mSeq, SHAMapNode(0, uint256()));
root->makeInner();
@@ -62,7 +62,7 @@ SHAMap::pointer SHAMap::snapShot(bool isMutable)
newMap.mTNByID = mTNByID;
newMap.root = root;
if (!isMutable)
newMap.mState = Immutable;
newMap.mState = smsImmutable;
return ret;
}
@@ -105,7 +105,7 @@ void SHAMap::dirtyUp(std::stack<SHAMapTreeNode::pointer>& stack, const uint256&
{ // walk the tree up from through the inner nodes to the root
// update linking hashes and add nodes to dirty list
assert((mState != Synching) && (mState != Immutable));
assert((mState != smsSynching) && (mState != smsImmutable));
while (!stack.empty())
{
@@ -238,7 +238,7 @@ SHAMapItem::SHAMapItem(const uint256& tag, const Serializer& data)
: mTag(tag), mData(data.peekData())
{ ; }
SHAMapItem::pointer SHAMap::firstBelow(SHAMapTreeNode* node)
SHAMapTreeNode* SHAMap::firstBelow(SHAMapTreeNode* node)
{
// Return the first item below this node
#ifdef ST_DEBUG
@@ -246,7 +246,7 @@ SHAMapItem::pointer SHAMap::firstBelow(SHAMapTreeNode* node)
#endif
do
{ // Walk down the tree
if (node->hasItem()) return node->peekItem();
if (node->hasItem()) return node;
bool foundNode = false;
for (int i = 0; i < 16; ++i)
@@ -261,11 +261,12 @@ SHAMapItem::pointer SHAMap::firstBelow(SHAMapTreeNode* node)
foundNode = true;
break;
}
if (!foundNode) return SHAMapItem::pointer();
if (!foundNode)
return NULL;
} while (true);
}
SHAMapItem::pointer SHAMap::lastBelow(SHAMapTreeNode* node)
SHAMapTreeNode* SHAMap::lastBelow(SHAMapTreeNode* node)
{
#ifdef DEBUG
std::cerr << "lastBelow(" << *node << ")" << std::endl;
@@ -273,7 +274,8 @@ SHAMapItem::pointer SHAMap::lastBelow(SHAMapTreeNode* node)
do
{ // Walk down the tree
if (node->hasItem()) return node->peekItem();
if (node->hasItem())
return node;
bool foundNode = false;
for (int i = 15; i >= 0; ++i)
@@ -283,7 +285,8 @@ SHAMapItem::pointer SHAMap::lastBelow(SHAMapTreeNode* node)
foundNode = true;
break;
}
if (!foundNode) return SHAMapItem::pointer();
if (!foundNode)
return NULL;
} while (true);
}
@@ -345,16 +348,39 @@ void SHAMap::eraseChildren(SHAMapTreeNode::pointer node)
SHAMapItem::pointer SHAMap::peekFirstItem()
{
boost::recursive_mutex::scoped_lock sl(mLock);
return firstBelow(root.get());
SHAMapTreeNode *node = firstBelow(root.get());
if (!node)
return SHAMapItem::pointer();
return node->peekItem();
}
SHAMapItem::pointer SHAMap::peekFirstItem(SHAMapTreeNode::TNType& type)
{
boost::recursive_mutex::scoped_lock sl(mLock);
SHAMapTreeNode *node = firstBelow(root.get());
if (!node)
return SHAMapItem::pointer();
type = node->getType();
return node->peekItem();
}
SHAMapItem::pointer SHAMap::peekLastItem()
{
boost::recursive_mutex::scoped_lock sl(mLock);
return lastBelow(root.get());
SHAMapTreeNode *node = lastBelow(root.get());
if (!node)
return SHAMapItem::pointer();
return node->peekItem();
}
SHAMapItem::pointer SHAMap::peekNextItem(const uint256& id)
{
SHAMapTreeNode::TNType type;
return peekNextItem(id, type);
}
SHAMapItem::pointer SHAMap::peekNextItem(const uint256& id, SHAMapTreeNode::TNType& type)
{ // Get a pointer to the next item in the tree after a given item - item must be in tree
boost::recursive_mutex::scoped_lock sl(mLock);
@@ -367,17 +393,24 @@ SHAMapItem::pointer SHAMap::peekNextItem(const uint256& id)
if (node->isLeaf())
{
if (node->peekItem()->getTag() > id)
return node->peekItem();
}
else for (int i = node->selectBranch(id) + 1; i < 16; ++i)
if (!node->isEmptyBranch(i))
{
node = getNode(node->getChildNodeID(i), node->getChildHash(i), false);
SHAMapItem::pointer item = firstBelow(node.get());
if (!item)
throw std::runtime_error("missing node");
return item;
type = node->getType();
return node->peekItem();
}
}
else
for (int i = node->selectBranch(id) + 1; i < 16; ++i)
if (!node->isEmptyBranch(i))
{
SHAMapTreeNode *firstNode = getNodePointer(node->getChildNodeID(i), node->getChildHash(i));
if (!firstNode)
throw std::runtime_error("missing node");
firstNode = firstBelow(firstNode);
if (!firstNode)
throw std::runtime_error("missing node");
type = firstNode->getType();
return firstNode->peekItem();
}
}
// must be last item
return SHAMapItem::pointer();
@@ -402,10 +435,10 @@ SHAMapItem::pointer SHAMap::peekPrevItem(const uint256& id)
if (!node->isEmptyBranch(i))
{
node = getNode(node->getChildNodeID(i), node->getChildHash(i), false);
SHAMapItem::pointer item = firstBelow(node.get());
SHAMapTreeNode* item = firstBelow(node.get());
if (!item)
throw std::runtime_error("missing node");
return item;
return item->peekItem();
}
}
// must be last item
@@ -421,6 +454,16 @@ SHAMapItem::pointer SHAMap::peekItem(const uint256& id)
return leaf->peekItem();
}
SHAMapItem::pointer SHAMap::peekItem(const uint256& id, SHAMapTreeNode::TNType& type)
{
boost::recursive_mutex::scoped_lock sl(mLock);
SHAMapTreeNode* leaf = walkToPointer(id);
if (!leaf)
return SHAMapItem::pointer();
type = leaf->getType();
return leaf->peekItem();
}
bool SHAMap::hasItem(const uint256& id)
{ // does the tree have an item with this ID
boost::recursive_mutex::scoped_lock sl(mLock);
@@ -432,7 +475,7 @@ bool SHAMap::hasItem(const uint256& id)
bool SHAMap::delItem(const uint256& id)
{ // delete the item with this ID
boost::recursive_mutex::scoped_lock sl(mLock);
assert(mState != Immutable);
assert(mState != smsImmutable);
std::stack<SHAMapTreeNode::pointer> stack = getStack(id, true, false);
if (stack.empty())
@@ -509,7 +552,7 @@ bool SHAMap::addGiveItem(const SHAMapItem::pointer& item, bool isTransaction, bo
(hasMeta ? SHAMapTreeNode::tnTRANSACTION_MD : SHAMapTreeNode::tnTRANSACTION_NM);
boost::recursive_mutex::scoped_lock sl(mLock);
assert(mState != Immutable);
assert(mState != smsImmutable);
std::stack<SHAMapTreeNode::pointer> stack = getStack(tag, true, false);
if (stack.empty())
@@ -601,7 +644,7 @@ bool SHAMap::updateGiveItem(const SHAMapItem::pointer& item, bool isTransaction,
uint256 tag = item->getTag();
boost::recursive_mutex::scoped_lock sl(mLock);
assert(mState != Immutable);
assert(mState != smsImmutable);
std::stack<SHAMapTreeNode::pointer> stack = getStack(tag, true, false);
if (stack.empty()) throw std::runtime_error("missing node");

View File

@@ -24,7 +24,8 @@ class SHAMap;
class SHAMapNode
{ // Identifies a node in a SHA256 hash
public:
typedef boost::shared_ptr<SHAMapNode> pointer;
typedef boost::shared_ptr<SHAMapNode> pointer;
typedef const boost::shared_ptr<SHAMapNode>& ref;
private:
static uint256 smMasks[65]; // AND with hash to get node id
@@ -216,11 +217,11 @@ public:
enum SHAMapState
{
Modifying = 0, // Objects can be added and removed (like an open ledger)
Immutable = 1, // Map cannot be changed (like a closed ledger)
Synching = 2, // Map's hash is locked in, valid nodes can be added (like a peer's closing ledger)
Floating = 3, // Map is free to change hash (like a synching open ledger)
Invalid = 4, // Map is known not to be valid (usually synching a corrupt ledger)
smsModifying = 0, // Objects can be added and removed (like an open ledger)
smsImmutable = 1, // Map cannot be changed (like a closed ledger)
smsSynching = 2, // Map's hash is locked in, valid nodes can be added (like a peer's closing ledger)
smsFloating = 3, // Map is free to change hash (like a synching open ledger)
smsInvalid = 4, // Map is known not to be valid (usually synching a corrupt ledger)
};
class SHAMapSyncFilter
@@ -228,9 +229,11 @@ class SHAMapSyncFilter
public:
SHAMapSyncFilter() { ; }
virtual ~SHAMapSyncFilter() { ; }
virtual void gotNode(const SHAMapNode& id, const uint256& nodeHash,
const std::vector<unsigned char>& nodeData, bool isLeaf)
{ ; }
virtual bool haveNode(const SHAMapNode& id, const uint256& nodeHash, std::vector<unsigned char>& nodeData)
{ return false; }
};
@@ -247,6 +250,7 @@ public:
{ ; }
virtual ~SHAMapMissingNode() throw()
{ ; }
const SHAMapNode& getNodeID() const { return mNodeID; }
const uint256& getNodeHash() const { return mNodeHash; }
};
@@ -255,6 +259,8 @@ class SHAMap
{
public:
typedef boost::shared_ptr<SHAMap> pointer;
typedef const boost::shared_ptr<SHAMap>& ref;
typedef std::map<uint256, std::pair<SHAMapItem::pointer, SHAMapItem::pointer> > SHAMapDiff;
private:
@@ -280,9 +286,9 @@ protected:
SHAMapTreeNode::pointer getNode(const SHAMapNode& id);
SHAMapTreeNode::pointer getNode(const SHAMapNode& id, const uint256& hash, bool modify);
SHAMapTreeNode* getNodePointer(const SHAMapNode& id, const uint256& hash);
SHAMapTreeNode* firstBelow(SHAMapTreeNode*);
SHAMapTreeNode* lastBelow(SHAMapTreeNode*);
SHAMapItem::pointer firstBelow(SHAMapTreeNode*);
SHAMapItem::pointer lastBelow(SHAMapTreeNode*);
SHAMapItem::pointer onlyBelow(SHAMapTreeNode*);
void eraseChildren(SHAMapTreeNode::pointer);
@@ -295,6 +301,8 @@ public:
SHAMap(uint32 seq = 0);
SHAMap(const uint256& hash);
~SHAMap() { mState = smsInvalid; }
// Returns a new map that's a snapshot of this one. Force CoW
SHAMap::pointer snapShot(bool isMutable);
@@ -318,11 +326,14 @@ public:
// save a copy if you only need a temporary
SHAMapItem::pointer peekItem(const uint256& id);
SHAMapItem::pointer peekItem(const uint256& id, SHAMapTreeNode::TNType& type);
// traverse functions
SHAMapItem::pointer peekFirstItem();
SHAMapItem::pointer peekFirstItem(SHAMapTreeNode::TNType& type);
SHAMapItem::pointer peekLastItem();
SHAMapItem::pointer peekNextItem(const uint256&);
SHAMapItem::pointer peekNextItem(const uint256&, SHAMapTreeNode::TNType& type);
SHAMapItem::pointer peekPrevItem(const uint256&);
// comparison/sync functions
@@ -337,17 +348,17 @@ public:
SHAMapSyncFilter* filter);
// status functions
void setImmutable(void) { assert(mState != Invalid); mState = Immutable; }
void clearImmutable(void) { mState = Modifying; }
bool isSynching(void) const { return (mState == Floating) || (mState == Synching); }
void setSynching(void) { mState = Synching; }
void setFloating(void) { mState = Floating; }
void clearSynching(void) { mState = Modifying; }
bool isValid(void) { return mState != Invalid; }
void setImmutable() { assert(mState != smsInvalid); mState = smsImmutable; }
void clearImmutable() { mState = smsModifying; }
bool isSynching() const { return (mState == smsFloating) || (mState == smsSynching); }
void setSynching() { mState = smsSynching; }
void setFloating() { mState = smsFloating; }
void clearSynching() { mState = smsModifying; }
bool isValid() { return mState != smsInvalid; }
// caution: otherMap must be accessed only by this function
// return value: true=successfully completed, false=too different
bool compare(const SHAMap::pointer& otherMap, SHAMapDiff& differences, int maxCount);
bool compare(SHAMap::ref otherMap, SHAMapDiff& differences, int maxCount);
void armDirty();
int flushDirty(int maxNodes, HashedObjectType t, uint32 seq);

View File

@@ -91,17 +91,22 @@ bool SHAMap::walkBranch(SHAMapTreeNode* node, SHAMapItem::pointer otherMapItem,
return true;
}
bool SHAMap::compare(const SHAMap::pointer& otherMap, SHAMapDiff& differences, int maxCount)
bool SHAMap::compare(SHAMap::ref otherMap, SHAMapDiff& differences, int maxCount)
{ // compare two hash trees, add up to maxCount differences to the difference table
// return value: true=complete table of differences given, false=too many differences
// throws on corrupt tables or missing nodes
// CAUTION: otherMap is not locked and must be immutable
assert(isValid() && otherMap && otherMap->isValid());
std::stack<SHAMapDiffNode> nodeStack; // track nodes we've pushed
ScopedLock sl(Lock());
if (getHash() == otherMap->getHash()) return true;
nodeStack.push(SHAMapDiffNode(SHAMapNode(), getHash(), otherMap->getHash()));
boost::recursive_mutex::scoped_lock sl(mLock);
if (getHash() == otherMap->getHash())
return true;
nodeStack.push(SHAMapDiffNode(SHAMapNode(), getHash(), otherMap->getHash()));
while (!nodeStack.empty())
{
SHAMapDiffNode dNode(nodeStack.top());
@@ -109,6 +114,11 @@ bool SHAMap::compare(const SHAMap::pointer& otherMap, SHAMapDiff& differences, i
SHAMapTreeNode* ourNode = getNodePointer(dNode.mNodeID, dNode.mOurHash);
SHAMapTreeNode* otherNode = otherMap->getNodePointer(dNode.mNodeID, dNode.mOtherHash);
if (!ourNode || !otherNode)
{
assert(false);
throw SHAMapMissingNode(dNode.mNodeID, uint256());
}
if (ourNode->isLeaf() && otherNode->isLeaf())
{ // two leaves
@@ -118,17 +128,20 @@ bool SHAMap::compare(const SHAMap::pointer& otherMap, SHAMapDiff& differences, i
{
differences.insert(std::make_pair(ourNode->getTag(),
std::make_pair(ourNode->getItem(), otherNode->getItem())));
if (--maxCount <= 0) return false;
if (--maxCount <= 0)
return false;
}
}
else
{
differences.insert(std::make_pair(ourNode->getTag(),
std::make_pair(ourNode->getItem(), SHAMapItem::pointer())));
if (--maxCount <= 0) return false;
if (--maxCount <= 0)
return false;
differences.insert(std::make_pair(otherNode->getTag(),
std::make_pair(SHAMapItem::pointer(), otherNode->getItem())));
if (--maxCount <= 0) return false;
if (--maxCount <= 0)
return false;
}
}
else if (ourNode->isInner() && otherNode->isLeaf())
@@ -164,7 +177,8 @@ bool SHAMap::compare(const SHAMap::pointer& otherMap, SHAMapDiff& differences, i
ourNode->getChildHash(i), otherNode->getChildHash(i)));
}
}
else assert(false);
else
assert(false);
}
return true;

View File

@@ -296,8 +296,9 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
}
else if (prefix == sHP_TransactionNode)
{
uint256 txID; // WRITEME: Need code to extract transaction ID from TX+MD
assert(false);
uint256 txID;
s.get256(txID, s.getLength() - 32);
s.chop(32);
mItem = boost::make_shared<SHAMapItem>(txID, s.peekData());
mType = tnTRANSACTION_MD;
}

View File

@@ -9,6 +9,8 @@ class Data
public:
typedef boost::shared_ptr<Data> pointer;
virtual ~Data(){ ; }
virtual bool isInt32(){ return(false); }
virtual bool isFloat(){ return(false); }
virtual bool isUint160(){ return(false); }

View File

@@ -102,7 +102,7 @@ bool SerializedLedgerEntry::thread(const uint256& txID, uint32 ledgerSeq, uint25
if (oldPrevTxID == txID)
return false;
prevTxID = oldPrevTxID;
prevLedgerID = getIFieldU32(sfLastTxnID);
prevLedgerID = getIFieldU32(sfLastTxnSeq);
assert(prevTxID != txID);
setIFieldH256(sfLastTxnID, txID);
setIFieldU32(sfLastTxnSeq, ledgerSeq);

View File

@@ -6,6 +6,8 @@
#include "../json/writer.h"
#include "Log.h"
std::auto_ptr<SerializedType> STObject::makeDefaultObject(SerializedTypeID id, const char *name)
{
switch(id)
@@ -713,8 +715,7 @@ void STObject::unitTest()
copy.setValueFieldU32(sfTest3, 1);
if (object1.getSerializer() == copy.getSerializer()) throw std::runtime_error("STObject error");
#ifdef DEBUG
Json::StyledStreamWriter ssw;
ssw.write(std::cerr, copy.getJson(0));
Log(lsDEBUG) << copy.getJson(0);
#endif
for (int i = 0; i < 1000; i++)

View File

@@ -106,7 +106,6 @@ enum SOE_Field
sfTakerGets,
sfTakerPays,
sfTarget,
sfTargetLedger,
sfTransferRate,
sfVersion,
sfWalletLocator,

View File

@@ -28,7 +28,7 @@ protected:
TransactionType mType;
STVariableLength mSignature;
STObject mMiddleTxn, mInnerTxn;
TransactionFormat* mFormat;
const TransactionFormat* mFormat;
SerializedTransaction* duplicate() const { return new SerializedTransaction(*this); }

View File

@@ -281,7 +281,6 @@ public:
STAmount getAmount() const { return mTransaction->getITFieldU64(sfAmount); }
STAmount getFee() const { return mTransaction->getTransactionFee(); }
uint32 getFromAccountSeq() const { return mTransaction->getSequence(); }
uint32 getSourceLedger() const { return mTransaction->getITFieldU32(sfTargetLedger); }
uint32 getIdent() const { return mTransaction->getITFieldU32(sfSourceTag); }
std::vector<unsigned char> getSignature() const { return mTransaction->getSignature(); }
uint32 getLedger() const { return mInLedger; }

View File

@@ -15,7 +15,7 @@
void TransactionEngine::txnWrite()
{
// Write back the account states and add the transaction to the ledger
// Write back the account states
for (boost::unordered_map<uint256, LedgerEntrySetEntry>::iterator it = mNodes.begin(), end = mNodes.end();
it != end; ++it)
{
@@ -430,10 +430,10 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
break;
case ttCONTRACT:
terResult= doContractAdd(txn);
terResult = doContractAdd(txn);
break;
case ttCONTRACT_REMOVE:
terResult=doContractRemove(txn);
terResult = doContractRemove(txn);
break;
default:
@@ -458,17 +458,27 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
if (tesSUCCESS == terResult || isTepPartial(terResult))
{
// Transaction succeeded fully or (retries are not allowed and the transaction succeeded partially).
Serializer m;
mNodes.calcRawMeta(m);
txnWrite();
Serializer s;
txn.add(s);
if (!mLedger->addTransaction(txID, s))
assert(false);
if (isSetBit(params, tapOPEN_LEDGER))
{
if (!mLedger->addTransaction(txID, s))
assert(false);
}
else
{
if (!mLedger->addTransaction(txID, s, m))
assert(false);
// Charge whatever fee they specified.
mLedger->destroyCoins(saPaid.getNValue());
// Charge whatever fee they specified.
mLedger->destroyCoins(saPaid.getNValue());
}
}
mTxnAccount = SLE::pointer();

View File

@@ -160,11 +160,6 @@ TransactionMetaNode::TransactionMetaNode(int type, const uint256& node, Serializ
void TransactionMetaNode::addRaw(Serializer& s)
{
if (mEntries.empty())
{ // ack, an empty node
assert(false);
return;
}
s.add8(mType);
s.add256(mNode);
mEntries.sort();

View File

@@ -46,6 +46,7 @@ protected:
public:
TransactionMetaNodeEntry(int type) : mType(type) { ; }
virtual ~TransactionMetaNodeEntry() { ; }
int getType() const { return mType; }
virtual Json::Value getJson(int) const = 0;
@@ -167,6 +168,9 @@ public:
class TransactionMetaSet
{
public:
typedef boost::shared_ptr<TransactionMetaSet> pointer;
protected:
uint256 mTransactionID;
uint32 mLedger;

View File

@@ -116,19 +116,40 @@ int ValidationCollection::getTrustedValidationCount(const uint256& ledger)
return trusted;
}
int ValidationCollection::getCurrentValidationCount(uint32 afterTime)
{
int ValidationCollection::getNodesAfter(const uint256& ledger)
{ // Number of trusted nodes that have moved past this ledger
int count = 0;
boost::mutex::scoped_lock sl(mValidationLock);
for (boost::unordered_map<uint160, SerializedValidation::pointer>::iterator it = mCurrentValidations.begin(),
end = mCurrentValidations.end(); it != end; ++it)
{
if (it->second->isTrusted() && (it->second->getSignTime() > afterTime))
if (it->second->isTrusted() && it->second->isPreviousHash(ledger))
++count;
}
return count;
}
int ValidationCollection::getLoadRatio(bool overLoaded)
{ // how many trusted nodes are able to keep up, higher is better
int goodNodes = overLoaded ? 1 : 0;
int badNodes = overLoaded ? 0 : 1;
{
boost::mutex::scoped_lock sl(mValidationLock);
for (boost::unordered_map<uint160, SerializedValidation::pointer>::iterator it = mCurrentValidations.begin(),
end = mCurrentValidations.end(); it != end; ++it)
{
if (it->second->isTrusted())
{
if (it->second->isFull())
++goodNodes;
else
++badNodes;
}
}
}
return (goodNodes * 100) / (goodNodes + badNodes);
}
boost::unordered_map<uint256, int> ValidationCollection::getCurrentValidations(uint256 currentLedger)
{
uint32 cutoff = theApp->getOPs().getNetworkTimeNC() - LEDGER_VAL_INTERVAL;

View File

@@ -34,7 +34,9 @@ public:
void getValidationCount(const uint256& ledger, bool currentOnly, int& trusted, int& untrusted);
int getTrustedValidationCount(const uint256& ledger);
int getCurrentValidationCount(uint32 afterTime);
int getNodesAfter(const uint256& ledger);
int getLoadRatio(bool overLoaded);
boost::unordered_map<uint256, int> getCurrentValidations(uint256 currentLedger = uint256());

View File

@@ -5,7 +5,7 @@
//
#define SERVER_VERSION_MAJOR 0
#define SERVER_VERSION_MINOR 4
#define SERVER_VERSION_MINOR 5
#define SERVER_VERSION_SUB "-a"
#define SERVER_NAME "NewCoin"
@@ -16,11 +16,11 @@
// Version we prefer to speak:
#define PROTO_VERSION_MAJOR 0
#define PROTO_VERSION_MINOR 6
#define PROTO_VERSION_MINOR 7
// Version we will speak to:
#define MIN_PROTO_MAJOR 0
#define MIN_PROTO_MINOR 6
#define MIN_PROTO_MINOR 7
#define MAKE_VERSION_INT(maj,min) ((maj << 16) | min)
#define GET_VERSION_MAJOR(ver) (ver >> 16)

View File

@@ -27,7 +27,7 @@ private:
protected:
BN_CTX* pctx;
BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; }
CAutoBN_CTX& operator=(BN_CTX* pnew) { pctx = pnew; return *this; }
public:
CAutoBN_CTX()

View File

@@ -69,9 +69,6 @@ message TMTransaction {
required bytes rawTransaction = 1;
required TransactionStatus status = 2;
optional uint64 receiveTimestamp = 3;
optional uint32 ledgerIndexPossible = 4; // the node may not know
optional uint32 ledgerIndexFinal = 5;
optional bytes conflictingTransaction = 6;
}