Be paranoid about ledger compatibility:

* Consider ledgers incompatible based on last valid ledger
* Test against even ledgers not acquired yet
* Don't validate an incompatible ledger
* Don't switch to an incompatible ledger
* Protect against an unreasonably small quorum
This commit is contained in:
JoelKatz
2015-07-28 15:14:51 -07:00
committed by Nik Bougalis
parent 38c6083a2f
commit 0bb570a36d
6 changed files with 183 additions and 11 deletions

View File

@@ -307,6 +307,99 @@ rippleTransferRate (ReadView const& view,
: rippleTransferRate(view, issuer);
}
bool
areCompatible (ReadView const& validLedger, ReadView const& testLedger,
beast::Journal::Stream& s, const char* reason)
{
bool ret = true;
if (validLedger.info().seq < testLedger.info().seq)
{
// valid -> ... -> test
auto hash = hashOfSeq (testLedger, validLedger.info().seq,
beast::Journal());
if (hash && (*hash != validLedger.info().hash))
{
JLOG(s) << reason << " incompatible with valid ledger";
JLOG(s) << "Hash(VSeq): " << to_string (*hash);
ret = false;
}
}
else if (validLedger.info().seq > testLedger.info().seq)
{
// test -> ... -> valid
auto hash = hashOfSeq (validLedger, testLedger.info().seq,
beast::Journal());
if (hash && (*hash != testLedger.info().hash))
{
JLOG(s) << reason << " incompatible preceding ledger";
JLOG(s) << "Hash(NSeq): " << to_string (*hash);
ret = false;
}
}
else if ((validLedger.info().seq == testLedger.info().seq) &&
(validLedger.info().hash != testLedger.info().hash))
{
// Same sequence number, different hash
JLOG(s) << reason << " incompatible ledger";
ret = false;
}
if (! ret)
{
JLOG(s) << "Val: " << validLedger.info().seq <<
" " << to_string (validLedger.info().hash);
JLOG(s) << "New: " << testLedger.info().seq <<
" " << to_string (testLedger.info().hash);
}
return ret;
}
bool areCompatible (uint256 const& validHash, LedgerIndex validIndex,
ReadView const& testLedger, beast::Journal::Stream& s, const char* reason)
{
bool ret = true;
if (testLedger.info().seq > validIndex)
{
// Ledger we are testing follows last valid ledger
auto hash = hashOfSeq (testLedger, validIndex,
beast::Journal());
if (hash && (*hash != validHash))
{
JLOG(s) << reason << " incompatible following ledger";
JLOG(s) << "Hash(VSeq): " << to_string (*hash);
ret = false;
}
}
else if ((validIndex == testLedger.info().seq) &&
(testLedger.info().hash != validHash))
{
JLOG(s) << reason << " incompatible ledger";
ret = false;
}
if (! ret)
{
JLOG(s) << "Val: " << validIndex <<
" " << to_string (validHash);
JLOG(s) << "New: " << testLedger.info().seq <<
" " << to_string (testLedger.info().hash);
}
return ret;
}
bool
dirIsEmpty (ReadView const& view,
Keylet const& k)