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" }