From da3720baa98891105e66ea473b17cc3f42323a2a Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 20 Jun 2012 02:18:03 -0700 Subject: [PATCH 01/14] Bugfixes. --- src/LedgerConsensus.cpp | 14 +++++++++----- src/LedgerConsensus.h | 6 ++++-- src/NetworkOPs.cpp | 5 +++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index a9edbf0c38..76f6ff2786 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -188,12 +188,15 @@ int LCTransaction::getAgreeLevel() return (mNays * 100 + 100) / (mYays + mNays + 1); } -LedgerConsensus::LedgerConsensus(Ledger::pointer previousLedger, uint32 closeTime) - : mState(lcsPRE_CLOSE), mCloseTime(closeTime), mPreviousLedger(previousLedger) +LedgerConsensus::LedgerConsensus(const uint256& prevLCLHash, Ledger::pointer previousLedger, uint32 closeTime) + : mState(lcsPRE_CLOSE), mCloseTime(closeTime), mPrevLedgerHash(prevLCLHash), mPreviousLedger(previousLedger) { + mValSeed = theConfig.VALIDATION_SEED; Log(lsDEBUG) << "Creating consensus object"; Log(lsTRACE) << "LCL:" << previousLedger->getHash().GetHex() <<", ct=" << closeTime; - if (theConfig.VALIDATION_SEED.isValid()) + if (previousLedger->getHash() != prevLCLHash) + mHaveCorrectLCL = mProposing = mValidating = false; + else if (mValSeed.isValid()) { mValidating = true; mProposing = theApp->getOPs().getOperatingMode() == NetworkOPs::omFULL; @@ -205,7 +208,7 @@ void LedgerConsensus::takeInitialPosition(Ledger::pointer initialLedger) { SHAMap::pointer initialSet = initialLedger->peekTransactionMap()->snapShot(false); uint256 txSet = initialSet->getHash(); - assert (initialLedger->getParentHash() == mPreviousLedger->getHash()); + assert (!mHaveCorrectLCL || (initialLedger->getParentHash() == mPreviousLedger->getHash())); // if any peers have taken a contrary position, process disputes boost::unordered_set found; @@ -316,6 +319,7 @@ void LedgerConsensus::adjustCount(SHAMap::pointer map, const std::vectorgetLedgerSeq()); @@ -724,7 +728,7 @@ void LedgerConsensus::accept(SHAMap::pointer set) assert(set->getHash() == mOurPosition->getCurrentHash()); Log(lsINFO) << "Computing new LCL based on network consensus"; Log(lsDEBUG) << "Consensus " << mOurPosition->getCurrentHash().GetHex(); - Log(lsDEBUG) << "Previous LCL " << mPreviousLedger->getHash().GetHex(); + Log(lsDEBUG) << "Previous LCL " << mPrevLedgerHash.GetHex(); Ledger::pointer newLCL = boost::make_shared(false, boost::ref(*mPreviousLedger)); diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h index 349722951d..fa8be9ceb3 100644 --- a/src/LedgerConsensus.h +++ b/src/LedgerConsensus.h @@ -83,9 +83,11 @@ class LedgerConsensus : public boost::enable_shared_from_this protected: LCState mState; uint32 mCloseTime; + uint256 mPrevLedgerHash; Ledger::pointer mPreviousLedger; LedgerProposal::pointer mOurPosition; - bool mProposing, mValidating; + NewcoinAddress mValSeed; + bool mProposing, mValidating, mHaveCorrectLCL; // Convergence tracking, trusted peers indexed by hash of public key boost::unordered_map mPeerPositions; @@ -130,7 +132,7 @@ protected: void endConsensus(); public: - LedgerConsensus(Ledger::pointer previousLedger, uint32 closeTime); + LedgerConsensus(const uint256& prevLCLHash, Ledger::pointer previousLedger, uint32 closeTime); int startup(); diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 29166e1b4e..7941726ac0 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -491,8 +491,9 @@ int NetworkOPs::beginConsensus(Ledger::pointer closingLedger) // Create a consensus object to get consensus on this ledger if (!!mConsensus) mConsensus->abort(); prevLedger->setImmutable(); - mConsensus = boost::make_shared - (prevLedger, theApp->getMasterLedger().getCurrentLedger()->getCloseTimeNC()); + mConsensus = boost::make_shared( + prevLedger->getHash(), // FIXME: Only do this if the previous ledger is the consensus previous ledger + prevLedger, theApp->getMasterLedger().getCurrentLedger()->getCloseTimeNC()); Log(lsDEBUG) << "Pre-close time, initiating consensus engine"; return mConsensus->startup(); From 171b5420d01a3aab8115797677a9401bf98143ed Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 20 Jun 2012 02:20:31 -0700 Subject: [PATCH 02/14] Fix some bugs in previous commit. --- src/LedgerConsensus.cpp | 2 +- src/SerializedValidation.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 76f6ff2786..93e9770197 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -226,7 +226,7 @@ void LedgerConsensus::takeInitialPosition(Ledger::pointer initialLedger) if (mProposing) mOurPosition = boost::make_shared - (theConfig.VALIDATION_SEED, initialLedger->getParentHash(), txSet); + (mValSeed, initialLedger->getParentHash(), txSet); else mOurPosition = boost::make_shared(initialLedger->getParentHash(), txSet); mapComplete(txSet, initialSet, false); diff --git a/src/SerializedValidation.cpp b/src/SerializedValidation.cpp index 7647be4833..7026806395 100644 --- a/src/SerializedValidation.cpp +++ b/src/SerializedValidation.cpp @@ -22,7 +22,9 @@ SerializedValidation::SerializedValidation(const uint256& ledgerHash, const Newc : STObject(sValidationFormat), mSignature("Signature"), mTrusted(false) { setValueFieldH256(sfLedgerHash, ledgerHash); - setValueFieldVL(sfSigningKey, NewcoinAddress::createNodePublic(naSeed).getNodePublic()); + NewcoinAddress na(NewcoinAddress::createNodePublic(naSeed)); + if (na.isValid()) + setValueFieldVL(sfSigningKey, na.getNodePublic()); if (!isFull) setFlag(sFullFlag); NewcoinAddress::createNodePrivate(naSeed).signNodePrivate(getSigningHash(), mSignature.peekValue()); From 2e40ad2da688098ae6030c428124000a66109c8c Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 20 Jun 2012 02:31:24 -0700 Subject: [PATCH 03/14] Cleanup. --- src/NetworkOPs.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 7941726ac0..3fb47feb7e 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -334,14 +334,11 @@ void NetworkOPs::checkState(const boost::system::error_code& result) // check if the ledger is good enough to go to omFULL // Note: Do not go to omFULL if we don't have the previous ledger // check if the ledger is bad enough to go to omCONNECTED -- TODO - if (theConfig.VALIDATION_SEED.isValid()) - { - if (theApp->getOPs().getNetworkTimeNC() < - (theApp->getMasterLedger().getCurrentLedger()->getCloseTimeNC() + 4)) - setMode(omFULL); - else - Log(lsWARNING) << "Too late to go to full, try next ledger"; - } + if (theApp->getOPs().getNetworkTimeNC() < + (theApp->getMasterLedger().getCurrentLedger()->getCloseTimeNC() + 4)) + setMode(omFULL); + else + Log(lsWARNING) << "Too late to go to full, will try in consensus window"; } if (mMode == omFULL) From f17f4dc3054a0d8edb08185e3fc919e73631ccd7 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 20 Jun 2012 02:54:19 -0700 Subject: [PATCH 04/14] Halve no-DB startup time. --- src/Application.cpp | 19 ++++++++++++++----- src/DBInit.cpp | 23 +++++++++++++++++++---- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/Application.cpp b/src/Application.cpp index 4300f0bf4b..05ea8e446d 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -1,6 +1,9 @@ #include +#include +#include + #include "../database/SqliteDatabase.h" #include "Application.h" @@ -52,6 +55,11 @@ void Application::stop() std::cerr << "Stopped: " << mIOService.stopped() << std::endl; } +static void InitDB(DatabaseCon** dbCon, const char *fileName, const char *dbInit[], int dbCount) +{ + *dbCon = new DatabaseCon(fileName, dbInit, dbCount); +} + void Application::run() { assert(mTxnDB == NULL); @@ -61,11 +69,12 @@ void Application::run() // // Construct databases. // - mTxnDB = new DatabaseCon("transaction.db", TxnDBInit, TxnDBCount); - mLedgerDB = new DatabaseCon("ledger.db", LedgerDBInit, LedgerDBCount); - mWalletDB = new DatabaseCon("wallet.db", WalletDBInit, WalletDBCount); - mHashNodeDB = new DatabaseCon("hashnode.db", HashNodeDBInit, HashNodeDBCount); - mNetNodeDB = new DatabaseCon("netnode.db", NetNodeDBInit, NetNodeDBCount); + boost::thread t1(boost::bind(&InitDB, &mTxnDB, "transaction.db", TxnDBInit, TxnDBCount)); + boost::thread t2(boost::bind(&InitDB, &mLedgerDB, "ledger.db", LedgerDBInit, LedgerDBCount)); + boost::thread t3(boost::bind(&InitDB, &mWalletDB, "wallet.db", WalletDBInit, WalletDBCount)); + boost::thread t4(boost::bind(&InitDB, &mHashNodeDB, "hashnode.db", HashNodeDBInit, HashNodeDBCount)); + boost::thread t5(boost::bind(&InitDB, &mNetNodeDB, "netnode.db", NetNodeDBInit, NetNodeDBCount)); + t1.join(); t2.join(); t3.join(); t4.join(); t5.join(); // // Begin validation and ip maintenance. diff --git a/src/DBInit.cpp b/src/DBInit.cpp index 8c6931e3b6..083d8155d3 100644 --- a/src/DBInit.cpp +++ b/src/DBInit.cpp @@ -2,6 +2,8 @@ // Transaction database holds transactions and public keys const char *TxnDBInit[] = { + "BEGIN TRANSACTION;", + "CREATE TABLE Transactions ( \ TransID CHARACTER(64) PRIMARY KEY, \ TransType CHARACTER(24), \ @@ -21,13 +23,17 @@ const char *TxnDBInit[] = { LedgerSeq BIGINT UNSIGNED \ );", "CREATE INDEX AcctTxindex ON \ - AccountTransactions(Account, LedgerSeq, TransID);" + AccountTransactions(Account, LedgerSeq, TransID);", + + "END TRANSACTION;" }; int TxnDBCount = sizeof(TxnDBInit) / sizeof(const char *); // Ledger database holds ledgers and ledger confirmations const char *LedgerDBInit[] = { + "BEGIN TRANSACTION;", + "CREATE TABLE Ledgers ( \ LedgerHash CHARACTER(64) PRIMARY KEY, \ LedgerSeq BIGINT UNSIGNED, \ @@ -46,8 +52,9 @@ const char *LedgerDBInit[] = { Signature BLOB \ );", "CREATE INDEX LedgerConfByHash ON \ - LedgerConfirmations(LedgerHash)" + LedgerConfirmations(LedgerHash)", #endif + "END TRANSACTION;" }; int LedgerDBCount = sizeof(LedgerDBInit) / sizeof(const char *); @@ -55,6 +62,8 @@ int LedgerDBCount = sizeof(LedgerDBInit) / sizeof(const char *); // Wallet database holds local accounts and trusted nodes const char *WalletDBInit[] = { // Node identity must be persisted for CAS routing and responsibilities. + "BEGIN TRANSACTION;", + "CREATE TABLE NodeIdentity ( \ PublicKey CHARACTER(53), \ PrivateKey CHARACTER(52), \ @@ -221,13 +230,17 @@ const char *WalletDBInit[] = { );", "CREATE INDEX PeerScanIndex ON \ - PeerIps(ScanNext);" + PeerIps(ScanNext);", + + "END TRANSACTION;" }; int WalletDBCount = sizeof(WalletDBInit) / sizeof(const char *); // Hash node database holds nodes indexed by hash const char *HashNodeDBInit[] = { + "BEGIN TRANSACTION;", + "CREATE TABLE CommittedObjects ( \ Hash CHARACTER(64) PRIMARY KEY, \ ObjType CHAR(1) NOT NULL, \ @@ -236,7 +249,9 @@ const char *HashNodeDBInit[] = { );", "CREATE INDEX ObjectLocate ON \ - CommittedObjects(LedgerIndex, ObjType);" + CommittedObjects(LedgerIndex, ObjType);", + + "END TRANSACTION;" }; int HashNodeDBCount = sizeof(HashNodeDBInit) / sizeof(const char *); From 687def56f3ed87aface1fe26177fe02ec263ea9a Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 20 Jun 2012 04:17:30 -0700 Subject: [PATCH 05/14] Support a 'lost sync' status change. --- src/Peer.cpp | 16 +++++++++------- src/newcoin.proto | 1 + 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Peer.cpp b/src/Peer.cpp index f90b2935a4..056c4b57bd 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -803,21 +803,23 @@ void Peer::recvStatus(newcoin::TMStatusChange& packet) packet.set_networktime(theApp->getOPs().getNetworkTimeNC()); mLastStatus = packet; + if (packet.newevent() == newcoin::neLOST_SYNC) + { + mPreviousLedgerHash.zero(); + mClosedLedgerHash.zero(); + } if (packet.has_ledgerhash() && (packet.ledgerhash().size() == (256 / 8))) { // a peer has changed ledgers - if (packet.has_previousledgerhash() && (packet.previousledgerhash().size() == (256 / 8))) - memcpy(mPreviousLedgerHash.begin(), packet.previousledgerhash().data(), 256 / 8); - else - mPreviousLedgerHash = mClosedLedgerHash; memcpy(mClosedLedgerHash.begin(), packet.ledgerhash().data(), 256 / 8); mClosedLedgerTime = ptFromSeconds(packet.networktime()); Log(lsTRACE) << "peer LCL is " << mClosedLedgerHash.GetHex(); } - else if(packet.has_previousledgerhash() && packet.previousledgerhash().size() == (256 / 8)) + else mClosedLedgerHash.zero(); + if (packet.has_previousledgerhash() && packet.previousledgerhash().size() == (256 / 8)) { - memcpy(mClosedLedgerHash.begin(), packet.previousledgerhash().data(), 256 / 8); - mClosedLedgerTime = ptFromSeconds(packet.networktime()); + memcpy(mPreviousLedgerHash.begin(), packet.previousledgerhash().data(), 256 / 8); } + else mPreviousLedgerHash.zero(); } void Peer::recvGetLedger(newcoin::TMGetLedger& packet) diff --git a/src/newcoin.proto b/src/newcoin.proto index 38be08e20c..1b4e30f556 100644 --- a/src/newcoin.proto +++ b/src/newcoin.proto @@ -88,6 +88,7 @@ enum NodeEvent { neCLOSING_LEDGER = 1; // closing a ledger because its close time has come neACCEPTED_LEDGER = 2; // accepting a closed ledger, we have finished computing it neSWITCHED_LEDGER = 3; // changing due to network consensus + neLOST_SYNC = 4; } message TMStatusChange { From c7fd34bf9eb1420ce7cc6a4b3a84d0a2e4728c7c Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 20 Jun 2012 04:18:36 -0700 Subject: [PATCH 06/14] bugfix. --- src/ValidationCollection.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/ValidationCollection.cpp b/src/ValidationCollection.cpp index 7da2747365..15d6d92792 100644 --- a/src/ValidationCollection.cpp +++ b/src/ValidationCollection.cpp @@ -12,12 +12,15 @@ bool ValidationCollection::addValidation(SerializedValidation::pointer val) uint256 hash = val->getLedgerHash(); uint160 node = val->getSignerPublic().getNodeID(); - boost::mutex::scoped_lock sl(mValidationLock); - bool ret = mValidations[hash].insert(std::make_pair(node, val)).second; - if (ret) - Log(lsINFO) << "Val for " << hash.GetHex() << " from " << node.GetHex() << " added " << - (val->isTrusted() ? "trusted" : "UNtrusted"); - return ret; + { + boost::mutex::scoped_lock sl(mValidationLock); + if (!mValidations[hash].insert(std::make_pair(node, val)).second) + return false; + } + + Log(lsINFO) << "Val for " << hash.GetHex() << " from " << node.GetHex() << " added " << + (val->isTrusted() ? "trusted" : "UNtrusted"); + return true; } ValidationSet ValidationCollection::getValidations(const uint256& ledger) @@ -38,10 +41,9 @@ void ValidationCollection::getValidationCount(const uint256& ledger, int& truste boost::unordered_map::iterator it = mValidations.find(ledger); if (it != mValidations.end()) { - for (ValidationSet::iterator vit = it->second.begin(), end = it->second.end(); - vit != end; ++vit) + for (ValidationSet::iterator vit = it->second.begin(), end = it->second.end(); vit != end; ++vit) { - if(vit->second->isTrusted()) + if (vit->second->isTrusted()) ++trusted; else ++untrusted; From 582f18eec55a4802101e36d1eff7f252cf9ead44 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 20 Jun 2012 04:18:48 -0700 Subject: [PATCH 07/14] Fix crash bug. --- src/SerializedValidation.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/SerializedValidation.cpp b/src/SerializedValidation.cpp index 7026806395..209f870948 100644 --- a/src/SerializedValidation.cpp +++ b/src/SerializedValidation.cpp @@ -22,9 +22,8 @@ SerializedValidation::SerializedValidation(const uint256& ledgerHash, const Newc : STObject(sValidationFormat), mSignature("Signature"), mTrusted(false) { setValueFieldH256(sfLedgerHash, ledgerHash); - NewcoinAddress na(NewcoinAddress::createNodePublic(naSeed)); - if (na.isValid()) - setValueFieldVL(sfSigningKey, na.getNodePublic()); + if (naSeed.isValid()) + setValueFieldVL(sfSigningKey, NewcoinAddress::createNodePublic(naSeed).getNodePublic()); if (!isFull) setFlag(sFullFlag); NewcoinAddress::createNodePrivate(naSeed).signNodePrivate(getSigningHash(), mSignature.peekValue()); From 2ca0c51722870e82428115d06a995049d64cced9 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 20 Jun 2012 04:19:04 -0700 Subject: [PATCH 08/14] Assume peers cycle (until told otherwise) when we watch the network accept a new LCL --- src/Peer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Peer.h b/src/Peer.h index 99c0204af2..6b95cf12e8 100644 --- a/src/Peer.h +++ b/src/Peer.h @@ -135,6 +135,7 @@ public: uint256 getClosedLedgerHash() const { return mClosedLedgerHash; } NewcoinAddress getNodePublic() const { return mNodePublic; } + void cycleStatus() { mPreviousLedgerHash = mClosedLedgerHash; mClosedLedgerHash.zero(); } }; #endif From 0af5d379c2b1a77bfc954e7a8d02bd518cb4faa9 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 20 Jun 2012 04:23:29 -0700 Subject: [PATCH 09/14] Fix set: 1) Create validation structure even if not proposing (but if validating) 2) Fix hashes in status change messages, do it only one way 3) Don't spin right at wobble time. 4) Report accept status change on new last-closed ledger, not new open ledger. 5) Make sure validation count is correct even if we first encounter a ledger on ourselves (not a peer) 6) At end of consensus, assume nodes cycled (until they report otherwise). By doing nothing, we effectively assumed they didn't. 7) Miscellaneous cleanups and fixes. --- src/LedgerConsensus.cpp | 39 ++++++++++++++++++++++----------------- src/NetworkOPs.cpp | 38 ++++++++++++++++++++++++++------------ 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 93e9770197..073723ec01 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -16,6 +16,8 @@ // #define LC_DEBUG +// TODO: If we don't have the previousLCL, check if we got it. If so, change modes + TransactionAcquire::TransactionAcquire(const uint256& hash) : PeerSet(hash, 1), mFilter(&theApp->getNodeCache()), mHaveRoot(false) { @@ -224,7 +226,7 @@ void LedgerConsensus::takeInitialPosition(Ledger::pointer initialLedger) } } - if (mProposing) + if (mValidating) mOurPosition = boost::make_shared (mValSeed, initialLedger->getParentHash(), txSet); else @@ -319,15 +321,22 @@ void LedgerConsensus::adjustCount(SHAMap::pointer map, const std::vectorgetLedgerSeq()); - s.set_networktime(theApp->getOPs().getNetworkTimeNC()); - uint256 plhash = ledger->getParentHash(); - s.set_previousledgerhash(plhash.begin(), plhash.size()); + if (!mHaveCorrectLCL) + s.set_newevent(newcoin::neLOST_SYNC); + else + { + s.set_newevent(event); + s.set_ledgerseq(ledger->getLedgerSeq()); + s.set_networktime(theApp->getOPs().getNetworkTimeNC()); + uint256 hash = ledger->getParentHash(); + s.set_previousledgerhash(hash.begin(), hash.size()); + hash = ledger->getHash(); + s.set_ledgerhash(hash.begin(), hash.size()); + } PackedMessage::pointer packet = boost::make_shared(s, newcoin::mtSTATUS_CHANGE); theApp->getConnectionPool().relayMessage(NULL, packet); + Log(lsINFO) << "send status change to peer"; } void LedgerConsensus::abort() @@ -751,15 +760,6 @@ void LedgerConsensus::accept(SHAMap::pointer set) uint256 newLCLHash = newLCL->getHash(); Log(lsTRACE) << "newLCL " << newLCLHash.GetHex(); -#ifdef DEBUG - if (1) - { - Log(lsTRACE) << "newLCL after transactions"; - Json::Value p; - newLCL->addJson(p, LEDGER_JSON_DUMP_TXNS | LEDGER_JSON_DUMP_STATE); - ssw.write(Log(lsTRACE).ref(), p); - } -#endif Ledger::pointer newOL = boost::make_shared(true, boost::ref(*newLCL)); @@ -815,6 +815,10 @@ void LedgerConsensus::accept(SHAMap::pointer set) Json::Value p; newOL->addJson(p, LEDGER_JSON_DUMP_TXNS | LEDGER_JSON_DUMP_STATE); ssw.write(Log(lsTRACE).ref(), p); + Log(lsINFO) << "newLCL after transactions"; + Json::Value p; + newLCL->addJson(p, LEDGER_JSON_DUMP_TXNS | LEDGER_JSON_DUMP_STATE); + ssw.write(Log(lsTRACE).ref(), p); } #endif @@ -831,7 +835,8 @@ void LedgerConsensus::accept(SHAMap::pointer set) theApp->getConnectionPool().relayMessage(NULL, boost::make_shared(val, newcoin::mtVALIDATION)); Log(lsINFO) << "Validation sent " << newLCL->getHash().GetHex(); } - statusChange(newcoin::neACCEPTED_LEDGER, newOL); + else Log(lsWARNING) << "Not validating"; + statusChange(newcoin::neACCEPTED_LEDGER, newLCL); } void LedgerConsensus::endConsensus() diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 3fb47feb7e..af8b8ad5a0 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -251,7 +251,7 @@ void NetworkOPs::setStateTimer(int sec) uint64 consensusTime = mLedgerMaster->getCurrentLedger()->getCloseTimeNC() - LEDGER_WOBBLE_TIME; uint64 now = getNetworkTimeNC(); - if (now >= consensusTime) sec = 0; + if (now >= consensusTime) sec = 1; else if (sec > (consensusTime - now)) sec = (consensusTime - now); } mNetTimer.expires_from_now(boost::posix_time::seconds(sec)); @@ -308,7 +308,6 @@ void NetworkOPs::checkState(const boost::system::error_code& result) return; } - // FIXME: Don't check unless last closed ledger is at least some seconds old // If full or tracking, check only at wobble time! if (checkLastClosedLedger(peerList)) @@ -374,9 +373,8 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector& peerLis if (!!peerLedger) { // FIXME: If we have this ledger, don't count it if it's too far past its close time - bool isNew = ledgers.find(peerLedger) == ledgers.end(); ValidationCount& vc = ledgers[peerLedger]; - if (isNew) + if (vc.nodesUsing == 0) { theApp->getValidations().getValidationCount(peerLedger, vc.trustedValidations, vc.untrustedValidations); @@ -392,19 +390,27 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector& peerLis Ledger::pointer currentClosed = mLedgerMaster->getClosedLedger(); uint256 closedLedger = currentClosed->getHash(); - ValidationCount& vc = ledgers[closedLedger]; - if ((vc.nodesUsing == 0) || (theApp->getWallet().getNodePublic() > vc.highNode)) - vc.highNode = theApp->getWallet().getNodePublic(); - ++ledgers[closedLedger].nodesUsing; + ValidationCount& ourVC = ledgers[closedLedger]; + if (ourVC.nodesUsing == 0) + { + ourVC.highNode = theApp->getWallet().getNodePublic(); + theApp->getValidations().getValidationCount(closedLedger, + ourVC.trustedValidations, ourVC.untrustedValidations); + } + ++ourVC.nodesUsing; + ValidationCount bestVC = ourVC; // 3) Is there a network ledger we'd like to switch to? If so, do we have it? bool switchLedgers = false; for(boost::unordered_map::iterator it = ledgers.begin(), end = ledgers.end(); it != end; ++it) { - if (it->second > vc) + Log(lsTRACE) << "L: " << it->first.GetHex() << + " t=" << it->second.trustedValidations << ", u=" << it->second.untrustedValidations << + ", n=" << it->second.nodesUsing; + if (it->second > bestVC) { - vc = it->second; + bestVC = it->second; closedLedger = it->first; switchLedgers = true; } @@ -464,8 +470,10 @@ void NetworkOPs::switchLastClosedLedger(Ledger::pointer newLedger) s.set_newevent(newcoin::neSWITCHED_LEDGER); s.set_ledgerseq(newLedger->getLedgerSeq()); s.set_networktime(theApp->getOPs().getNetworkTimeNC()); - uint256 plhash = newLedger->getParentHash(); - s.set_previousledgerhash(plhash.begin(), plhash.size()); + uint256 hash = newLedger->getParentHash(); + s.set_previousledgerhash(hash.begin(), hash.size()); + hash = newLedger->getHash(); + s.set_ledgerhash(hash.begin(), hash.size()); PackedMessage::pointer packet = boost::make_shared(s, newcoin::mtSTATUS_CHANGE); theApp->getConnectionPool().relayMessage(NULL, packet); } @@ -566,6 +574,12 @@ void NetworkOPs::mapComplete(const uint256& hash, SHAMap::pointer map) void NetworkOPs::endConsensus() { + uint256 deadLedger = theApp->getMasterLedger().getClosedLedger()->getParentHash(); + Log(lsTRACE) << "Ledger " << deadLedger.GetHex() << " is now dead"; + std::vector peerList = theApp->getConnectionPool().getPeerVector(); + for (std::vector::const_iterator it = peerList.begin(), end = peerList.end(); it != end; ++it) + if (*it && ((*it)->getClosedLedgerHash() == deadLedger)) + (*it)->cycleStatus(); mConsensus = boost::shared_ptr(); } From 7e35a793aa984c80d26aa4cada2b4a2a32493af8 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 20 Jun 2012 04:51:45 -0700 Subject: [PATCH 10/14] Fix. --- src/LedgerConsensus.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 073723ec01..acb269def5 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -816,9 +816,9 @@ void LedgerConsensus::accept(SHAMap::pointer set) newOL->addJson(p, LEDGER_JSON_DUMP_TXNS | LEDGER_JSON_DUMP_STATE); ssw.write(Log(lsTRACE).ref(), p); Log(lsINFO) << "newLCL after transactions"; - Json::Value p; - newLCL->addJson(p, LEDGER_JSON_DUMP_TXNS | LEDGER_JSON_DUMP_STATE); - ssw.write(Log(lsTRACE).ref(), p); + Json::Value p2; + newLCL->addJson(p2, LEDGER_JSON_DUMP_TXNS | LEDGER_JSON_DUMP_STATE); + ssw.write(Log(lsTRACE).ref(), p2); } #endif From a022f8304dd4aa71fdc1daa42d0faeacb2c21cc1 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 20 Jun 2012 06:04:54 -0700 Subject: [PATCH 11/14] Mark a FIXME --- src/NetworkOPs.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index af8b8ad5a0..100c9d4a1b 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -359,8 +359,11 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector& peerLis // Do we have sufficient validations for our last closed ledger? Or do sufficient nodes // agree? And do we have no better ledger available? // If so, we are either tracking or full. - boost::unordered_map ledgers; + // FIXME: We may have a ledger with many recent validations but that no directly-connected + // node is using. THis is kind of fundamental. + + boost::unordered_map ledgers; for (std::vector::const_iterator it = peerList.begin(), end = peerList.end(); it != end; ++it) { if (!*it) From 1549ef4d9b92246051c2586a3070cea70ce8c8eb Mon Sep 17 00:00:00 2001 From: jed Date: Wed, 20 Jun 2012 08:38:36 -0700 Subject: [PATCH 12/14] allow you to send large amounts from RPC --- newcoin.vcxproj | 2 +- src/Amount.cpp | 2 +- src/Peer.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/newcoin.vcxproj b/newcoin.vcxproj index 975e16da8e..ea76caa586 100644 --- a/newcoin.vcxproj +++ b/newcoin.vcxproj @@ -72,7 +72,7 @@ MaxSpeed true true - BOOST_TEST_NO_MAIN;_CRT_SECURE_NO_WARNINGS;_WIN32_WINNT=0x0501;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + BOOST_TEST_ALTERNATIVE_INIT_API;BOOST_TEST_NO_MAIN;_CRT_SECURE_NO_WARNINGS;_WIN32_WINNT=0x0501;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) ..\OpenSSL\include;..\boost_1_47_0;..\protobuf-2.4.1\src diff --git a/src/Amount.cpp b/src/Amount.cpp index cd4cd3bc5a..88d40b912a 100644 --- a/src/Amount.cpp +++ b/src/Amount.cpp @@ -100,7 +100,7 @@ bool STAmount::setValue(const std::string& sAmount, const std::string& sCurrency if (bInteger) { - uValue = sAmount.empty() ? 0 : boost::lexical_cast(sAmount); + uValue = sAmount.empty() ? 0 : boost::lexical_cast(sAmount); iOffset = 0; } else diff --git a/src/Peer.cpp b/src/Peer.cpp index 056c4b57bd..30cf075bd9 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -731,7 +731,7 @@ void Peer::recvGetPeers(newcoin::TMGetPeers& packet) addr->set_ipv4(inet_addr(strIP.c_str())); addr->set_ipv4port(port); - std::cout << "Teaching about: " << strIP << std::endl; + //std::cout << "Teaching about: " << strIP << std::endl; } @@ -757,7 +757,7 @@ void Peer::recvPeers(newcoin::TMPeers& packet) // if (strIP != "127.0.0.1") { - std::cout << "Learning about: " << strIP << std::endl; + //std::cout << "Learning about: " << strIP << std::endl; theApp->getConnectionPool().savePeer(strIP, port, 'T'); } From 3bc3e83b425446c77ef43baf05f221705c96a54b Mon Sep 17 00:00:00 2001 From: jed Date: Wed, 20 Jun 2012 09:37:19 -0700 Subject: [PATCH 13/14] windows installer --- deploy/cointoss.nsi | 37 ++++++++++ deploy/newcoind.cfg | 147 ++++++++++++++++++++++++++++++++++++++ deploy/start CoinToss.bat | 3 + deploy/validators.txt | 25 +++++++ 4 files changed, 212 insertions(+) create mode 100644 deploy/cointoss.nsi create mode 100644 deploy/newcoind.cfg create mode 100644 deploy/start CoinToss.bat create mode 100644 deploy/validators.txt diff --git a/deploy/cointoss.nsi b/deploy/cointoss.nsi new file mode 100644 index 0000000000..9e32d62bbd --- /dev/null +++ b/deploy/cointoss.nsi @@ -0,0 +1,37 @@ +Name "CoinToss" + +; The file to write +OutFile "toss install.exe" + +; The default installation directory +InstallDir "$PROGRAMFILES\CoinToss" + +; Request application privileges for Windows Vista +RequestExecutionLevel user + +;-------------------------------- + +; Pages + +Page directory +Page instfiles + +;-------------------------------- + +; The stuff to install +Section "" ;No components page, name is not important + + ; Set output path to the installation directory. + SetOutPath $INSTDIR + + ; Put file there + File ..\Release\newcoin.exe + File ..\*.dll + File "start CoinToss.bat" + File newcoind.cfg + File validators.txt + File /r /x .git ..\..\nc-client\*.* + + + +SectionEnd ; end the section diff --git a/deploy/newcoind.cfg b/deploy/newcoind.cfg new file mode 100644 index 0000000000..a4e5618295 --- /dev/null +++ b/deploy/newcoind.cfg @@ -0,0 +1,147 @@ +# +# Sample newcoind.cfg +# +# This file should be named newcoind.cfg. This file is UTF-8 with Dos, UNIX, +# or Mac style end of lines. Blank lines and lines beginning with '#' are +# ignored. Undefined sections are reserved. No escapes are currently defined. +# +# When you launch newcoind, it will attempt to find this file. +# +# --conf=: +# You may specify the location of this file with --conf=. The config +# directory is the directory containing this file. The data directory is a +# the subdirectory named "dbs". +# +# Windows and no --conf: +# The config directory is the same directory as the newcoind program. The +# data directory is a the subdirectory named "dbs". +# +# Other OSes and no --conf: +# This file will be looked for in these places in the following order: +# ./newcoind.cfg +# $XDG_CONFIG_HOME/newcoin/newcoind.cfg +# +# If newcoind.cfg, is found in the current working directory, the directory +# will be used as the config directory. The data directory is a the +# subdirectory named "dbs". +# +# Otherwise, the data directory data is: +# $XDG_DATA_HOME/newcoin/ +# +# Note: $XDG_CONFIG_HOME defaults to $HOME/.config +# $XDG_DATA_HOME defaults to $HOME/.local/share +# +# [debug_logfile] +# Specifies were a debug logfile is kept. By default, no debug log is kept +# +# Example: debug.log +# +# [validators_site]: +# Specifies where to find validators.txt for UNL boostrapping and RPC command unl_network. +# During alpha testing, this defaults to: redstem.com +# +# Example: newcoin.org +# +# [unl_default]: +# XXX This should be called: [validators_file] +# Specifies how to bootstrap the UNL list. The UNL list is based on a +# validators.txt file and is maintained in the databases. When newcoind +# starts up, if the databases are missing or are obsolete due to an upgrade +# of newcoind, newcoind will reconstruct the UNL list as specified here. +# +# If this entry is not present or empty, newcoind will look for a validators.txt in the +# config directory. If not found there, it will attempt to retrieve the file +# from the newcoin foundation's web site. +# +# This entry is also used by the RPC command unl_load. +# +# Specify the file by specifying its full path. +# +# Examples: +# C:/home/johndoe/newcoin/validators.txt +# /home/johndoe/newcoin/validators.txt +# +# [validators]: +# Only valid in "newcoind.cfg", "newcoin.txt", and the referered [validators_url]. +# List of nodes to accept as validators speficied by public key or domain. +# +# For domains, newcoind will probe for https web servers at the specied +# domain in the following order: newcoin.DOMAIN, www.DOMAIN, DOMAIN +# +# Examples: +# redstem.com +# n9KorY8QtTdRx7TVDpwnG9NvyxsDwHUKUEeDLY3AkiGncVaSXZi5 +# n9MqiExBcoG19UXwoLjBJnhsxEhAZMuWwJDRdkyDz1EkEkwzQTNt John Doe +# +# [ips]: +# Only valid in "newcoind.cfg", "newcoin.txt", and the referered [ips_url]. +# List of ips where the Newcoin protocol is avialable. +# One ipv4 or ipv6 address per line. +# A port may optionally be specified after adding a space to the address. +# By convention, if known, IPs are listed in from most to least trusted. +# +# Examples: +# 192.168.0.1 +# 192.168.0.1 3939 +# 2001:0db8:0100:f101:0210:a4ff:fee3:9566 +# +# [peer_ip]: +# IP address or domain to bind to allow external connections from peers. +# Defaults to not allow external connections from peers. +# +# Examples: 0.0.0.0 - Bind on all interfaces. +# +# [peer_port]: +# Port to bind to allow external connections from peers. +# +# [rpc_ip]: +# IP address or domain to bind to allow insecure RPC connections. +# Defaults to not allow RPC connections. +# +# [rpc_port]: +# Port to bind to if allowing insecure RPC connections. +# +# [rpc_allow_remote]: +# 0 or 1. 0 only allows RPC connections from 127.0.0.1. [default 0] +# +# [websocket_ip]: +# IP address or domain to bind to allow client connections. +# +# Examples: 0.0.0.0 - Bind on all interfaces. +# 127.0.0.1 - Bind on localhost interface. Only local programs may connect. +# +# [websocket_port]: +# Port to bind to allow client connections. +# +# [validation_seed]: +# To perform validation, this section should contain either a validation seed or key. +# The validation seed is used to generate the validation public/private key pair. +# To obtain a validation seed, use the validation_create command. +# +# Examples: RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE +# shfArahZT9Q9ckTf3s1psJ7C7qzVN +# + +[peer_ip] +0.0.0.0 + +[peer_port] +51235 + +[rpc_ip] +127.0.0.1 + +[rpc_port] +5005 + +[rpc_allow_remote] +1 + +[debug_logfile] +debug.log + +[validation_seed] +shh1D4oj5czH3PUEjYES8c7Bay3tE + +[unl_default] +validators.txt diff --git a/deploy/start CoinToss.bat b/deploy/start CoinToss.bat new file mode 100644 index 0000000000..b23c09ade2 --- /dev/null +++ b/deploy/start CoinToss.bat @@ -0,0 +1,3 @@ +start newcoin +sleep 4 +start index.html \ No newline at end of file diff --git a/deploy/validators.txt b/deploy/validators.txt new file mode 100644 index 0000000000..728f72bacc --- /dev/null +++ b/deploy/validators.txt @@ -0,0 +1,25 @@ +# +# Default validators.txt +# +# A list of domains to bootstrap a nodes UNLs or for clients to indirectly +# locate IPs to contact the Newcoin network. +# +# This file is UTF-8 with Dos, UNIX, or Mac style end of lines. +# Blank lines and lines starting with a '#' are ignored. +# All other lines should be hankos or domain names. +# +# [validators]: +# List of nodes to accept as validators speficied by public key or domain. +# +# For domains, newcoind will probe for https web servers at the specied +# domain in the following order: newcoin.DOMAIN, www.DOMAIN, DOMAIN +# +# Examples: redstem.com +# n9KorY8QtTdRx7TVDpwnG9NvyxsDwHUKUEeDLY3AkiGncVaSXZi5 +# n9MqiExBcoG19UXwoLjBJnhsxEhAZMuWwJDRdkyDz1EkEkwzQTNt John Doe +# + +[validators] +n9LQC4xFSWXNv1SU1sKtjrW6TZpBZSwp1nRWej8saGs155x42YFZ first +n9LFzWuhKNvXStHAuemfRKFVECLApowncMAM5chSCL9R5ECHGN4V second +n9KXAZxiHkWuVGxDEE8boW7WmcycpZNmWei4vxVaywLZ391Nbuqx third From 58dcc8b9c19863d3d8d1ea40d04900135ddc501a Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 20 Jun 2012 13:26:32 -0700 Subject: [PATCH 14/14] Don't use stale validiations. --- src/LedgerConsensus.cpp | 4 ++-- src/NetworkOPs.cpp | 6 ++---- src/SerializedObject.h | 1 + src/SerializedValidation.cpp | 10 +++++++++- src/SerializedValidation.h | 5 +++-- src/ValidationCollection.cpp | 31 +++++++++++++++++++++++++++---- src/ValidationCollection.h | 3 ++- 7 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index acb269def5..fc6a798c0e 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -825,7 +825,7 @@ void LedgerConsensus::accept(SHAMap::pointer set) if (mValidating) { SerializedValidation::pointer v = boost::make_shared - (newLCLHash, mOurPosition->peekSeed(), true); + (newLCLHash, newLCL->getCloseTimeNC(), mOurPosition->peekSeed(), true); v->setTrusted(); // FIXME: If not proposing, set not full theApp->getValidations().addValidation(v); @@ -833,7 +833,7 @@ void LedgerConsensus::accept(SHAMap::pointer set) newcoin::TMValidation val; val.set_validation(&validation[0], validation.size()); theApp->getConnectionPool().relayMessage(NULL, boost::make_shared(val, newcoin::mtVALIDATION)); - Log(lsINFO) << "Validation sent " << newLCL->getHash().GetHex(); + Log(lsINFO) << "Validation sent " << newLCLHash.GetHex(); } else Log(lsWARNING) << "Not validating"; statusChange(newcoin::neACCEPTED_LEDGER, newLCL); diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 100c9d4a1b..bad18d8862 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -269,8 +269,6 @@ public: { if (trustedValidations > v.trustedValidations) return true; if (trustedValidations < v.trustedValidations) return false; - if (untrustedValidations > v.untrustedValidations) return true; - if (untrustedValidations < v.untrustedValidations) return false; if (nodesUsing > v.nodesUsing) return true; if (nodesUsing < v.nodesUsing) return false; return highNode > v.highNode; @@ -379,7 +377,7 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector& peerLis ValidationCount& vc = ledgers[peerLedger]; if (vc.nodesUsing == 0) { - theApp->getValidations().getValidationCount(peerLedger, + theApp->getValidations().getValidationCount(peerLedger, true, vc.trustedValidations, vc.untrustedValidations); Log(lsTRACE) << peerLedger.GetHex() << " has " << vc.trustedValidations << " trusted validations and " << vc.untrustedValidations << " untrusted"; @@ -397,7 +395,7 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector& peerLis if (ourVC.nodesUsing == 0) { ourVC.highNode = theApp->getWallet().getNodePublic(); - theApp->getValidations().getValidationCount(closedLedger, + theApp->getValidations().getValidationCount(closedLedger, true, ourVC.trustedValidations, ourVC.untrustedValidations); } ++ourVC.nodesUsing; diff --git a/src/SerializedObject.h b/src/SerializedObject.h index 3c322486da..ab115e1254 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -38,6 +38,7 @@ enum SOE_Field sfBorrowRate, sfBorrowStart, sfBorrower, + sfCloseTime, sfCurrency, sfCurrencyIn, sfCurrencyOut, diff --git a/src/SerializedValidation.cpp b/src/SerializedValidation.cpp index 209f870948..9c19bc7615 100644 --- a/src/SerializedValidation.cpp +++ b/src/SerializedValidation.cpp @@ -4,6 +4,7 @@ SOElement SerializedValidation::sValidationFormat[] = { { sfFlags, "Flags", STI_UINT32, SOE_FLAGS, 0 }, { sfLedgerHash, "LedgerHash", STI_HASH256, SOE_REQUIRED, 0 }, + { sfCloseTime, "CloseTime", STI_UINT64, SOE_REQUIRED, 0 }, { sfSigningKey, "SigningKey", STI_VL, SOE_REQUIRED, 0 }, { sfExtensions, "Extensions", STI_TL, SOE_IFFLAG, 0x01000000 }, { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 }, @@ -18,10 +19,12 @@ SerializedValidation::SerializedValidation(SerializerIterator& sit, bool checkSi if (!isValid()) throw std::runtime_error("Invalid validation"); } -SerializedValidation::SerializedValidation(const uint256& ledgerHash, const NewcoinAddress& naSeed, bool isFull) +SerializedValidation::SerializedValidation(const uint256& ledgerHash, uint64 closeTime, + const NewcoinAddress& naSeed, bool isFull) : STObject(sValidationFormat), mSignature("Signature"), mTrusted(false) { setValueFieldH256(sfLedgerHash, ledgerHash); + setValueFieldU64(sfCloseTime, closeTime); if (naSeed.isValid()) setValueFieldVL(sfSigningKey, NewcoinAddress::createNodePublic(naSeed).getNodePublic()); if (!isFull) setFlag(sFullFlag); @@ -47,6 +50,11 @@ uint256 SerializedValidation::getLedgerHash() const return getValueFieldH256(sfLedgerHash); } +uint64 SerializedValidation::getCloseTime() const +{ + return getValueFieldU64(sfCloseTime); +} + bool SerializedValidation::isValid() const { try diff --git a/src/SerializedValidation.h b/src/SerializedValidation.h index 987a883234..ab0886a6bf 100644 --- a/src/SerializedValidation.h +++ b/src/SerializedValidation.h @@ -23,9 +23,10 @@ public: SerializedValidation(SerializerIterator& sit, bool checkSignature = true); SerializedValidation(const Serializer& s, bool checkSignature = true); - SerializedValidation(const uint256& ledgerHash, const NewcoinAddress& naSeed, bool isFull); + SerializedValidation(const uint256& ledgerHash, uint64 closeTime, const NewcoinAddress& naSeed, bool isFull); uint256 getLedgerHash() const; + uint64 getCloseTime() const; NewcoinAddress getSignerPublic() const; bool isValid() const; bool isFull() const; @@ -33,7 +34,7 @@ public: CKey::pointer getSigningKey() const; uint256 getSigningHash() const; - void setTrusted() { mTrusted = true; } + void setTrusted() { mTrusted = true; } void addSigned(Serializer&) const; void addSignature(Serializer&) const; std::vector getSigned() const; diff --git a/src/ValidationCollection.cpp b/src/ValidationCollection.cpp index 15d6d92792..b30ea4a00f 100644 --- a/src/ValidationCollection.cpp +++ b/src/ValidationCollection.cpp @@ -2,12 +2,21 @@ #include "ValidationCollection.h" #include "Application.h" +#include "LedgerTiming.h" #include "Log.h" bool ValidationCollection::addValidation(SerializedValidation::pointer val) { - if(theApp->getUNL().nodeInUNL(val->getSignerPublic())) - val->setTrusted(); + bool isTrusted = false; + if (theApp->getUNL().nodeInUNL(val->getSignerPublic())) + { + uint64 now = theApp->getOPs().getNetworkTimeNC(); + uint64 valClose = val->getCloseTime(); + if ((now > valClose) && (now < (valClose + 2 * LEDGER_INTERVAL))) + isTrusted = true; + else + Log(lsWARNING) << "Received stale validation"; + } uint256 hash = val->getLedgerHash(); uint160 node = val->getSignerPublic().getNodeID(); @@ -16,6 +25,12 @@ bool ValidationCollection::addValidation(SerializedValidation::pointer val) boost::mutex::scoped_lock sl(mValidationLock); if (!mValidations[hash].insert(std::make_pair(node, val)).second) return false; + if (isTrusted) + { + boost::unordered_map::iterator it = mCurrentValidations.find(node); + if ((it == mCurrentValidations.end()) || (val->getCloseTime() >= it->second->getCloseTime())) + mCurrentValidations[node] = val; + } } Log(lsINFO) << "Val for " << hash.GetHex() << " from " << node.GetHex() << " added " << @@ -34,16 +49,24 @@ ValidationSet ValidationCollection::getValidations(const uint256& ledger) return ret; } -void ValidationCollection::getValidationCount(const uint256& ledger, int& trusted, int &untrusted) +void ValidationCollection::getValidationCount(const uint256& ledger, bool currentOnly, int& trusted, int &untrusted) { trusted = untrusted = 0; boost::mutex::scoped_lock sl(mValidationLock); boost::unordered_map::iterator it = mValidations.find(ledger); + uint64 now = theApp->getOPs().getNetworkTimeNC(); if (it != mValidations.end()) { for (ValidationSet::iterator vit = it->second.begin(), end = it->second.end(); vit != end; ++vit) { - if (vit->second->isTrusted()) + bool trusted = vit->second->isTrusted(); + if (trusted && currentOnly) + { + uint64 closeTime = vit->second->getCloseTime(); + if ((now < closeTime) || (now > (closeTime + 2 * LEDGER_INTERVAL))) + trusted = false; + } + if (trusted) ++trusted; else ++untrusted; diff --git a/src/ValidationCollection.h b/src/ValidationCollection.h index 3f41e0fc0f..62540f5853 100644 --- a/src/ValidationCollection.h +++ b/src/ValidationCollection.h @@ -16,13 +16,14 @@ class ValidationCollection boost::mutex mValidationLock; boost::unordered_map mValidations; + boost::unordered_map mCurrentValidations; public: ValidationCollection() { ; } bool addValidation(SerializedValidation::pointer); ValidationSet getValidations(const uint256& ledger); - void getValidationCount(const uint256& ledger, int& trusted, int& untrusted); + void getValidationCount(const uint256& ledger, bool currentOnly, int& trusted, int& untrusted); }; #endif