Merge branch 'master' of github.com:jedmccaleb/NewCoin

This commit is contained in:
Arthur Britto
2012-11-15 11:26:16 -08:00
11 changed files with 169 additions and 63 deletions

View File

@@ -17,13 +17,15 @@
enum JobType
{ // must be in priority order, low to high
jtINVALID,
jtVALIDATION_ut,
jtTRANSACTION,
jtPROPOSAL_ut,
jtVALIDATION_t,
jtTRANSACTION_l,
jtPROPOSAL_t,
jtADMIN,
jtVALIDATION_ut, // A validation from an untrusted source
jtCLIENTOP_ut, // A client operation from a non-local/untrusted source
jtTRANSACTION, // A transaction received from the network
jtPROPOSAL_ut, // A proposal from an untrusted source
jtCLIENTOP_t, // A client operation from a trusted source
jtVALIDATION_t, // A validation from a trusted source
jtTRANSACTION_l, // A local transaction
jtPROPOSAL_t, // A proposal from a trusted source
jtADMIN, // An administrative operation
jtDEATH, // job of death, used internally
};

View File

@@ -267,7 +267,7 @@ bool LCTransaction::updateVote(int percentTime, bool proposing)
LedgerConsensus::LedgerConsensus(const uint256& prevLCLHash, Ledger::ref previousLedger, uint32 closeTime)
: mState(lcsPRE_CLOSE), mCloseTime(closeTime), mPrevLedgerHash(prevLCLHash), mPreviousLedger(previousLedger),
mValPublic(theConfig.VALIDATION_PUB), mValPrivate(theConfig.VALIDATION_PRIV),
mValPublic(theConfig.VALIDATION_PUB), mValPrivate(theConfig.VALIDATION_PRIV), mConsensusFail(false),
mCurrentMSeconds(0), mClosePercent(0), mHaveCloseTimeConsensus(false),
mConsensusStartTime(boost::posix_time::microsec_clock::universal_time())
{
@@ -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 || !mValPublic.isValid() || !mValPrivate.isValid())
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<SerializedValidation>
(mPreviousLedger->getHash(), theApp->getOPs().getValidationTimeNC(), mValPublic, false);
v->setTrusted();
v->sign(signingHash, mValPrivate);
theApp->isNew(signingHash);
theApp->getValidations().addValidation(v);
std::vector<unsigned char> validation = v->getSigned();
ripple::TMValidation val;
val.set_validation(&validation[0], validation.size());
theApp->getConnectionPool().relayMessage(NULL,
boost::make_shared<PackedMessage>(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()
@@ -769,7 +800,7 @@ bool LedgerConsensus::haveConsensus(bool forReal)
cLog(lsDEBUG) << "Checking for TX consensus: agree=" << agree << ", disagree=" << disagree;
return ContinuousLedgerTiming::haveConsensus(mPreviousProposers, agree + disagree, agree, currentValidations,
mPreviousMSeconds, mCurrentMSeconds, forReal);
mPreviousMSeconds, mCurrentMSeconds, forReal, mConsensusFail);
}
SHAMap::pointer LedgerConsensus::getTransactionTree(const uint256& hash, bool doAcquire)
@@ -1193,15 +1224,17 @@ void LedgerConsensus::accept(SHAMap::ref set)
}
statusChange(ripple::neACCEPTED_LEDGER, *newLCL);
if (mValidating)
if (mValidating && !mConsensusFail)
{
uint256 signingHash;
SerializedValidation::pointer v = boost::make_shared<SerializedValidation>
(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<unsigned char> validation = v->getSigned();
ripple::TMValidation val;
val.set_validation(&validation[0], validation.size());
@@ -1238,7 +1271,7 @@ void LedgerConsensus::accept(SHAMap::ref set)
cLog(lsINFO) << "Applying transactions from current ledger";
applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(), newOL, newLCL,
failedTransactions, true);
theApp->getMasterLedger().pushLedger(newLCL, newOL, true);
theApp->getMasterLedger().pushLedger(newLCL, newOL, !mConsensusFail);
mNewLedgerHash = newLCL->getHash();
mState = lcsACCEPTED;
sl.unlock();

View File

@@ -91,7 +91,7 @@ protected:
LedgerAcquire::pointer mAcquiringLedger;
LedgerProposal::pointer mOurPosition;
RippleAddress mValPublic, mValPrivate;
bool mProposing, mValidating, mHaveCorrectLCL;
bool mProposing, mValidating, mHaveCorrectLCL, mConsensusFail;
int mCurrentMSeconds, mClosePercent, mCloseResolution;
bool mHaveCloseTimeConsensus;
@@ -148,6 +148,7 @@ protected:
void playbackProposals();
int getThreshold();
void closeLedger();
void checkOurValidation();
void beginAccept(bool synchronous);
void endConsensus();

View File

@@ -63,7 +63,8 @@ bool ContinuousLedgerTiming::haveConsensus(
int currentFinished, // proposers who have validated a ledger after this one
int previousAgreeTime, // how long it took to agree on the last ledger
int currentAgreeTime, // how long we've been trying to agree
bool forReal) // deciding whether to stop consensus process
bool forReal, // deciding whether to stop consensus process
bool& failed) // we can't reach a consensus
{
cLog(lsTRACE) << boost::str(boost::format("CLC::haveConsensus: prop=%d/%d agree=%d validated=%d time=%d/%d%s") %
currentProposers % previousProposers % currentAgree % currentFinished % currentAgreeTime % previousAgreeTime %
@@ -85,13 +86,15 @@ bool ContinuousLedgerTiming::haveConsensus(
if (((currentAgree * 100 + 100) / (currentProposers + 1)) > 80)
{
tLog(forReal, lsINFO) << "normal consensus";
failed = false;
return true;
}
// If 50% of the nodes on your UNL have moved on, you should declare consensus
if (((currentFinished * 100) / (currentProposers + 1)) > 50)
// If 80% of the nodes on your UNL have moved on, you should declare consensus
if (((currentFinished * 100) / (currentProposers + 1)) > 80)
{
tLog(forReal, lsWARNING) << "We see no consensus, but 50% of nodes have moved on";
tLog(forReal, lsWARNING) << "We see no consensus, but 80% of nodes have moved on";
failed = true;
return true;
}

View File

@@ -66,7 +66,7 @@ public:
int previousProposers, int currentProposers,
int currentAgree, int currentClosed,
int previousAgreeTime, int currentAgreeTime,
bool forReal);
bool forReal, bool& failed);
static int getNextLedgerTimeResolution(int previousResolution, bool previousAgree, int ledgerSeq);
};

