diff --git a/src/cpp/ripple/LedgerConsensus.cpp b/src/cpp/ripple/LedgerConsensus.cpp index e5a877b3b..e537abb16 100644 --- a/src/cpp/ripple/LedgerConsensus.cpp +++ b/src/cpp/ripple/LedgerConsensus.cpp @@ -305,6 +305,36 @@ LedgerConsensus::LedgerConsensus(const uint256& prevLCLHash, Ledger::ref previou } } +void LedgerConsensus::checkOurValidation() +{ // This only covers some cases - Fix for the case where we can't ever acquire the consensus ledger + if (!mHaveCorrectLCL) + return; + + SerializedValidation::pointer lastVal = theApp->getOPs().getLastValidation(); + if (lastVal) + { + if (lastVal->getFieldU32(sfLedgerSequence) == mPreviousLedger->getLedgerSeq()) + return; + if (lastVal->getLedgerHash() == mPrevLedgerHash) + return; + } + + uint256 signingHash; + SerializedValidation::pointer v = boost::make_shared + (mPreviousLedger->getHash(), theApp->getOPs().getValidationTimeNC(), mValPublic, false); + v->setTrusted(); + v->sign(signingHash, mValPrivate); + theApp->isNew(signingHash); + theApp->getValidations().addValidation(v); + std::vector validation = v->getSigned(); + ripple::TMValidation val; + val.set_validation(&validation[0], validation.size()); + theApp->getConnectionPool().relayMessage(NULL, + boost::make_shared(val, ripple::mtVALIDATION)); + theApp->getOPs().setLastValidation(v); + cLog(lsWARNING) << "Sending partial validation"; +} + void LedgerConsensus::checkLCL() { uint256 netLgr = mPrevLedgerHash; @@ -575,12 +605,13 @@ void LedgerConsensus::statePreClose() void LedgerConsensus::closeLedger() { - mState = lcsESTABLISH; - mConsensusStartTime = boost::posix_time::microsec_clock::universal_time(); - mCloseTime = theApp->getOPs().getCloseTimeNC(); - theApp->getOPs().setLastCloseTime(mCloseTime); - statusChange(ripple::neCLOSING_LEDGER, *mPreviousLedger); - takeInitialPosition(*theApp->getMasterLedger().closeLedger(true)); + checkOurValidation(); + mState = lcsESTABLISH; + mConsensusStartTime = boost::posix_time::microsec_clock::universal_time(); + mCloseTime = theApp->getOPs().getCloseTimeNC(); + theApp->getOPs().setLastCloseTime(mCloseTime); + statusChange(ripple::neCLOSING_LEDGER, *mPreviousLedger); + takeInitialPosition(*theApp->getMasterLedger().closeLedger(true)); } void LedgerConsensus::stateEstablish() @@ -1197,11 +1228,13 @@ void LedgerConsensus::accept(SHAMap::ref set) { uint256 signingHash; SerializedValidation::pointer v = boost::make_shared - (newLCLHash, theApp->getOPs().getValidationTimeNC(), mValPublic, mValPrivate, - mProposing, boost::ref(signingHash)); + (newLCLHash, theApp->getOPs().getValidationTimeNC(), mValPublic, mProposing); + v->setFieldU32(sfLedgerSequence, newLCL->getLedgerSeq()); + v->sign(signingHash, mValPrivate); v->setTrusted(); theApp->isNew(signingHash); // suppress it if we receive it theApp->getValidations().addValidation(v); + theApp->getOPs().setLastValidation(v); std::vector validation = v->getSigned(); ripple::TMValidation val; val.set_validation(&validation[0], validation.size()); diff --git a/src/cpp/ripple/LedgerConsensus.h b/src/cpp/ripple/LedgerConsensus.h index 064d5800c..9f16e9df8 100644 --- a/src/cpp/ripple/LedgerConsensus.h +++ b/src/cpp/ripple/LedgerConsensus.h @@ -148,6 +148,7 @@ protected: void playbackProposals(); int getThreshold(); void closeLedger(); + void checkOurValidation(); void beginAccept(bool synchronous); void endConsensus(); diff --git a/src/cpp/ripple/NetworkOPs.h b/src/cpp/ripple/NetworkOPs.h index 1280482c1..56f6f428c 100644 --- a/src/cpp/ripple/NetworkOPs.h +++ b/src/cpp/ripple/NetworkOPs.h @@ -84,8 +84,8 @@ protected: int mLastCloseProposers, mLastCloseConvergeTime; uint256 mLastCloseHash; uint32 mLastCloseTime; - SerializedValidation::pointer mLastValidation; uint32 mLastValidationTime; + SerializedValidation::pointer mLastValidation; // XXX Split into more locks. @@ -133,8 +133,7 @@ public: Ledger::pointer getLedgerByHash(const uint256& hash) { return mLedgerMaster->getLedgerByHash(hash); } Ledger::pointer getLedgerBySeq(const uint32 seq) { return mLedgerMaster->getLedgerBySeq(seq); } - uint256 getClosedLedgerHash() - { return mLedgerMaster->getClosedLedger()->getHash(); } + uint256 getClosedLedgerHash() { return mLedgerMaster->getClosedLedger()->getHash(); } SerializedValidation::ref getLastValidation() { return mLastValidation; } void setLastValidation(SerializedValidation::ref v) { mLastValidation = v; } diff --git a/src/cpp/ripple/SerializedValidation.cpp b/src/cpp/ripple/SerializedValidation.cpp index 75d8249ab..c344e1002 100644 --- a/src/cpp/ripple/SerializedValidation.cpp +++ b/src/cpp/ripple/SerializedValidation.cpp @@ -39,26 +39,32 @@ SerializedValidation::SerializedValidation(SerializerIterator& sit, bool checkSi } SerializedValidation::SerializedValidation(const uint256& ledgerHash, uint32 signTime, - const RippleAddress& naPub, const RippleAddress& naPriv, bool isFull, uint256& signingHash) + const RippleAddress& raPub, bool isFull) : STObject(sValidationFormat, sfValidation), mTrusted(false) -{ +{ // Does not sign setFieldH256(sfLedgerHash, ledgerHash); setFieldU32(sfSigningTime, signTime); - setFieldVL(sfSigningPubKey, naPub.getNodePublic()); - mNodeID = naPub.getNodeID(); + setFieldVL(sfSigningPubKey, raPub.getNodePublic()); + mNodeID = raPub.getNodeID(); assert(mNodeID.isNonZero()); if (!isFull) setFlag(sFullFlag); +} +void SerializedValidation::sign(const RippleAddress& raPriv) +{ + uint256 signingHash; + sign(signingHash, raPriv); +} + +void SerializedValidation::sign(uint256& signingHash, const RippleAddress& raPriv) +{ signingHash = getSigningHash(); std::vector signature; - naPriv.signNodePrivate(signingHash, signature); + raPriv.signNodePrivate(signingHash, signature); setFieldVL(sfSignature, signature); - // XXX Check if this can fail. - // if (!RippleAddress::createNodePrivate(naSeed).signNodePrivate(getSigningHash(), mSignature.peekValue())) - // throw std::runtime_error("Unable to sign validation"); } uint256 SerializedValidation::getSigningHash() const @@ -90,8 +96,8 @@ bool SerializedValidation::isValid(const uint256& signingHash) const { try { - RippleAddress naPublicKey = RippleAddress::createNodePublic(getFieldVL(sfSigningPubKey)); - return naPublicKey.isValid() && naPublicKey.verifyNodePublic(signingHash, getFieldVL(sfSignature)); + RippleAddress raPublicKey = RippleAddress::createNodePublic(getFieldVL(sfSigningPubKey)); + return raPublicKey.isValid() && raPublicKey.verifyNodePublic(signingHash, getFieldVL(sfSignature)); } catch (...) { diff --git a/src/cpp/ripple/SerializedValidation.h b/src/cpp/ripple/SerializedValidation.h index 57b3b42a8..72e1fc50e 100644 --- a/src/cpp/ripple/SerializedValidation.h +++ b/src/cpp/ripple/SerializedValidation.h @@ -24,13 +24,14 @@ public: // These throw if the object is not valid SerializedValidation(SerializerIterator& sit, bool checkSignature = true); - SerializedValidation(const uint256& ledgerHash, uint32 signTime, const RippleAddress& naPub, - const RippleAddress& naPriv, bool isFull, uint256& signingHash); + + // Does not sign the validation + SerializedValidation(const uint256& ledgerHash, uint32 signTime, const RippleAddress& raPub, bool isFull); uint256 getLedgerHash() const; uint32 getSignTime() const; uint32 getFlags() const; - RippleAddress getSignerPublic() const; + RippleAddress getSignerPublic() const; uint160 getNodeID() const { return mNodeID; } bool isValid() const; bool isFull() const; @@ -41,6 +42,8 @@ public: void setTrusted() { mTrusted = true; } std::vector getSigned() const; std::vector getSignature() const; + void sign(uint256& signingHash, const RippleAddress& raPrivate); + void sign(const RippleAddress& raPrivate); // The validation this replaced const uint256& getPreviousHash() { return mPreviousHash; }