From cc4827559c899eee322cbe50f574835f43a267eb Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 3 Sep 2012 06:03:09 -0700 Subject: [PATCH] Support for proposals that contain the previous ledger hash. A fix for ledger acquires not stopping when they should. --- src/LedgerConsensus.cpp | 15 ++++++++++----- src/LedgerProposal.h | 2 ++ src/NetworkOPs.cpp | 24 ++++++++++++++++++++---- src/Peer.cpp | 11 ++++++++--- src/newcoin.proto | 5 +++-- 5 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 44aae4eabc..cf36b77ea6 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -860,12 +860,17 @@ void LedgerConsensus::playbackProposals() { BOOST_FOREACH(const LedgerProposal::pointer& proposal, it->second) { - proposal->setPrevLedger(mPrevLedgerHash); - if (proposal->checkSign()) - { - Log(lsINFO) << "Applying deferred proposal"; - peerPosition(proposal); + if (proposal->hasSignature()) + { // old-style + proposal->setPrevLedger(mPrevLedgerHash); + if (proposal->checkSign()) + { + Log(lsINFO) << "Applying deferred proposal"; + peerPosition(proposal); + } } + else if (proposal->isPrevLedger(mPrevLedgerHash)) + peerPosition(proposal); } } } diff --git a/src/LedgerProposal.h b/src/LedgerProposal.h index 6bb833cc2d..a3d7faecde 100644 --- a/src/LedgerProposal.h +++ b/src/LedgerProposal.h @@ -56,6 +56,8 @@ public: void setPrevLedger(const uint256& prevLedger) { mPreviousLedger = prevLedger; } void setSignature(const std::string& signature) { mSignature = signature; } + bool hasSignature() { return !mSignature.empty(); } + bool isPrevLedger(const uint256& pl) { return mPreviousLedger == pl; } const boost::posix_time::ptime getCreateTime() { return mTime; } bool isStale(boost::posix_time::ptime cutoff) { return mTime > cutoff; } diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index f8860a56e1..6946687a61 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -518,7 +518,8 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector& peerLis if (!consensus) { Log(lsINFO) << "Acquiring consensus ledger " << closedLedger; - LedgerAcquire::pointer mAcquiringLedger = theApp->getMasterLedgerAcquire().findCreate(closedLedger); + if (!mAcquiringLedger || (mAcquiringLedger->getHash() != closedLedger)) + mAcquiringLedger = theApp->getMasterLedgerAcquire().findCreate(closedLedger); if (!mAcquiringLedger || mAcquiringLedger->isFailed()) { theApp->getMasterLedgerAcquire().dropLedger(closedLedger); @@ -605,8 +606,8 @@ int NetworkOPs::beginConsensus(const uint256& networkClosed, Ledger::pointer clo } // <-- bool: true to relay -bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, uint32 closeTime, - const std::string& pubKey, const std::string& signature, const NewcoinAddress& nodePublic) +bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, const uint256& prevLedger, + uint32 closeTime, const std::string& pubKey, const std::string& signature, const NewcoinAddress& nodePublic) { // JED: does mConsensus need to be locked? @@ -616,6 +617,7 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, uint // Get a preliminary hash to use to suppress duplicates Serializer s(256); s.add256(proposeHash); + s.add256(prevLedger); s.add32(proposeSeq); s.add32(closeTime); s.addRaw(pubKey); @@ -649,6 +651,21 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, uint return true; } + if (prevLedger.isNonZero()) + { // new-style + LedgerProposal::pointer proposal = + boost::make_shared(prevLedger, proposeSeq, proposeHash, closeTime, naPeerPublic); + if (!proposal->checkSign(signature)) + { + Log(lsWARNING) << "New-style ledger proposal fails signature check"; + return false; + } + if (prevLedger == mConsensus->getLCL()) + return mConsensus->peerPosition(proposal); + mConsensus->deferProposal(proposal, nodePublic); + return false; + } + LedgerProposal::pointer proposal = boost::make_shared(mConsensus->getLCL(), proposeSeq, proposeHash, closeTime, naPeerPublic); if (!proposal->checkSign(signature)) @@ -658,7 +675,6 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, uint mConsensus->deferProposal(proposal, nodePublic); return false; } - return mConsensus->peerPosition(proposal); } diff --git a/src/Peer.cpp b/src/Peer.cpp index 6d0a6be41a..d2955b6d59 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -724,10 +724,13 @@ void Peer::recvPropose(newcoin::TMProposeSet& packet) return; } - uint256 currentTxHash; + uint256 currentTxHash, prevLedger; memcpy(currentTxHash.begin(), packet.currenttxhash().data(), 32); - if(theApp->getOPs().recvPropose(packet.proposeseq(), currentTxHash, packet.closetime(), + if ((packet.has_previousledger()) && (packet.previousledger().size() == 32)) + memcpy(prevLedger.begin(), packet.previousledger().data(), 32); + + if(theApp->getOPs().recvPropose(packet.proposeseq(), currentTxHash, prevLedger, packet.closetime(), packet.nodepubkey(), packet.signature(), mNodePublic)) { // FIXME: Not all nodes will want proposals PackedMessage::pointer message = boost::make_shared(packet, newcoin::mtPROPOSE_LEDGER); @@ -969,6 +972,8 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet) } memcpy(ledgerhash.begin(), packet.ledgerhash().data(), 32); ledger = theApp->getMasterLedger().getLedgerByHash(ledgerhash); + if (!ledger) + Log(lsINFO) << "Don't have ledger " << ledgerhash; } else if (packet.has_ledgerseq()) ledger = theApp->getMasterLedger().getLedgerBySeq(packet.ledgerseq()); @@ -987,7 +992,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet) return; } - if ((!ledger) || (packet.has_ledgerseq() && (packet.ledgerseq()!=ledger->getLedgerSeq()))) + if ((!ledger) || (packet.has_ledgerseq() && (packet.ledgerseq() != ledger->getLedgerSeq()))) { punishPeer(PP_UNKNOWN_REQUEST); Log(lsWARNING) << "Can't find the ledger they want"; diff --git a/src/newcoin.proto b/src/newcoin.proto index 79f517468f..2426f16ece 100644 --- a/src/newcoin.proto +++ b/src/newcoin.proto @@ -107,8 +107,9 @@ message TMProposeSet { required bytes nodePubKey = 3; required uint32 closeTime = 4; required bytes signature = 5; // signature of above fields - repeated bytes addedTransactions = 6; // not required if number is large - repeated bytes removedTransactions = 7; // not required if number is large + optional bytes previousledger = 6; + repeated bytes addedTransactions = 10; // not required if number is large + repeated bytes removedTransactions = 11; // not required if number is large } enum TxSetStatus {