Support for proposals that contain the previous ledger hash.

A fix for ledger acquires not stopping when they should.
This commit is contained in:
JoelKatz
2012-09-03 06:03:09 -07:00
parent 7d6259d8b3
commit cc4827559c
5 changed files with 43 additions and 14 deletions

View File

@@ -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);
}
}
}

View File

@@ -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; }

View File

@@ -518,7 +518,8 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& 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<LedgerProposal>(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<LedgerProposal>(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);
}

View File

@@ -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<PackedMessage>(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";

View File

@@ -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 {