diff options
author | s_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b> | 2010-08-03 18:25:05 +0000 |
---|---|---|
committer | s_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b> | 2010-08-03 18:25:05 +0000 |
commit | 2c06be915de967494920bdbb3096bbb455ccf99f (patch) | |
tree | da4dca822bdb75d871ee8d652b4aa306e62bff20 | |
parent | 6ff5f718b6a67797b2b3bab8905d607ad216ee21 (diff) |
new safety feature displays a warning message and locks down RPC if it detects a problem that may require an upgrade
-- version 0.3.8
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@122 1a98c847-1fd6-4fd8-948a-caf3550aa51b
-rw-r--r-- | db.cpp | 13 | ||||
-rw-r--r-- | db.h | 2 | ||||
-rw-r--r-- | main.cpp | 60 | ||||
-rw-r--r-- | main.h | 13 | ||||
-rw-r--r-- | rpc.cpp | 4 | ||||
-rw-r--r-- | serialize.h | 2 | ||||
-rw-r--r-- | setup.nsi | 6 | ||||
-rw-r--r-- | ui.cpp | 15 |
8 files changed, 81 insertions, 34 deletions
@@ -342,6 +342,16 @@ bool CTxDB::WriteHashBestChain(uint256 hashBestChain) return Write(string("hashBestChain"), hashBestChain);
}
+bool CTxDB::ReadBestInvalidWork(CBigNum& bnBestInvalidWork)
+{
+ return Read(string("bnBestInvalidWork"), bnBestInvalidWork);
+}
+
+bool CTxDB::WriteBestInvalidWork(CBigNum bnBestInvalidWork)
+{
+ return Write(string("bnBestInvalidWork"), bnBestInvalidWork);
+}
+
CBlockIndex* InsertBlockIndex(uint256 hash)
{
if (hash == 0)
@@ -446,6 +456,9 @@ bool CTxDB::LoadBlockIndex() bnBestChainWork = pindexBest->bnChainWork;
printf("LoadBlockIndex(): hashBestChain=%s height=%d\n", hashBestChain.ToString().substr(0,16).c_str(), nBestHeight);
+ // Load bnBestInvalidWork, OK if it doesn't exist
+ ReadBestInvalidWork(bnBestInvalidWork);
+
return true;
}
@@ -280,6 +280,8 @@ public: bool EraseBlockIndex(uint256 hash);
bool ReadHashBestChain(uint256& hashBestChain);
bool WriteHashBestChain(uint256 hashBestChain);
+ bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork);
+ bool WriteBestInvalidWork(CBigNum bnBestInvalidWork);
bool LoadBlockIndex();
};
@@ -25,6 +25,7 @@ const uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6 CBlockIndex* pindexGenesisBlock = NULL;
int nBestHeight = -1;
CBigNum bnBestChainWork = 0;
+CBigNum bnBestInvalidWork = 0;
uint256 hashBestChain = 0;
CBlockIndex* pindexBest = NULL;
int64 nTimeBestReceived = 0;
@@ -794,12 +795,12 @@ uint256 GetOrphanRoot(const CBlock* pblock) return pblock->GetHash();
}
-int64 CBlock::GetBlockValue(int64 nFees) const
+int64 CBlock::GetBlockValue(int nHeight, int64 nFees) const
{
int64 nSubsidy = 50 * COIN;
// Subsidy is cut in half every 4 years
- nSubsidy >>= (nBestHeight / 210000);
+ nSubsidy >>= (nHeight / 210000);
return nSubsidy + nFees;
}
@@ -865,6 +866,28 @@ bool IsInitialBlockDownload() pindexBest->nTime < GetTime() - 24 * 60 * 60);
}
+bool IsLockdown()
+{
+ if (!pindexBest)
+ return false;
+ return (bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6);
+}
+
+void Lockdown(CBlockIndex* pindexNew)
+{
+ if (pindexNew->bnChainWork > bnBestInvalidWork)
+ {
+ bnBestInvalidWork = pindexNew->bnChainWork;
+ CTxDB().WriteBestInvalidWork(bnBestInvalidWork);
+ MainFrameRepaint();
+ }
+ printf("Lockdown: invalid block=%s height=%d work=%s\n", pindexNew->GetBlockHash().ToString().substr(0,22).c_str(), pindexNew->nHeight, pindexNew->bnChainWork.ToString().c_str());
+ printf("Lockdown: current best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,22).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());
+ printf("Lockdown: IsLockdown()=%d\n", (IsLockdown() ? 1 : 0));
+ if (IsLockdown())
+ printf("Lockdown: WARNING: Displayed transactions may not be correct! You may need to upgrade.\n");
+}
+
@@ -1086,7 +1109,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) return false;
}
- if (vtx[0].GetValueOut() > GetBlockValue(nFees))
+ if (vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees))
return false;
// Update block index on disk without changing it in memory.
@@ -1116,11 +1139,13 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) CBlockIndex* plonger = pindexNew;
while (pfork != plonger)
{
- if (!(pfork = pfork->pprev))
- return error("Reorganize() : pfork->pprev is null");
while (plonger->nHeight > pfork->nHeight)
if (!(plonger = plonger->pprev))
return error("Reorganize() : plonger->pprev is null");
+ if (pfork == plonger)
+ break;
+ if (!(pfork = pfork->pprev))
+ return error("Reorganize() : pfork->pprev is null");
}
// List of what to disconnect
@@ -1160,16 +1185,8 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) return error("Reorganize() : ReadFromDisk for connect failed");
if (!block.ConnectBlock(txdb, pindex))
{
- // Invalid block, delete the rest of this branch
+ // Invalid block
txdb.TxnAbort();
- for (int j = i; j < vConnect.size(); j++)
- {
- CBlockIndex* pindex = vConnect[j];
- pindex->EraseBlockFromDisk();
- txdb.EraseBlockIndex(pindex->GetBlockHash());
- mapBlockIndex.erase(pindex->GetBlockHash());
- delete pindex;
- }
return error("Reorganize() : ConnectBlock failed");
}
@@ -1227,12 +1244,12 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) pindexNew->bnChainWork = (pindexNew->pprev ? pindexNew->pprev->bnChainWork : 0) + pindexNew->GetBlockWork();
CTxDB txdb;
- txdb.TxnBegin();
txdb.WriteBlockIndex(CDiskBlockIndex(pindexNew));
// New best
if (pindexNew->bnChainWork > bnBestChainWork)
{
+ txdb.TxnBegin();
if (pindexGenesisBlock == NULL && hash == hashGenesisBlock)
{
pindexGenesisBlock = pindexNew;
@@ -1244,9 +1261,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash))
{
txdb.TxnAbort();
- pindexNew->EraseBlockFromDisk();
- mapBlockIndex.erase(pindexNew->GetBlockHash());
- delete pindexNew;
+ Lockdown(pindexNew);
return error("AddToBlockIndex() : ConnectBlock failed");
}
txdb.TxnCommit();
@@ -1262,9 +1277,11 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) if (!Reorganize(txdb, pindexNew))
{
txdb.TxnAbort();
+ Lockdown(pindexNew);
return error("AddToBlockIndex() : Reorganize failed");
}
}
+ txdb.TxnCommit();
// New best block
hashBestChain = hash;
@@ -1273,10 +1290,9 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) bnBestChainWork = pindexNew->bnChainWork;
nTimeBestReceived = GetTime();
nTransactionsUpdated++;
- printf("AddToBlockIndex: new best=%s height=%d\n", hashBestChain.ToString().substr(0,16).c_str(), nBestHeight);
+ printf("AddToBlockIndex: new best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,22).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());
}
- txdb.TxnCommit();
txdb.Close();
if (pindexNew == pindexBest)
@@ -1352,7 +1368,7 @@ bool CBlock::AcceptBlock() // Check that all transactions are finalized
foreach(const CTransaction& tx, vtx)
- if (!tx.IsFinal(nTime))
+ if (!tx.IsFinal(pindexPrev->nHeight+1, nTime))
return error("AcceptBlock() : contains a non-final transaction");
// Check proof of work
@@ -2648,7 +2664,7 @@ void BitcoinMiner() }
}
pblock->nBits = nBits;
- pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(nFees);
+ pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(pindexPrev->nHeight+1, nFees);
printf("Running BitcoinMiner with %d transactions in block\n", pblock->vtx.size());
@@ -33,6 +33,7 @@ extern const uint256 hashGenesisBlock; extern CBlockIndex* pindexGenesisBlock;
extern int nBestHeight;
extern CBigNum bnBestChainWork;
+extern CBigNum bnBestInvalidWork;
extern uint256 hashBestChain;
extern CBlockIndex* pindexBest;
extern unsigned int nTransactionsUpdated;
@@ -80,6 +81,7 @@ void GenerateBitcoins(bool fGenerate); void ThreadBitcoinMiner(void* parg);
void BitcoinMiner();
bool IsInitialBlockDownload();
+bool IsLockdown();
@@ -410,15 +412,16 @@ public: return SerializeHash(*this);
}
- bool IsFinal(int64 nBlockTime=0) const
+ bool IsFinal(int nBlockHeight=0, int64 nBlockTime=0) const
{
- // Time based nLockTime implemented in 0.1.6,
- // do not use time based until most 0.1.5 nodes have upgraded.
+ // Time based nLockTime implemented in 0.1.6
if (nLockTime == 0)
return true;
+ if (nBlockHeight == 0)
+ nBlockHeight = nBestHeight;
if (nBlockTime == 0)
nBlockTime = GetAdjustedTime();
- if (nLockTime < (nLockTime < 500000000 ? nBestHeight : nBlockTime))
+ if (nLockTime < (nLockTime < 500000000 ? nBlockHeight : nBlockTime))
return true;
foreach(const CTxIn& txin, vin)
if (!txin.IsFinal())
@@ -1046,7 +1049,7 @@ public: }
- int64 GetBlockValue(int64 nFees) const;
+ int64 GetBlockValue(int nHeight, int64 nFees) const;
bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);
bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex);
bool ReadFromDisk(const CBlockIndex* blockindex, bool fReadTransactions=true);
@@ -946,6 +946,10 @@ void ThreadRPCServer2(void* parg) printf("ThreadRPCServer method=%s\n", strMethod.c_str());
+ // Observe lockdown
+ if (IsLockdown() && strMethod != "help" && strMethod != "stop" && strMethod != "getgenerate" && strMethod != "setgenerate")
+ throw runtime_error("WARNING: Displayed transactions may not be correct! You may need to upgrade.");
+
// Execute
map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
if (mi == mapCallTable.end())
diff --git a/serialize.h b/serialize.h index 8f3e0601e3..77c1bc04b4 100644 --- a/serialize.h +++ b/serialize.h @@ -19,7 +19,7 @@ class CScript; class CDataStream;
class CAutoFile;
-static const int VERSION = 307;
+static const int VERSION = 308;
static const char* pszSubVer = "";
@@ -7,7 +7,7 @@ RequestExecutionLevel highest # General Symbol Definitions
!define REGKEY "SOFTWARE\$(^Name)"
-!define VERSION 0.3.7
+!define VERSION 0.3.8
!define COMPANY "Bitcoin project"
!define URL http://www.bitcoin.org/
@@ -42,12 +42,12 @@ Var StartMenuGroup !insertmacro MUI_LANGUAGE English
# Installer attributes
-OutFile bitcoin-0.3.7-win32-setup.exe
+OutFile bitcoin-0.3.8-win32-setup.exe
InstallDir $PROGRAMFILES\Bitcoin
CRCCheck on
XPStyle on
ShowInstDetails show
-VIProductVersion 0.3.7.0
+VIProductVersion 0.3.8.0
VIAddVersionKey ProductName Bitcoin
VIAddVersionKey ProductVersion "${VERSION}"
VIAddVersionKey CompanyName "${COMPANY}"
@@ -196,6 +196,8 @@ bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* pa void CalledSetStatusBar(const string& strText, int nField)
{
+ if (nField == 0 && IsLockdown())
+ return;
if (pframeMain && pframeMain->m_statusBar)
pframeMain->m_statusBar->SetStatusText(strText, nField);
}
@@ -376,7 +378,7 @@ void CMainFrame::OnIconize(wxIconizeEvent& event) // to get rid of the deprecated warning. Just ignore it.
if (!event.Iconized())
fClosedToTray = false;
-#ifdef __WXGTK__
+#if defined(__WXGTK__) || defined(__WXMAC_OSX__)
if (mapArgs.count("-minimizetotray")) {
#endif
// The tray icon sometimes disappears on ubuntu karmic
@@ -1011,6 +1013,13 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event) RefreshStatusColumn();
// Update status bar
+ static bool fPrevLockdown;
+ if (IsLockdown())
+ m_statusBar->SetStatusText(string(" ") + _("WARNING: Displayed transactions may not be correct! You may need to upgrade."), 0);
+ else if (fPrevLockdown)
+ m_statusBar->SetStatusText("", 0);
+ fPrevLockdown = IsLockdown();
+
string strGen = "";
if (fGenerateBitcoins)
strGen = _(" Generating");
@@ -1598,7 +1607,7 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent) //m_listBox->Append(_("Test 2"));
m_listBox->SetSelection(0);
SelectPage(0);
-#ifdef __WXGTK__
+#if defined(__WXGTK__) || defined(__WXMAC_OSX__)
m_checkBoxStartOnSystemStartup->SetLabel(_("&Start Bitcoin on window system startup"));
if (!mapArgs.count("-minimizetotray"))
{
@@ -2697,7 +2706,7 @@ void CreateMainWindow() pframeMain = new CMainFrame(NULL);
if (mapArgs.count("-min"))
pframeMain->Iconize(true);
-#ifdef __WXGTK__
+#if defined(__WXGTK__) || defined(__WXMAC_OSX__)
if (!mapArgs.count("-minimizetotray"))
fMinimizeToTray = false;
#endif
|