diff --git a/newcoin.vcxproj b/newcoin.vcxproj
index 1891a5d7a3..6a20b4ec24 100644
--- a/newcoin.vcxproj
+++ b/newcoin.vcxproj
@@ -124,6 +124,7 @@
+
diff --git a/newcoin.vcxproj.filters b/newcoin.vcxproj.filters
index 064de313cd..8b4cedd1e3 100644
--- a/newcoin.vcxproj.filters
+++ b/newcoin.vcxproj.filters
@@ -342,6 +342,9 @@
Source Files
+
+ Source Files
+
diff --git a/src/cpp/ripple/Config.h b/src/cpp/ripple/Config.h
index 2caf47abfa..53d91f6921 100644
--- a/src/cpp/ripple/Config.h
+++ b/src/cpp/ripple/Config.h
@@ -21,7 +21,7 @@
#define CONFIG_FILE_NAME SYSTEM_NAME "d.cfg" // rippled.cfg
-#define DEFAULT_VALIDATORS_SITE "redstem.com"
+#define DEFAULT_VALIDATORS_SITE ""
#define VALIDATORS_FILE_NAME "validators.txt"
const int SYSTEM_PEER_PORT = 6561;
diff --git a/src/cpp/ripple/LedgerAcquire.cpp b/src/cpp/ripple/LedgerAcquire.cpp
index 0d979f61d8..c3387cf5fe 100644
--- a/src/cpp/ripple/LedgerAcquire.cpp
+++ b/src/cpp/ripple/LedgerAcquire.cpp
@@ -396,7 +396,7 @@ bool LedgerAcquire::takeBase(const std::string& data)
}
bool LedgerAcquire::takeTxNode(const std::list& nodeIDs,
- const std::list< std::vector >& data)
+ const std::list< std::vector >& data, SMAddNode& san)
{
if (!mHaveBase) return false;
std::list::const_iterator nodeIDit = nodeIDs.begin();
@@ -406,11 +406,15 @@ bool LedgerAcquire::takeTxNode(const std::list& nodeIDs,
{
if (nodeIDit->isRoot())
{
- if (!mLedger->peekTransactionMap()->addRootNode(mLedger->getTransHash(), *nodeDatait, snfWIRE, &tFilter))
+ if (!san.combine(mLedger->peekTransactionMap()->addRootNode(mLedger->getTransHash(), *nodeDatait,
+ snfWIRE, &tFilter)))
+ return false;
+ }
+ else
+ {
+ if (!san.combine(mLedger->peekTransactionMap()->addKnownNode(*nodeIDit, *nodeDatait, &tFilter)))
return false;
}
- else if (!mLedger->peekTransactionMap()->addKnownNode(*nodeIDit, *nodeDatait, &tFilter))
- return false;
++nodeIDit;
++nodeDatait;
}
@@ -428,7 +432,7 @@ bool LedgerAcquire::takeTxNode(const std::list& nodeIDs,
}
bool LedgerAcquire::takeAsNode(const std::list& nodeIDs,
- const std::list< std::vector >& data)
+ const std::list< std::vector >& data, SMAddNode& san)
{
cLog(lsTRACE) << "got ASdata (" << nodeIDs.size() <<") acquiring ledger " << mHash;
tLog(nodeIDs.size() == 1, lsTRACE) << "got AS node: " << nodeIDs.front();
@@ -446,14 +450,14 @@ bool LedgerAcquire::takeAsNode(const std::list& nodeIDs,
{
if (nodeIDit->isRoot())
{
- if (!mLedger->peekAccountStateMap()->addRootNode(mLedger->getAccountHash(),
- *nodeDatait, snfWIRE, &tFilter))
+ if (!san.combine(mLedger->peekAccountStateMap()->addRootNode(mLedger->getAccountHash(),
+ *nodeDatait, snfWIRE, &tFilter)))
{
cLog(lsWARNING) << "Bad ledger base";
return false;
}
}
- else if (!mLedger->peekAccountStateMap()->addKnownNode(*nodeIDit, *nodeDatait, &tFilter))
+ else if (!san.combine(mLedger->peekAccountStateMap()->addKnownNode(*nodeIDit, *nodeDatait, &tFilter)))
{
cLog(lsWARNING) << "Unable to add AS node";
return false;
@@ -474,24 +478,22 @@ bool LedgerAcquire::takeAsNode(const std::list& nodeIDs,
return true;
}
-bool LedgerAcquire::takeAsRootNode(const std::vector& data)
+bool LedgerAcquire::takeAsRootNode(const std::vector& data, SMAddNode& san)
{
if (!mHaveBase)
return false;
AccountStateSF tFilter(mLedger->getHash(), mLedger->getLedgerSeq());
- if (!mLedger->peekAccountStateMap()->addRootNode(mLedger->getAccountHash(), data, snfWIRE, &tFilter))
- return false;
- return true;
+ return san.combine(
+ mLedger->peekAccountStateMap()->addRootNode(mLedger->getAccountHash(), data, snfWIRE, &tFilter));
}
-bool LedgerAcquire::takeTxRootNode(const std::vector& data)
+bool LedgerAcquire::takeTxRootNode(const std::vector& data, SMAddNode& san)
{
if (!mHaveBase)
return false;
TransactionStateSF tFilter(mLedger->getHash(), mLedger->getLedgerSeq());
- if (!mLedger->peekTransactionMap()->addRootNode(mLedger->getTransHash(), data, snfWIRE, &tFilter))
- return false;
- return true;
+ return san.combine(
+ mLedger->peekTransactionMap()->addRootNode(mLedger->getTransHash(), data, snfWIRE, &tFilter));
}
LedgerAcquire::pointer LedgerAcquireMaster::findCreate(const uint256& hash)
@@ -532,13 +534,13 @@ void LedgerAcquireMaster::dropLedger(const uint256& hash)
mLedgers.erase(hash);
}
-bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref peer)
+SMAddNode LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref peer)
{
uint256 hash;
if (packet.ledgerhash().size() != 32)
{
std::cerr << "Acquire error" << std::endl;
- return false;
+ return SMAddNode::invalid();
}
memcpy(hash.begin(), packet.ledgerhash().data(), 32);
cLog(lsTRACE) << "Got data (" << packet.nodes().size() << ") for acquiring ledger: " << hash;
@@ -547,7 +549,7 @@ bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref
if (!ledger)
{
cLog(lsINFO) << "Got data for ledger we're not acquiring";
- return false;
+ return SMAddNode();
}
if (packet.type() == ripple::liBASE)
@@ -555,23 +557,24 @@ bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref
if (packet.nodes_size() < 1)
{
cLog(lsWARNING) << "Got empty base data";
- return false;
+ return SMAddNode::invalid();
}
if (!ledger->takeBase(packet.nodes(0).nodedata()))
{
cLog(lsWARNING) << "Got invalid base data";
- return false;
+ return SMAddNode::invalid();
}
- if ((packet.nodes().size() > 1) && !ledger->takeAsRootNode(strCopy(packet.nodes(1).nodedata())))
+ SMAddNode san = SMAddNode::useful();
+ if ((packet.nodes().size() > 1) && !ledger->takeAsRootNode(strCopy(packet.nodes(1).nodedata()), san))
{
cLog(lsWARNING) << "Included ASbase invalid";
}
- if ((packet.nodes().size() > 2) && !ledger->takeTxRootNode(strCopy(packet.nodes(2).nodedata())))
+ if ((packet.nodes().size() > 2) && !ledger->takeTxRootNode(strCopy(packet.nodes(2).nodedata()), san))
{
cLog(lsWARNING) << "Included TXbase invalid";
}
ledger->trigger(peer, false);
- return true;
+ return san;
}
if ((packet.type() == ripple::liTX_NODE) || (packet.type() == ripple::liAS_NODE))
@@ -581,8 +584,8 @@ bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref
if (packet.nodes().size() <= 0)
{
- cLog(lsINFO) << "Got request for no nodes";
- return false;
+ cLog(lsINFO) << "Got response with no nodes";
+ return SMAddNode::invalid();
}
for (int i = 0; i < packet.nodes().size(); ++i)
{
@@ -590,24 +593,24 @@ bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref
if (!node.has_nodeid() || !node.has_nodedata())
{
cLog(lsWARNING) << "Got bad node";
- return false;
+ return SMAddNode::invalid();
}
nodeIDs.push_back(SHAMapNode(node.nodeid().data(), node.nodeid().size()));
nodeData.push_back(std::vector(node.nodedata().begin(), node.nodedata().end()));
}
- bool ret;
+ SMAddNode ret;
if (packet.type() == ripple::liTX_NODE)
- ret = ledger->takeTxNode(nodeIDs, nodeData);
+ ledger->takeTxNode(nodeIDs, nodeData, ret);
else
- ret = ledger->takeAsNode(nodeIDs, nodeData);
- if (ret)
+ ledger->takeAsNode(nodeIDs, nodeData, ret);
+ if (!ret.isInvalid())
ledger->trigger(peer, false);
return ret;
}
cLog(lsWARNING) << "Not sure what ledger data we got";
- return false;
+ return SMAddNode::invalid();
}
// vim:ts=4
diff --git a/src/cpp/ripple/LedgerAcquire.h b/src/cpp/ripple/LedgerAcquire.h
index eab3e47d82..2f9778c565 100644
--- a/src/cpp/ripple/LedgerAcquire.h
+++ b/src/cpp/ripple/LedgerAcquire.h
@@ -97,10 +97,12 @@ public:
void addOnComplete(boost::function);
bool takeBase(const std::string& data);
- bool takeTxNode(const std::list& IDs, const std::list >& data);
- bool takeTxRootNode(const std::vector& data);
- bool takeAsNode(const std::list& IDs, const std::list >& data);
- bool takeAsRootNode(const std::vector& data);
+ bool takeTxNode(const std::list& IDs, const std::list >& data,
+ SMAddNode&);
+ bool takeTxRootNode(const std::vector& data, SMAddNode&);
+ bool takeAsNode(const std::list& IDs, const std::list >& data,
+ SMAddNode&);
+ bool takeAsRootNode(const std::vector& data, SMAddNode&);
void trigger(Peer::ref, bool timer);
bool tryLocal();
void addPeers();
@@ -119,7 +121,7 @@ public:
LedgerAcquire::pointer find(const uint256& hash);
bool hasLedger(const uint256& ledgerHash);
void dropLedger(const uint256& ledgerHash);
- bool gotLedgerData(ripple::TMLedgerData& packet, Peer::ref);
+ SMAddNode gotLedgerData(ripple::TMLedgerData& packet, Peer::ref);
};
#endif
diff --git a/src/cpp/ripple/LedgerConsensus.cpp b/src/cpp/ripple/LedgerConsensus.cpp
index 7cc01870db..27ac245ae6 100644
--- a/src/cpp/ripple/LedgerConsensus.cpp
+++ b/src/cpp/ripple/LedgerConsensus.cpp
@@ -126,21 +126,23 @@ void TransactionAcquire::trigger(Peer::ref peer, bool timer)
resetTimer();
}
-bool TransactionAcquire::takeNodes(const std::list& nodeIDs,
+SMAddNode TransactionAcquire::takeNodes(const std::list& nodeIDs,
const std::list< std::vector >& data, Peer::ref peer)
{
if (mComplete)
{
cLog(lsTRACE) << "TX set complete";
- return true;
+ return SMAddNode();
}
if (mFailed)
{
cLog(lsTRACE) << "TX set failed";
- return false;
+ return SMAddNode();
}
try
{
+ if (nodeIDs.empty())
+ return SMAddNode::invalid();
std::list::const_iterator nodeIDit = nodeIDs.begin();
std::list< std::vector >::const_iterator nodeDatait = data.begin();
ConsensusTransSetSF sf;
@@ -151,12 +153,12 @@ bool TransactionAcquire::takeNodes(const std::list& nodeIDs,
if (mHaveRoot)
{
cLog(lsWARNING) << "Got root TXS node, already have it";
- return false;
+ return SMAddNode();
}
if (!mMap->addRootNode(getHash(), *nodeDatait, snfWIRE, NULL))
{
cLog(lsWARNING) << "TX acquire got bad root node";
- return false;
+ return SMAddNode::invalid();
}
else
mHaveRoot = true;
@@ -164,19 +166,19 @@ bool TransactionAcquire::takeNodes(const std::list& nodeIDs,
else if (!mMap->addKnownNode(*nodeIDit, *nodeDatait, &sf))
{
cLog(lsWARNING) << "TX acquire got bad non-root node";
- return false;
+ return SMAddNode::invalid();
}
++nodeIDit;
++nodeDatait;
}
trigger(peer, false);
progress();
- return true;
+ return SMAddNode::useful();
}
catch (...)
{
cLog(lsERROR) << "Peer sends us junky transaction node data";
- return false;
+ return SMAddNode::invalid();
}
}
@@ -996,14 +998,14 @@ bool LedgerConsensus::peerHasSet(Peer::ref peer, const uint256& hashSet, ripple:
return true;
}
-bool LedgerConsensus::peerGaveNodes(Peer::ref peer, const uint256& setHash,
+SMAddNode LedgerConsensus::peerGaveNodes(Peer::ref peer, const uint256& setHash,
const std::list& nodeIDs, const std::list< std::vector >& nodeData)
{
boost::unordered_map::iterator acq = mAcquiring.find(setHash);
if (acq == mAcquiring.end())
{
cLog(lsINFO) << "Got TX data for set not acquiring: " << setHash;
- return false;
+ return SMAddNode();
}
TransactionAcquire::pointer set = acq->second; // We must keep the set around during the function
return set->takeNodes(nodeIDs, nodeData, peer);
diff --git a/src/cpp/ripple/LedgerConsensus.h b/src/cpp/ripple/LedgerConsensus.h
index 1db7069961..accbb4df46 100644
--- a/src/cpp/ripple/LedgerConsensus.h
+++ b/src/cpp/ripple/LedgerConsensus.h
@@ -45,7 +45,8 @@ public:
SHAMap::pointer getMap() { return mMap; }
- bool takeNodes(const std::list& IDs, const std::list< std::vector >& data, Peer::ref);
+ SMAddNode takeNodes(const std::list& IDs,
+ const std::list< std::vector >& data, Peer::ref);
};
class LCTransaction
@@ -184,7 +185,7 @@ public:
bool peerHasSet(Peer::ref peer, const uint256& set, ripple::TxSetStatus status);
- bool peerGaveNodes(Peer::ref peer, const uint256& setHash,
+ SMAddNode peerGaveNodes(Peer::ref peer, const uint256& setHash,
const std::list& nodeIDs, const std::list< std::vector >& nodeData);
bool isOurPubKey(const RippleAddress &k) { return k == mValPublic; }
diff --git a/src/cpp/ripple/LedgerEntrySet.cpp b/src/cpp/ripple/LedgerEntrySet.cpp
index 1ff883fb52..59df4ec215 100644
--- a/src/cpp/ripple/LedgerEntrySet.cpp
+++ b/src/cpp/ripple/LedgerEntrySet.cpp
@@ -407,22 +407,26 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result)
mSet.setAffectedNode(it.first, *type, nodeType);
if (type == &sfDeletedNode)
- { // nodes was deleted
+ {
assert(origNode);
assert(curNode);
threadOwners(origNode, mLedger, newMod); // thread transaction to owners
- STObject mods(sfPreviousFields);
+ STObject prevs(sfPreviousFields);
+ BOOST_FOREACH(const SerializedType& obj, *origNode)
+ { // go through the original node for modified fields saved on modification
+ if (obj.getFName().shouldMeta(SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry(obj))
+ prevs.addObject(obj);
+ }
+ if (!prevs.empty())
+ mSet.getAffectedNode(it.first, *type).addObject(prevs);
+
STObject finals(sfFinalFields);
BOOST_FOREACH(const SerializedType& obj, *curNode)
- {
- if (obj.getFName().shouldMeta(SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry(obj))
- mods.addObject(obj);
+ { // go through the final node for final fields
if (obj.getFName().shouldMeta(SField::sMD_Always | SField::sMD_DeleteFinal))
finals.addObject(obj);
}
- if (!mods.empty())
- mSet.getAffectedNode(it.first, *type).addObject(mods);
if (!finals.empty())
mSet.getAffectedNode(it.first, *type).addObject(finals);
}
@@ -431,17 +435,21 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result)
if (curNode->isThreadedType()) // thread transaction to node it modified
threadTx(curNode, mLedger, newMod);
- STObject mods(sfPreviousFields);
- STObject finals(sfFinalFields);
+ STObject prevs(sfPreviousFields);
BOOST_FOREACH(const SerializedType& obj, *origNode)
{ // search the original node for values saved on modify
if (obj.getFName().shouldMeta(SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry(obj))
- mods.addObject(obj);
+ prevs.addObject(obj);
+ }
+ if (!prevs.empty())
+ mSet.getAffectedNode(it.first, *type).addObject(prevs);
+
+ STObject finals(sfFinalFields);
+ BOOST_FOREACH(const SerializedType& obj, *curNode)
+ { // search the final node for values saved always
if (obj.getFName().shouldMeta(SField::sMD_Always | SField::sMD_ChangeNew))
finals.addObject(obj);
}
- if (!mods.empty())
- mSet.getAffectedNode(it.first, *type).addObject(mods);
if (!finals.empty())
mSet.getAffectedNode(it.first, *type).addObject(finals);
}
diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp
index ed4847f9bd..53654ab454 100644
--- a/src/cpp/ripple/NetworkOPs.cpp
+++ b/src/cpp/ripple/NetworkOPs.cpp
@@ -813,13 +813,13 @@ SHAMap::pointer NetworkOPs::getTXMap(const uint256& hash)
return mConsensus->getTransactionTree(hash, false);
}
-bool NetworkOPs::gotTXData(const boost::shared_ptr& peer, const uint256& hash,
+SMAddNode NetworkOPs::gotTXData(const boost::shared_ptr& peer, const uint256& hash,
const std::list& nodeIDs, const std::list< std::vector >& nodeData)
{
if (!haveConsensusObject())
{
cLog(lsWARNING) << "Got TX data with no consensus object";
- return false;
+ return SMAddNode();
}
return mConsensus->peerGaveNodes(peer, hash, nodeIDs, nodeData);
}
@@ -1029,18 +1029,17 @@ void NetworkOPs::pubLedger(Ledger::ref lpAccepted)
for (SHAMapItem::pointer item = txSet.peekFirstItem(); !!item; item = txSet.peekNextItem(item->getTag()))
{
- SerializedTransaction::pointer stTxn = theApp->getMasterTransaction().fetch(item, false, 0);
- if(stTxn)
- {
- // XXX Need to support other results.
- // XXX Need to give failures too.
- TER terResult = tesSUCCESS;
-
- SerializerIterator it(item->peekSerializer());
+ SerializerIterator it(item->peekSerializer());
- TransactionMetaSet::pointer meta = boost::make_shared(stTxn->getTransactionID(), lpAccepted->getLedgerSeq(), it.getVL());
- pubAcceptedTransaction(lpAccepted, *stTxn, terResult,meta);
- }
+ // OPTIMIZEME: Could get transaction from txn master, but still must call getVL
+ Serializer txnSer(it.getVL());
+ SerializerIterator txnIt(txnSer);
+ SerializedTransaction stTxn(txnIt);
+
+ TransactionMetaSet::pointer meta = boost::make_shared(
+ stTxn.getTransactionID(), lpAccepted->getLedgerSeq(), it.getVL());
+
+ pubAcceptedTransaction(lpAccepted, stTxn, meta->getResultTER(), meta);
}
}
}
@@ -1135,6 +1134,7 @@ void NetworkOPs::pubAccountTransaction(Ledger::ref lpCurrent, const SerializedTr
if (!notify.empty())
{
Json::Value jvObj = transJson(stTxn, terResult, bAccepted, lpCurrent, "account");
+ if(meta) jvObj["meta"]=meta->getJson(0);
BOOST_FOREACH(InfoSub* ispListener, notify)
{
@@ -1194,7 +1194,7 @@ void NetworkOPs::subAccount(InfoSub* ispListener, const boost::unordered_set usisElement;
usisElement.insert(ispListener);
- mSubAccount.insert(simIterator, make_pair(naAccountID.getAccountID(), usisElement));
+ subMap.insert(simIterator, make_pair(naAccountID.getAccountID(), usisElement));
}
else
{
diff --git a/src/cpp/ripple/NetworkOPs.h b/src/cpp/ripple/NetworkOPs.h
index 778846a227..4826979e15 100644
--- a/src/cpp/ripple/NetworkOPs.h
+++ b/src/cpp/ripple/NetworkOPs.h
@@ -199,7 +199,7 @@ public:
// ledger proposal/close functions
void processTrustedProposal(LedgerProposal::pointer proposal, boost::shared_ptr set,
RippleAddress nodePublic, uint256 checkLedger, bool sigGood);
- bool gotTXData(const boost::shared_ptr& peer, const uint256& hash,
+ SMAddNode gotTXData(const boost::shared_ptr& peer, const uint256& hash,
const std::list& nodeIDs, const std::list< std::vector >& nodeData);
bool recvValidation(const SerializedValidation::pointer& val);
SHAMap::pointer getTXMap(const uint256& hash);
diff --git a/src/cpp/ripple/Peer.cpp b/src/cpp/ripple/Peer.cpp
index c42108e2e3..fcca1754d3 100644
--- a/src/cpp/ripple/Peer.cpp
+++ b/src/cpp/ripple/Peer.cpp
@@ -1432,12 +1432,14 @@ void Peer::recvLedger(ripple::TMLedgerData& packet)
nodeIDs.push_back(SHAMapNode(node.nodeid().data(), node.nodeid().size()));
nodeData.push_back(std::vector(node.nodedata().begin(), node.nodedata().end()));
}
- if (!theApp->getOPs().gotTXData(shared_from_this(), hash, nodeIDs, nodeData))
+ SMAddNode san = theApp->getOPs().gotTXData(shared_from_this(), hash, nodeIDs, nodeData);
+ if (san.isInvalid())
punishPeer(PP_UNWANTED_DATA);
return;
}
- if (!theApp->getMasterLedgerAcquire().gotLedgerData(packet, shared_from_this()))
+ SMAddNode san = theApp->getMasterLedgerAcquire().gotLedgerData(packet, shared_from_this());
+ if (san.isInvalid())
punishPeer(PP_UNWANTED_DATA);
}
diff --git a/src/cpp/ripple/Peer.h b/src/cpp/ripple/Peer.h
index f3c29c0f24..c05aac0d2b 100644
--- a/src/cpp/ripple/Peer.h
+++ b/src/cpp/ripple/Peer.h
@@ -22,6 +22,12 @@ enum PeerPunish
PP_BAD_SIGNATURE = 4, // Object had bad signature
};
+enum PeerReward
+{
+ PR_NEEDED_DATA = 1,
+ PR_NEW_TRANSACTION = 2,
+};
+
typedef std::pair ipPort;
DEFINE_INSTANCE(Peer);
diff --git a/src/cpp/ripple/ProofOfWork.cpp b/src/cpp/ripple/ProofOfWork.cpp
index c550a97497..1e4ab5d9b1 100644
--- a/src/cpp/ripple/ProofOfWork.cpp
+++ b/src/cpp/ripple/ProofOfWork.cpp
@@ -213,12 +213,28 @@ void ProofOfWorkGenerator::sweep()
void ProofOfWorkGenerator::loadHigh()
{
- // WRITEME
+ time_t now = time(NULL);
+
+ boost::mutex::scoped_lock sl(mLock);
+ if (mLastDifficultyChange == now)
+ return;
+ if (mPowEntry == 30)
+ return;
+ ++mPowEntry;
+ mLastDifficultyChange = now;
}
void ProofOfWorkGenerator::loadLow()
{
- // WRITEME
+ time_t now = time(NULL);
+
+ boost::mutex::scoped_lock sl(mLock);
+ if (mLastDifficultyChange == now)
+ return;
+ if (mPowEntry == 0)
+ return;
+ --mPowEntry;
+ mLastDifficultyChange = now;
}
struct PowEntry
diff --git a/src/cpp/ripple/SHAMap.h b/src/cpp/ripple/SHAMap.h
index 7adc92bc2f..c4d8302620 100644
--- a/src/cpp/ripple/SHAMap.h
+++ b/src/cpp/ripple/SHAMap.h
@@ -281,6 +281,44 @@ public:
extern std::ostream& operator<<(std::ostream&, const SHAMapMissingNode&);
+class SMAddNode
+{ // results of adding nodes
+protected:
+ bool mInvalid, mUseful;
+
+ SMAddNode(bool i, bool u) : mInvalid(i), mUseful(u) { ; }
+
+public:
+ SMAddNode() : mInvalid(false), mUseful(false) { ; }
+
+ void setInvalid() { mInvalid = true; }
+ void setUseful() { mUseful = true; }
+ void reset() { mInvalid = false; mUseful = false; }
+
+ bool isInvalid() const { return mInvalid; }
+ bool isUseful() const { return mUseful; }
+
+ bool combine(const SMAddNode& n)
+ {
+ if (n.mInvalid)
+ {
+ mInvalid = true;
+ return false;
+ }
+ if (n.mUseful)
+ mUseful = true;
+ return true;
+ }
+
+ operator bool() const { return !mInvalid; }
+
+ static SMAddNode okay() { return SMAddNode(false, false); }
+ static SMAddNode useful() { return SMAddNode(false, true); }
+ static SMAddNode invalid() { return SMAddNode(true, false); }
+};
+
+extern bool SMANCombine(SMAddNode& existing, const SMAddNode& additional);
+
class SHAMap : public IS_INSTANCE(SHAMap)
{
public:
@@ -374,11 +412,11 @@ public:
bool getNodeFat(const SHAMapNode& node, std::vector& nodeIDs,
std::list >& rawNode, bool fatRoot, bool fatLeaves);
bool getRootNode(Serializer& s, SHANodeFormat format);
- bool addRootNode(const uint256& hash, const std::vector& rootNode, SHANodeFormat format,
+ SMAddNode addRootNode(const uint256& hash, const std::vector& rootNode, SHANodeFormat format,
SHAMapSyncFilter* filter);
- bool addRootNode(const std::vector& rootNode, SHANodeFormat format,
+ SMAddNode addRootNode(const std::vector& rootNode, SHANodeFormat format,
SHAMapSyncFilter* filter);
- bool addKnownNode(const SHAMapNode& nodeID, const std::vector& rawNode,
+ SMAddNode addKnownNode(const SHAMapNode& nodeID, const std::vector& rawNode,
SHAMapSyncFilter* filter);
// status functions
diff --git a/src/cpp/ripple/SHAMapSync.cpp b/src/cpp/ripple/SHAMapSync.cpp
index 5c419f1062..7abcf9fd8f 100644
--- a/src/cpp/ripple/SHAMapSync.cpp
+++ b/src/cpp/ripple/SHAMapSync.cpp
@@ -135,7 +135,8 @@ bool SHAMap::getRootNode(Serializer& s, SHANodeFormat format)
return true;
}
-bool SHAMap::addRootNode(const std::vector& rootNode, SHANodeFormat format, SHAMapSyncFilter* filter)
+SMAddNode SHAMap::addRootNode(const std::vector& rootNode, SHANodeFormat format,
+ SHAMapSyncFilter* filter)
{
boost::recursive_mutex::scoped_lock sl(mLock);
@@ -143,12 +144,12 @@ bool SHAMap::addRootNode(const std::vector& rootNode, SHANodeForm
if (root->getNodeHash().isNonZero())
{
cLog(lsTRACE) << "got root node, already have one";
- return true;
+ return SMAddNode::okay();
}
SHAMapTreeNode::pointer node = boost::make_shared(SHAMapNode(), rootNode, 0, format);
if (!node)
- return false;
+ return SMAddNode::invalid();
#ifdef DEBUG
node->dump();
@@ -170,10 +171,10 @@ bool SHAMap::addRootNode(const std::vector& rootNode, SHANodeForm
filter->gotNode(*root, root->getNodeHash(), s.peekData(), root->getType());
}
- return true;
+ return SMAddNode::useful();
}
-bool SHAMap::addRootNode(const uint256& hash, const std::vector& rootNode, SHANodeFormat format,
+SMAddNode SHAMap::addRootNode(const uint256& hash, const std::vector& rootNode, SHANodeFormat format,
SHAMapSyncFilter* filter)
{
boost::recursive_mutex::scoped_lock sl(mLock);
@@ -183,14 +184,12 @@ bool SHAMap::addRootNode(const uint256& hash, const std::vector&
{
cLog(lsTRACE) << "got root node, already have one";
assert(root->getNodeHash() == hash);
- return true;
+ return SMAddNode::okay();
}
SHAMapTreeNode::pointer node = boost::make_shared(SHAMapNode(), rootNode, 0, format);
- if (!node)
- return false;
- if (node->getNodeHash() != hash)
- return false;
+ if (!node || node->getNodeHash() != hash)
+ return SMAddNode::invalid();
returnNode(root, true);
root = node;
@@ -207,42 +206,42 @@ bool SHAMap::addRootNode(const uint256& hash, const std::vector&
filter->gotNode(*root, root->getNodeHash(), s.peekData(), root->getType());
}
- return true;
+ return SMAddNode::useful();
}
-bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector& rawNode,
+SMAddNode SHAMap::addKnownNode(const SHAMapNode& node, const std::vector& rawNode,
SHAMapSyncFilter* filter)
{ // return value: true=okay, false=error
assert(!node.isRoot());
if (!isSynching())
{
cLog(lsINFO) << "AddKnownNode while not synching";
- return true;
+ return SMAddNode::okay();
}
boost::recursive_mutex::scoped_lock sl(mLock);
if (checkCacheNode(node))
- return true;
+ return SMAddNode::okay();
std::stack stack = getStack(node.getNodeID(), true, true);
if (stack.empty())
{
cLog(lsWARNING) << "AddKnownNode with empty stack";
- return false;
+ return SMAddNode::invalid();
}
SHAMapTreeNode::pointer iNode = stack.top();
if (!iNode)
{ // we should always have a root
assert(false);
- return true;
+ return SMAddNode::invalid();
}
if (iNode->isLeaf() || (iNode->getDepth() >= node.getDepth()))
{
cLog(lsTRACE) << "got inner node, already had it (late)";
- return true;
+ return SMAddNode::okay();
}
if (iNode->getDepth() != (node.getDepth() - 1))
@@ -250,25 +249,25 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector(node, rawNode, mSeq, snfWIRE);
if (hash != newNode->getNodeHash()) // these aren't the droids we're looking for
- return false;
+ return SMAddNode::invalid();
if (filter)
{
@@ -279,7 +278,7 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vectorisLeaf())
- return true; // only a leaf can fill a branch
+ return SMAddNode::useful(); // only a leaf can fill a branch
// did this new leaf cause its parents to fill up
do
@@ -294,11 +293,11 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vectorgetChildNodeID(i), iNode->getChildHash(i), false);
if (nextNode->isInner() && !nextNode->isFullBelow())
- return true;
+ return SMAddNode::useful();
}
catch (SHAMapMissingNode&)
{
- return true;
+ return SMAddNode::useful();
}
}
iNode->setFullBelow();
@@ -306,7 +305,7 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vectorisFullBelow())
clearSynching();
- return true;
+ return SMAddNode::useful();
}
bool SHAMap::deepCompare(SHAMap& other)
@@ -486,6 +485,8 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
cLog(lsFATAL) << "Didn't get root node " << gotNodes.size();
BOOST_FAIL("NodeSize");
}
+
+ SMAddNode node();
if (!destination.addRootNode(*gotNodes.begin(), snfWIRE, NULL))
{
cLog(lsFATAL) << "AddRootNode fails";
diff --git a/src/cpp/ripple/Serializer.h b/src/cpp/ripple/Serializer.h
index 7b7b67fe25..4bb929b199 100644
--- a/src/cpp/ripple/Serializer.h
+++ b/src/cpp/ripple/Serializer.h
@@ -93,6 +93,7 @@ public:
// totality functions
const std::vector& peekData() const { return mData; }
std::vector getData() const { return mData; }
+ std::vector& modData() { return mData; }
int getCapacity() const { return mData.capacity(); }
int getDataLength() const { return mData.size(); }
const void* getDataPtr() const { return &mData.front(); }
diff --git a/src/cpp/ripple/TransactionMaster.cpp b/src/cpp/ripple/TransactionMaster.cpp
index bfa0a8b720..ed6b575d63 100644
--- a/src/cpp/ripple/TransactionMaster.cpp
+++ b/src/cpp/ripple/TransactionMaster.cpp
@@ -31,16 +31,29 @@ Transaction::pointer TransactionMaster::fetch(const uint256& txnID, bool checkDi
return txn;
}
-SerializedTransaction::pointer TransactionMaster::fetch(SHAMapItem::ref item, bool checkDisk, uint32 uCommitLedger)
+SerializedTransaction::pointer TransactionMaster::fetch(SHAMapItem::ref item, SHAMapTreeNode::TNType type,
+ bool checkDisk, uint32 uCommitLedger)
{
SerializedTransaction::pointer txn;
Transaction::pointer iTx = theApp->getMasterTransaction().fetch(item->getTag(), false);
if (!iTx)
{
- SerializerIterator sit(item->peekSerializer());
- txn = boost::make_shared(boost::ref(sit));
+ if (type == SHAMapTreeNode::tnTRANSACTION_NM)
+ {
+ SerializerIterator sit(item->peekSerializer());
+ txn = boost::make_shared(boost::ref(sit));
+ }
+ else if (type == SHAMapTreeNode::tnTRANSACTION_MD)
+ {
+ Serializer s;
+ int length;
+ item->peekSerializer().getVL(s.modData(), 0, length);
+ SerializerIterator sit(s);
+
+ txn = boost::make_shared(boost::ref(sit));
+ }
}
else
{
diff --git a/src/cpp/ripple/TransactionMaster.h b/src/cpp/ripple/TransactionMaster.h
index 138c05c9c0..2db5eb1701 100644
--- a/src/cpp/ripple/TransactionMaster.h
+++ b/src/cpp/ripple/TransactionMaster.h
@@ -16,7 +16,8 @@ public:
TransactionMaster();
Transaction::pointer fetch(const uint256&, bool checkDisk);
- SerializedTransaction::pointer fetch(SHAMapItem::ref item, bool checkDisk, uint32 uCommitLedger);
+ SerializedTransaction::pointer fetch(SHAMapItem::ref item, SHAMapTreeNode:: TNType type,
+ bool checkDisk, uint32 uCommitLedger);
// return value: true = we had the transaction already
bool canonicalize(Transaction::pointer& txn, bool maybeNew);
diff --git a/src/cpp/ripple/TransactionMeta.h b/src/cpp/ripple/TransactionMeta.h
index a22058089e..66f57b1cb7 100644
--- a/src/cpp/ripple/TransactionMeta.h
+++ b/src/cpp/ripple/TransactionMeta.h
@@ -37,6 +37,8 @@ public:
const uint256& getTxID() { return mTransactionID; }
uint32 getLgrSeq() { return mLedger; }
+ int getResult() const { return mResult; }
+ TER getResultTER() const { return static_cast(mResult); }
bool isNodeAffected(const uint256&) const;
void setAffectedNode(const uint256&, SField::ref type, uint16 nodeType);
@@ -45,6 +47,7 @@ public:
const STObject& peekAffectedNode(const uint256&) const;
//std::vector getAffectedAccounts();
+
Json::Value getJson(int p) const { return getAsObject().getJson(p); }
void addRaw(Serializer&, TER);
diff --git a/src/cpp/ripple/UniqueNodeList.cpp b/src/cpp/ripple/UniqueNodeList.cpp
index 9b9c55a5d1..df37f6d4df 100644
--- a/src/cpp/ripple/UniqueNodeList.cpp
+++ b/src/cpp/ripple/UniqueNodeList.cpp
@@ -1547,14 +1547,17 @@ void UniqueNodeList::validatorsResponse(const boost::system::error_code& err, st
void UniqueNodeList::nodeNetwork()
{
- HttpsClient::httpsGet(
- theApp->getIOService(),
- theConfig.VALIDATORS_SITE,
- 443,
- VALIDATORS_FILE_PATH,
- VALIDATORS_FILE_BYTES_MAX,
- boost::posix_time::seconds(VALIDATORS_FETCH_SECONDS),
- boost::bind(&UniqueNodeList::validatorsResponse, this, _1, _2));
+ if(!theConfig.VALIDATORS_SITE.empty())
+ {
+ HttpsClient::httpsGet(
+ theApp->getIOService(),
+ theConfig.VALIDATORS_SITE,
+ 443,
+ VALIDATORS_FILE_PATH,
+ VALIDATORS_FILE_BYTES_MAX,
+ boost::posix_time::seconds(VALIDATORS_FETCH_SECONDS),
+ boost::bind(&UniqueNodeList::validatorsResponse, this, _1, _2));
+ }
}
void UniqueNodeList::nodeBootstrap()
diff --git a/src/cpp/ripple/WSConnection.cpp b/src/cpp/ripple/WSConnection.cpp
index 8030cdc670..875b18942f 100644
--- a/src/cpp/ripple/WSConnection.cpp
+++ b/src/cpp/ripple/WSConnection.cpp
@@ -50,7 +50,6 @@ Json::Value WSConnection::invokeCommand(Json::Value& jvRequest)
// Regular RPC command
{
- boost::recursive_mutex::scoped_lock sl(theApp->getMasterLock());
jvResult["result"] = mRPCHandler.doCommand(
jvRequest["command"].asString(),
jvRequest.isMember("params")
diff --git a/src/cpp/ripple/ripple.proto b/src/cpp/ripple/ripple.proto
index 5ffbb657df..250ebf5ac0 100644
--- a/src/cpp/ripple/ripple.proto
+++ b/src/cpp/ripple/ripple.proto
@@ -5,6 +5,7 @@ enum MessageType {
mtHELLO = 1;
mtERROR_MSG = 2;
mtPING = 3;
+ mtPOW = 4;
// network presence detection
mtGET_CONTACTS = 10;
@@ -32,20 +33,44 @@ enum MessageType {
}
-// Sent on connect
+// empty message (or just result) = request proof of work
+// token, iterations, target, challenge = give proof of work challenge
+// token, response = show proof of work
+// token, result = result of pow attempt
+message TMProofWork
+{
+ optional string token = 1;
+ optional uint32 iterations = 2;
+ optional bytes target = 3;
+ optional bytes challenge = 4;
+ optional bytes response = 5;
+ enum POWResult
+ {
+ powrOK = 0;
+ powrREUSED = 1;
+ powrEXPIRED = 2; // You took too long solving
+ powrTOOEASY = 3; // Difficulty went way up, sorry
+ powrINVALID = 4;
+ powrDISCONNECT = 5; // We are disconnecting
+ }
+ optional POWResult result = 6;
+}
+
+// Sent on connect
message TMHello {
- required uint32 protoVersion = 1;
- required uint32 protoVersionMin = 2;
- required bytes nodePublic = 3;
- required bytes nodeProof = 4;
- optional string fullVersion = 5;
- optional uint64 netTime = 6;
- optional uint32 ipv4Port = 7;
- optional uint32 ledgerIndex = 8;
- optional bytes ledgerClosed = 9; // our last closed ledger
- optional bytes ledgerPrevious = 10; // the ledger before the last closed ledger
- optional bool nodePrivate = 11; // Request to not forward IP.
+ required uint32 protoVersion = 1;
+ required uint32 protoVersionMin = 2;
+ required bytes nodePublic = 3;
+ required bytes nodeProof = 4;
+ optional string fullVersion = 5;
+ optional uint64 netTime = 6;
+ optional uint32 ipv4Port = 7;
+ optional uint32 ledgerIndex = 8;
+ optional bytes ledgerClosed = 9; // our last closed ledger
+ optional bytes ledgerPrevious = 10; // the ledger before the last closed ledger
+ optional bool nodePrivate = 11; // Request to not forward IP.
+ optional TMProofWork proofOfWork = 12; // request/provide proof of work
}
diff --git a/test/config-example.js b/test/config-example.js
index b0e9c44481..0724941867 100644
--- a/test/config-example.js
+++ b/test/config-example.js
@@ -14,12 +14,13 @@ exports.servers = {
// A local test server.
"alpha" : {
'trusted' : true,
+ 'no_server' : true,
// "peer_ip" : "0.0.0.0",
// "peer_port" : 51235,
'rpc_ip' : "0.0.0.0",
'rpc_port' : 5005,
'websocket_ip' : "127.0.0.1",
- 'websocket_port' : 6005,
+ 'websocket_port' : 5006,
// 'validation_seed' : "shhDFVsmS2GSu5vUyZSPXYfj1r79h",
// 'validators' : "n9L8LZZCwsdXzKUN9zoVxs4YznYXZ9hEhsQZY7aVpxtFaSceiyDZ beta"
}