View File

@@ -85,6 +85,8 @@ protected:
uint256 mLastCloseHash;
uint32 mLastCloseTime;
uint32 mLastValidationTime;
SerializedValidation::pointer mLastValidation;
// XXX Split into more locks.
boost::interprocess::interprocess_upgradable_mutex mMonitorLock;
@@ -131,8 +133,10 @@ 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; }
SLE::pointer getSLE(Ledger::pointer lpLedger, const uint256& uHash) { return lpLedger->getSLE(uHash); }

View File

@@ -115,7 +115,7 @@ uint160 RippleAddress::getNodeID() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - getNodeID");
case VER_NODE_PUBLIC:
// Note, we are encoding the left.
@@ -129,7 +129,7 @@ const std::vector<unsigned char>& RippleAddress::getNodePublic() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - getNodePublic");
case VER_NODE_PUBLIC:
return vchData;
@@ -143,7 +143,7 @@ std::string RippleAddress::humanNodePublic() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - humanNodePublic");
case VER_NODE_PUBLIC:
return ToString();
@@ -209,7 +209,7 @@ const std::vector<unsigned char>& RippleAddress::getNodePrivateData() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - getNodePrivateData");
case VER_NODE_PRIVATE:
return vchData;
@@ -223,7 +223,7 @@ uint256 RippleAddress::getNodePrivate() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source = getNodePrivate");
case VER_NODE_PRIVATE:
return uint256(vchData);
@@ -237,7 +237,7 @@ std::string RippleAddress::humanNodePrivate() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - humanNodePrivate");
case VER_NODE_PRIVATE:
return ToString();
@@ -279,7 +279,7 @@ uint160 RippleAddress::getAccountID() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - getAccountID");
case VER_ACCOUNT_ID:
return uint160(vchData);
@@ -297,7 +297,7 @@ std::string RippleAddress::humanAccountID() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - humanAccountID");
case VER_ACCOUNT_ID:
return ToString();
@@ -353,7 +353,7 @@ const std::vector<unsigned char>& RippleAddress::getAccountPublic() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - getAccountPublic");
case VER_ACCOUNT_ID:
throw std::runtime_error("public not available from account id");
@@ -371,7 +371,7 @@ std::string RippleAddress::humanAccountPublic() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - humanAccountPublic");
case VER_ACCOUNT_ID:
throw std::runtime_error("public not available from account id");
@@ -446,7 +446,7 @@ uint256 RippleAddress::getAccountPrivate() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - getAccountPrivate");
case VER_ACCOUNT_PRIVATE:
return uint256(vchData);
@@ -460,7 +460,7 @@ std::string RippleAddress::humanAccountPrivate() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - humanAccountPrivate");
case VER_ACCOUNT_PRIVATE:
return ToString();
@@ -606,7 +606,7 @@ BIGNUM* RippleAddress::getGeneratorBN() const
{ // returns the public generator
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - getGeneratorBN");
case VER_FAMILY_GENERATOR:
// Do nothing.
@@ -625,7 +625,7 @@ const std::vector<unsigned char>& RippleAddress::getGenerator() const
{ // returns the public generator
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - getGenerator");
case VER_FAMILY_GENERATOR:
// Do nothing.
@@ -640,7 +640,7 @@ std::string RippleAddress::humanGenerator() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - humanGenerator");
case VER_FAMILY_GENERATOR:
return ToString();
@@ -678,7 +678,7 @@ uint128 RippleAddress::getSeed() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - getSeed");
case VER_FAMILY_SEED:
return uint128(vchData);
@@ -692,7 +692,7 @@ std::string RippleAddress::humanSeed1751() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - humanSeed1751");
case VER_FAMILY_SEED:
{
@@ -719,7 +719,7 @@ std::string RippleAddress::humanSeed() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
throw std::runtime_error("unset source - humanSeed");
case VER_FAMILY_SEED:
return ToString();

View File

@@ -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<unsigned char> 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 (...)
{

View File

@@ -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<unsigned char> getSigned() const;
std::vector<unsigned char> getSignature() const;
void sign(uint256& signingHash, const RippleAddress& raPrivate);
void sign(const RippleAddress& raPrivate);
// The validation this replaced
const uint256& getPreviousHash() { return mPreviousHash; }

View File

@@ -97,12 +97,12 @@ void ValidationCollection::getValidationCount(const uint256& ledger, bool curren
uint32 now = theApp->getOPs().getNetworkTimeNC();
if (set)
{
for (ValidationSet::iterator vit = set->begin(), end = set->end(); vit != end; ++vit)
BOOST_FOREACH(u160_val_pair& it, *set)
{
bool isTrusted = vit->second->isTrusted();
bool isTrusted = it.second->isTrusted();
if (isTrusted && currentOnly)
{
uint32 closeTime = vit->second->getSignTime();
uint32 closeTime = it.second->getSignTime();
if ((now < (closeTime - LEDGER_EARLY_INTERVAL)) || (now > (closeTime + LEDGER_VAL_INTERVAL)))
isTrusted = false;
else
@@ -119,6 +119,28 @@ void ValidationCollection::getValidationCount(const uint256& ledger, bool curren
cLog(lsTRACE) << "VC: " << ledger << "t:" << trusted << " u:" << untrusted;
}
void ValidationCollection::getValidationTypes(const uint256& ledger, int& full, int& partial)
{
full = partial = 0;
boost::mutex::scoped_lock sl(mValidationLock);
VSpointer set = findSet(ledger);
if (set)
{
BOOST_FOREACH(u160_val_pair& it, *set)
{
if (it.second->isTrusted())
{
if (it.second->isFull())
++full;
else
++partial;
}
}
}
cLog(lsTRACE) << "VC: " << ledger << "f:" << full << " p:" << partial;
}
int ValidationCollection::getTrustedValidationCount(const uint256& ledger)
{
int trusted = 0;
@@ -126,9 +148,9 @@ int ValidationCollection::getTrustedValidationCount(const uint256& ledger)
VSpointer set = findSet(ledger);
if (set)
{
for (ValidationSet::iterator vit = set->begin(), end = set->end(); vit != end; ++vit)
BOOST_FOREACH(u160_val_pair& it, *set)
{
if (vit->second->isTrusted())
if (it.second->isTrusted())
++trusted;
}
}
@@ -167,6 +189,36 @@ int ValidationCollection::getLoadRatio(bool overLoaded)
return (goodNodes * 100) / (goodNodes + badNodes);
}
std::list<SerializedValidation::pointer> ValidationCollection::getCurrentTrustedValidations()
{
uint32 cutoff = theApp->getOPs().getNetworkTimeNC() - LEDGER_VAL_INTERVAL;
std::list<SerializedValidation::pointer> ret;
boost::mutex::scoped_lock sl(mValidationLock);
boost::unordered_map<uint160, SerializedValidation::pointer>::iterator it = mCurrentValidations.begin();
while (it != mCurrentValidations.end())
{
if (!it->second) // contains no record
it = mCurrentValidations.erase(it);
else if (it->second->getSignTime() < cutoff)
{ // contains a stale record
mStaleValidations.push_back(it->second);
it->second.reset();
condWrite();
it = mCurrentValidations.erase(it);
}
else
{ // contains a live record
if (it->second->isTrusted())
ret.push_back(it->second);
++it;
}
}
return ret;
}
boost::unordered_map<uint256, currentValidationCount>
ValidationCollection::getCurrentValidations(uint256 currentLedger)
{

View File

@@ -38,6 +38,7 @@ public:
bool addValidation(const SerializedValidation::pointer&);
ValidationSet getValidations(const uint256& ledger);
void getValidationCount(const uint256& ledger, bool currentOnly, int& trusted, int& untrusted);
void getValidationTypes(const uint256& ledger, int& full, int& partial);
int getTrustedValidationCount(const uint256& ledger);
@@ -45,6 +46,7 @@ public:
int getLoadRatio(bool overLoaded);
boost::unordered_map<uint256, currentValidationCount> getCurrentValidations(uint256 currentLedger);
std::list<SerializedValidation::pointer> getCurrentTrustedValidations();
void flush();
void sweep() { mValidations.sweep(); }