diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index a2eff8f8aa..400244ce1e 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -163,6 +163,8 @@ void LedgerConsensus::closeTime(Ledger::pointer& current) void LedgerConsensus::mapComplete(const uint256& hash, SHAMap::pointer map) { + mAcquiring.erase(hash); + if (!map) { // this is an invalid/corrupt map mComplete[hash] = map; @@ -252,6 +254,7 @@ int LedgerConsensus::timerEntry() bool changes = false; SHAMap::pointer ourPosition; + std::vector addedTx, removedTx; for(boost::unordered_map::iterator it = mDisputes.begin(), end = mDisputes.end(); it != end; ++it) @@ -264,16 +267,26 @@ int LedgerConsensus::timerEntry() changes = true; } if (it->second->getOurPosition()) // now a yes + { ourPosition->addItem(SHAMapItem(it->first, it->second->peekTransaction()), true); + addedTx.push_back(it->first); + } else // now a no + { ourPosition->delItem(it->first); + removedTx.push_back(it->first); + } } } if (changes) { - // broadcast IHAVE - // broadcast new proposal + uint256 newHash = ourPosition->getHash(); + mOurPosition->changePosition(newHash); + propose(addedTx, removedTx); + std::vector hashes; + hashes.push_back(newHash); + sendHaveTxSet(hashes); } } return 1; @@ -321,6 +334,20 @@ void LedgerConsensus::startAcquiring(TransactionAcquire::pointer acquire) } } +void LedgerConsensus::propose(const std::vector& added, const std::vector& removed) +{ + newcoin::TMProposeSet prop; + prop.set_currenttxhash(mOurPosition->getCurrentHash().begin(), 256 / 8); + prop.set_prevclosedhash(mOurPosition->getPrevLedger().begin(), 256 / 8); + prop.set_proposeseq(mOurPosition->getProposeSeq()); + + std::vector pubKey = mOurPosition->getPubKey(); + std::vector sig = mOurPosition->sign(); + prop.set_nodepubkey(&pubKey[0], pubKey.size()); + prop.set_signature(&sig[0], sig.size()); + theApp->getConnectionPool().relayMessage(NULL, boost::make_shared(prop, newcoin::mtPROPOSE_LEDGER)); +} + void LedgerConsensus::addDisputedTransaction(const uint256& txID, const std::vector& tx) { boost::unordered_map::iterator it = mDisputes.find(txID); @@ -350,6 +377,13 @@ void LedgerConsensus::addDisputedTransaction(const uint256& txID, const std::vec bool LedgerConsensus::peerPosition(LedgerProposal::pointer newPosition) { + if (newPosition->getPrevLedger() != mPreviousLedger->getHash()) + { +#ifdef DEBUG + std::cerr << "Peer sends proposal with wrong previous ledger" << std::endl; +#endif + return false; + } LedgerProposal::pointer& currentPosition = mPeerPositions[newPosition->getPeerID()]; if (currentPosition) { diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h index dc15a3851b..9b3b6d4be8 100644 --- a/src/LedgerConsensus.h +++ b/src/LedgerConsensus.h @@ -99,6 +99,7 @@ protected: void addDisputedTransaction(const uint256&, const std::vector& transaction); void adjustCount(SHAMap::pointer map, const std::vector& peers); + void propose(const std::vector& addedTx, const std::vector& removedTx); void addPosition(LedgerProposal&, bool ours); void removePosition(LedgerProposal&, bool ours); diff --git a/src/LedgerProposal.cpp b/src/LedgerProposal.cpp index 0c855d5d26..9c78e0afb7 100644 --- a/src/LedgerProposal.cpp +++ b/src/LedgerProposal.cpp @@ -6,9 +6,8 @@ #include "key.h" #include "Application.h" -LedgerProposal::LedgerProposal(uint32 closingSeq, uint32 proposeSeq, const uint256& proposeTx, - const std::string& pubKey) : mCurrentHash(proposeTx), - mProposeSeq(proposeSeq), mKey(boost::make_shared()) +LedgerProposal::LedgerProposal(const uint256& pLgr, uint32 seq, const uint256& tx, const std::string& pubKey) : + mPreviousLedger(pLgr), mCurrentHash(tx), mProposeSeq(seq), mKey(boost::make_shared()) { if (!mKey->SetPubKey(pubKey)) throw std::runtime_error("Invalid public key in proposal"); @@ -23,13 +22,6 @@ LedgerProposal::LedgerProposal(CKey::pointer mPrivateKey, const uint256& prevLgr mPeerID = Serializer::getSHA512Half(mKey->GetPubKey()); } -LedgerProposal::LedgerProposal(LedgerProposal::pointer previous, const uint256& newp) : - mPeerID(previous->mPeerID), mPreviousLedger(previous->mPreviousLedger), - mCurrentHash(newp), mProposeSeq(previous->mProposeSeq + 1), mKey(previous->mKey) -{ - ; -} - uint256 LedgerProposal::getSigningHash() const { Serializer s(72); @@ -44,3 +36,17 @@ bool LedgerProposal::checkSign(const std::string& signature) { return mKey->Verify(getSigningHash(), signature); } + +void LedgerProposal::changePosition(const uint256& newPosition) +{ + mCurrentHash = newPosition; + ++mProposeSeq; +} + +std::vector LedgerProposal::sign(void) +{ + std::vector ret; + if (!mKey->Sign(getSigningHash(), ret)) + throw std::runtime_error("unable to sign proposal"); + return ret; +} \ No newline at end of file diff --git a/src/LedgerProposal.h b/src/LedgerProposal.h index f2e501aee9..961ba47244 100644 --- a/src/LedgerProposal.h +++ b/src/LedgerProposal.h @@ -16,7 +16,6 @@ protected: uint256 mPeerID, mPreviousLedger, mCurrentHash; uint32 mProposeSeq; CKey::pointer mKey; -// std::vector mAddedTx, mRemovedTx; static const uint32 sProposeMagic = 0x50525000; // PRP @@ -25,14 +24,11 @@ public: typedef boost::shared_ptr pointer; // proposal from peer - LedgerProposal(uint32 closingSeq, uint32 proposeSeq, const uint256& propose, const std::string& pubKey); + LedgerProposal(const uint256& prevLgr, uint32 proposeSeq, const uint256& propose, const std::string& pubKey); // our first proposal LedgerProposal(CKey::pointer privateKey, const uint256& prevLedger, const uint256& position); - // our following proposals - LedgerProposal(LedgerProposal::pointer previous, const uint256& newPosition); - uint256 getSigningHash() const; bool checkSign(const std::string& signature); @@ -40,7 +36,10 @@ public: const uint256& getCurrentHash() const { return mCurrentHash; } const uint256& getPrevLedger() const { return mPreviousLedger; } uint32 getProposeSeq() const { return mProposeSeq; } + std::vector getPubKey() const { return mKey->GetPubKey(); } + std::vector sign(); + void changePosition(const uint256& newPosition); }; #endif diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h index 536dcbffd5..1d7c63dd69 100644 --- a/src/NetworkOPs.h +++ b/src/NetworkOPs.h @@ -77,7 +77,7 @@ public: const std::vector& myNode, std::list< std::vector >& newNodes); // ledger proposal/close functions - bool proposeLedger(uint32 closingSeq, uint32 proposeSeq, const uint256& proposeHash, + bool proposeLedger(const uint256& prevLgrHash, uint32 proposeSeq, const uint256& proposeHash, const std::string& pubKey, const std::string& signature); bool gotTXData(boost::shared_ptr peer, const uint256& hash, const std::list& nodeIDs, const std::list< std::vector >& nodeData); diff --git a/src/newcoin.proto b/src/newcoin.proto index c813d3457c..f1e453fc8c 100644 --- a/src/newcoin.proto +++ b/src/newcoin.proto @@ -102,7 +102,7 @@ message TMStatusChange { // Announce to the network our position on a closing ledger message TMProposeSet { - required uint32 closingSeq = 1; + required bytes prevClosedHash = 1; required uint32 proposeSeq = 2; required bytes currentTxHash = 3; // the hash of the ledger we are proposing required bytes nodePubKey = 4;