alert system

-- version 0.3.11

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@142 1a98c847-1fd6-4fd8-948a-caf3550aa51b
This commit is contained in:
s_nakamoto 2010-08-25 00:05:37 +00:00
parent 2201a0808e
commit 401926283a
8 changed files with 409 additions and 86 deletions

200
main.cpp
View file

@ -898,14 +898,7 @@ bool IsInitialBlockDownload()
pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60); pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60);
} }
bool IsLockdown() void InvalidChainFound(CBlockIndex* pindexNew)
{
if (!pindexBest)
return false;
return (bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6);
}
void Lockdown(CBlockIndex* pindexNew)
{ {
if (pindexNew->bnChainWork > bnBestInvalidWork) if (pindexNew->bnChainWork > bnBestInvalidWork)
{ {
@ -913,11 +906,10 @@ void Lockdown(CBlockIndex* pindexNew)
CTxDB().WriteBestInvalidWork(bnBestInvalidWork); CTxDB().WriteBestInvalidWork(bnBestInvalidWork);
MainFrameRepaint(); MainFrameRepaint();
} }
printf("Lockdown: invalid block=%s height=%d work=%s\n", pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight, pindexNew->bnChainWork.ToString().c_str()); printf("InvalidChainFound: invalid block=%s height=%d work=%s\n", pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight, pindexNew->bnChainWork.ToString().c_str());
printf("Lockdown: current best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str()); printf("InvalidChainFound: current best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());
printf("Lockdown: IsLockdown()=%d\n", (IsLockdown() ? 1 : 0)); if (pindexBest && bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6)
if (IsLockdown()) printf("InvalidChainFound: WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n");
printf("Lockdown: WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n");
} }
@ -927,6 +919,9 @@ void Lockdown(CBlockIndex* pindexNew)
bool CTransaction::DisconnectInputs(CTxDB& txdb) bool CTransaction::DisconnectInputs(CTxDB& txdb)
{ {
// Relinquish previous transactions' spent pointers // Relinquish previous transactions' spent pointers
@ -1282,7 +1277,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash)) if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash))
{ {
txdb.TxnAbort(); txdb.TxnAbort();
Lockdown(pindexNew); InvalidChainFound(pindexNew);
return error("SetBestChain() : ConnectBlock failed"); return error("SetBestChain() : ConnectBlock failed");
} }
txdb.TxnCommit(); txdb.TxnCommit();
@ -1298,7 +1293,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
if (!Reorganize(txdb, pindexNew)) if (!Reorganize(txdb, pindexNew))
{ {
txdb.TxnAbort(); txdb.TxnAbort();
Lockdown(pindexNew); InvalidChainFound(pindexNew);
return error("SetBestChain() : Reorganize failed"); return error("SetBestChain() : Reorganize failed");
} }
} }
@ -1571,16 +1566,16 @@ bool ScanMessageStart(Stream& s)
} }
} }
bool CheckDiskSpace(int64 nAdditionalBytes) bool CheckDiskSpace(uint64 nAdditionalBytes)
{ {
uint64 nFreeBytesAvailable = filesystem::space(GetDataDir()).available; uint64 nFreeBytesAvailable = filesystem::space(GetDataDir()).available;
// Check for 15MB because database could create another 10MB log file at any time // Check for 15MB because database could create another 10MB log file at any time
if (nFreeBytesAvailable < (int64)15000000 + nAdditionalBytes) if (nFreeBytesAvailable < (uint64)15000000 + nAdditionalBytes)
{ {
fShutdown = true; fShutdown = true;
string strMessage = _("Warning: Disk space is low "); string strMessage = _("Warning: Disk space is low ");
strWarning = strMessage; strMiscWarning = strMessage;
printf("*** %s\n", strMessage.c_str()); printf("*** %s\n", strMessage.c_str());
ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION); ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION);
CreateThread(Shutdown, NULL); CreateThread(Shutdown, NULL);
@ -1648,17 +1643,7 @@ bool LoadBlockIndex(bool fAllowNew)
if (!fAllowNew) if (!fAllowNew)
return false; return false;
// Genesis Block: // Genesis Block:
// GetHash() = 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
// hashMerkleRoot = 0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
// txNew.vin[0].scriptSig = 486604799 4 0x736B6E616220726F662074756F6C69616220646E6F63657320666F206B6E697262206E6F20726F6C6C65636E61684320393030322F6E614A2F33302073656D695420656854
// txNew.vout[0].nValue = 5000000000
// txNew.vout[0].scriptPubKey = 0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704 OP_CHECKSIG
// block.nVersion = 1
// block.nTime = 1231006505
// block.nBits = 0x1d00ffff
// block.nNonce = 2083236893
// CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1) // CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
// CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0) // CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
// CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73) // CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
@ -1672,9 +1657,7 @@ bool LoadBlockIndex(bool fAllowNew)
txNew.vout.resize(1); txNew.vout.resize(1);
txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
txNew.vout[0].nValue = 50 * COIN; txNew.vout[0].nValue = 50 * COIN;
CBigNum bnPubKey; txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
bnPubKey.SetHex("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704");
txNew.vout[0].scriptPubKey = CScript() << bnPubKey << OP_CHECKSIG;
CBlock block; CBlock block;
block.vtx.push_back(txNew); block.vtx.push_back(txNew);
block.hashPrevBlock = 0; block.hashPrevBlock = 0;
@ -1686,11 +1669,10 @@ bool LoadBlockIndex(bool fAllowNew)
//// debug print //// debug print
printf("%s\n", block.GetHash().ToString().c_str()); printf("%s\n", block.GetHash().ToString().c_str());
printf("%s\n", block.hashMerkleRoot.ToString().c_str());
printf("%s\n", hashGenesisBlock.ToString().c_str()); printf("%s\n", hashGenesisBlock.ToString().c_str());
txNew.vout[0].scriptPubKey.print(); printf("%s\n", block.hashMerkleRoot.ToString().c_str());
block.print();
assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
block.print();
assert(block.GetHash() == hashGenesisBlock); assert(block.GetHash() == hashGenesisBlock);
@ -1798,6 +1780,111 @@ void PrintBlockTree()
//////////////////////////////////////////////////////////////////////////////
//
// CAlert
//
map<uint256, CAlert> mapAlerts;
CCriticalSection cs_mapAlerts;
string GetWarnings(string strFor)
{
int nPriority = 0;
string strStatusBar;
string strRPC;
// Misc warnings like out of disk space and clock is wrong
if (strMiscWarning != "")
{
nPriority = 1000;
strStatusBar = strMiscWarning;
}
// Longer invalid proof-of-work chain
if (pindexBest && bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6)
{
nPriority = 2000;
strStatusBar = strRPC = "WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.";
}
// Alerts
CRITICAL_BLOCK(cs_mapAlerts)
{
foreach(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
{
const CAlert& alert = item.second;
if (alert.AppliesToMe() && alert.nPriority > nPriority)
{
nPriority = alert.nPriority;
strStatusBar = alert.strStatusBar;
strRPC = alert.strRPCError;
}
}
}
if (strFor == "statusbar")
return strStatusBar;
else if (strFor == "rpc")
return strRPC;
assert(("GetWarnings() : invalid parameter", false));
return "error";
}
bool CAlert::ProcessAlert()
{
if (!CheckSignature())
return false;
if (!IsInEffect())
return false;
CRITICAL_BLOCK(cs_mapAlerts)
{
// Cancel previous alerts
for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
{
const CAlert& alert = (*mi).second;
if (Cancels(alert))
{
printf("cancelling alert %d\n", alert.nID);
mapAlerts.erase(mi++);
}
else if (!alert.IsInEffect())
{
printf("expiring alert %d\n", alert.nID);
mapAlerts.erase(mi++);
}
else
mi++;
}
// Check if this alert has been cancelled
foreach(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
{
const CAlert& alert = item.second;
if (alert.Cancels(*this))
{
printf("alert already cancelled by %d\n", alert.nID);
return false;
}
}
// Add to mapAlerts
mapAlerts.insert(make_pair(GetHash(), *this));
}
printf("accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());
MainFrameRepaint();
return true;
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// Messages // Messages
@ -1827,7 +1914,7 @@ bool ProcessMessages(CNode* pfrom)
if (vRecv.empty()) if (vRecv.empty())
return true; return true;
//if (fDebug) //if (fDebug)
// printf("ProcessMessages(%d bytes)\n", vRecv.size()); // printf("ProcessMessages(%u bytes)\n", vRecv.size());
// //
// Message format // Message format
@ -1869,6 +1956,11 @@ bool ProcessMessages(CNode* pfrom)
// Message size // Message size
unsigned int nMessageSize = hdr.nMessageSize; unsigned int nMessageSize = hdr.nMessageSize;
if (nMessageSize > MAX_SIZE)
{
printf("ProcessMessage(%s, %u bytes) : nMessageSize > MAX_SIZE\n", strCommand.c_str(), nMessageSize);
continue;
}
if (nMessageSize > vRecv.size()) if (nMessageSize > vRecv.size())
{ {
// Rewind and wait for rest of message // Rewind and wait for rest of message
@ -1889,7 +1981,7 @@ bool ProcessMessages(CNode* pfrom)
memcpy(&nChecksum, &hash, sizeof(nChecksum)); memcpy(&nChecksum, &hash, sizeof(nChecksum));
if (nChecksum != hdr.nChecksum) if (nChecksum != hdr.nChecksum)
{ {
printf("ProcessMessage(%s, %d bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n", printf("ProcessMessage(%s, %u bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum); strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum);
continue; continue;
} }
@ -1906,15 +1998,15 @@ bool ProcessMessages(CNode* pfrom)
} }
catch (std::ios_base::failure& e) catch (std::ios_base::failure& e)
{ {
if (strstr(e.what(), "CDataStream::read() : end of data")) if (strstr(e.what(), "end of data"))
{ {
// Allow exceptions from underlength message on vRecv // Allow exceptions from underlength message on vRecv
printf("ProcessMessage(%s, %d bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what()); printf("ProcessMessage(%s, %u bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what());
} }
else if (strstr(e.what(), ": size too large")) else if (strstr(e.what(), "size too large"))
{ {
// Allow exceptions from overlong size // Allow exceptions from overlong size
printf("ProcessMessage(%s, %d bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what()); printf("ProcessMessage(%s, %u bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what());
} }
else else
{ {
@ -1928,7 +2020,7 @@ bool ProcessMessages(CNode* pfrom)
} }
if (!fRet) if (!fRet)
printf("ProcessMessage(%s, %d bytes) FAILED\n", strCommand.c_str(), nMessageSize); printf("ProcessMessage(%s, %u bytes) FAILED\n", strCommand.c_str(), nMessageSize);
} }
vRecv.Compact(); vRecv.Compact();
@ -1965,14 +2057,13 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CAddress addrMe; CAddress addrMe;
CAddress addrFrom; CAddress addrFrom;
uint64 nNonce = 1; uint64 nNonce = 1;
string strSubVer;
vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe; vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;
if (pfrom->nVersion == 10300) if (pfrom->nVersion == 10300)
pfrom->nVersion = 300; pfrom->nVersion = 300;
if (pfrom->nVersion >= 106 && !vRecv.empty()) if (pfrom->nVersion >= 106 && !vRecv.empty())
vRecv >> addrFrom >> nNonce; vRecv >> addrFrom >> nNonce;
if (pfrom->nVersion >= 106 && !vRecv.empty()) if (pfrom->nVersion >= 106 && !vRecv.empty())
vRecv >> strSubVer; vRecv >> pfrom->strSubVer;
if (pfrom->nVersion >= 209 && !vRecv.empty()) if (pfrom->nVersion >= 209 && !vRecv.empty())
vRecv >> pfrom->nStartingHeight; vRecv >> pfrom->nStartingHeight;
@ -2010,6 +2101,11 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->PushGetBlocks(pindexBest, uint256(0)); pfrom->PushGetBlocks(pindexBest, uint256(0));
} }
// Relay alerts
CRITICAL_BLOCK(cs_mapAlerts)
foreach(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
item.second.RelayTo(pfrom);
pfrom->fSuccessfullyConnected = true; pfrom->fSuccessfullyConnected = true;
printf("version message: version %d, blocks=%d\n", pfrom->nVersion, pfrom->nStartingHeight); printf("version message: version %d, blocks=%d\n", pfrom->nVersion, pfrom->nStartingHeight);
@ -2362,6 +2458,22 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
} }
else if (strCommand == "alert")
{
CAlert alert;
vRecv >> alert;
if (alert.ProcessAlert())
{
// Relay
pfrom->setKnown.insert(alert.GetHash());
CRITICAL_BLOCK(cs_vNodes)
foreach(CNode* pnode, vNodes)
alert.RelayTo(pnode);
}
}
else else
{ {
// Ignore unknown commands for extensibility // Ignore unknown commands for extensibility
@ -2695,7 +2807,7 @@ void BitcoinMiner()
map<uint256, CTxIndex> mapTestPool; map<uint256, CTxIndex> mapTestPool;
vector<char> vfAlreadyAdded(mapTransactions.size()); vector<char> vfAlreadyAdded(mapTransactions.size());
bool fFoundSomething = true; bool fFoundSomething = true;
unsigned int nBlockSize = 0; uint64 nBlockSize = 0;
while (fFoundSomething && nBlockSize < MAX_SIZE/2) while (fFoundSomething && nBlockSize < MAX_SIZE/2)
{ {
fFoundSomething = false; fFoundSomething = false;

218
main.h
View file

@ -14,7 +14,6 @@ class CBlockIndex;
class CWalletTx; class CWalletTx;
class CKeyItem; class CKeyItem;
static const unsigned int MAX_SIZE = 0x02000000;
static const unsigned int MAX_BLOCK_SIZE = 1000000; static const unsigned int MAX_BLOCK_SIZE = 1000000;
static const int64 COIN = 100000000; static const int64 COIN = 100000000;
static const int64 CENT = 1000000; static const int64 CENT = 1000000;
@ -61,7 +60,7 @@ extern int fMinimizeOnClose;
bool CheckDiskSpace(int64 nAdditionalBytes=0); bool CheckDiskSpace(uint64 nAdditionalBytes=0);
FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb"); FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
FILE* AppendBlockFile(unsigned int& nFileRet); FILE* AppendBlockFile(unsigned int& nFileRet);
bool AddKey(const CKey& key); bool AddKey(const CKey& key);
@ -85,7 +84,7 @@ void ThreadBitcoinMiner(void* parg);
void BitcoinMiner(); void BitcoinMiner();
bool CheckProofOfWork(uint256 hash, unsigned int nBits); bool CheckProofOfWork(uint256 hash, unsigned int nBits);
bool IsInitialBlockDownload(); bool IsInitialBlockDownload();
bool IsLockdown(); string GetWarnings(string strFor);
@ -298,7 +297,6 @@ public:
int64 nValue; int64 nValue;
CScript scriptPubKey; CScript scriptPubKey;
public:
CTxOut() CTxOut()
{ {
SetNull(); SetNull();
@ -475,6 +473,10 @@ public:
if (vin.empty() || vout.empty()) if (vin.empty() || vout.empty())
return error("CTransaction::CheckTransaction() : vin or vout empty"); return error("CTransaction::CheckTransaction() : vin or vout empty");
// Size limits
if (::GetSerializeSize(*this, SER_DISK) > MAX_SIZE)
return error("CTransaction::CheckTransaction() : size limits failed");
// Check for negative or overflow output values // Check for negative or overflow output values
int64 nValueOut = 0; int64 nValueOut = 0;
foreach(const CTxOut& txout, vout) foreach(const CTxOut& txout, vout)
@ -1469,6 +1471,214 @@ public:
//
// Alert messages are broadcast as a vector of signed data. Unserializing may
// not read the entire buffer if the alert is for a newer version, but older
// versions can still relay the original data.
//
class CUnsignedAlert
{
public:
int nVersion;
int64 nRelayUntil; // when newer nodes stop relaying to newer nodes
int64 nExpiration;
int nID;
int nCancel;
set<int> setCancel;
int nMinVer; // lowest version inclusive
int nMaxVer; // highest version inclusive
set<string> setSubVer; // empty matches all
int nPriority;
// Actions
string strComment;
string strStatusBar;
string strRPCError;
IMPLEMENT_SERIALIZE
(
READWRITE(this->nVersion);
nVersion = this->nVersion;
READWRITE(nRelayUntil);
READWRITE(nExpiration);
READWRITE(nID);
READWRITE(nCancel);
READWRITE(setCancel);
READWRITE(nMinVer);
READWRITE(nMaxVer);
READWRITE(setSubVer);
READWRITE(nPriority);
READWRITE(strComment);
READWRITE(strStatusBar);
READWRITE(strRPCError);
)
void SetNull()
{
nVersion = 1;
nRelayUntil = 0;
nExpiration = 0;
nID = 0;
nCancel = 0;
setCancel.clear();
nMinVer = 0;
nMaxVer = 0;
setSubVer.clear();
nPriority = 0;
strComment.clear();
strStatusBar.clear();
strRPCError.clear();
}
string ToString() const
{
string strSetCancel;
foreach(int n, setCancel)
strSetCancel += strprintf("%d ", n);
string strSetSubVer;
foreach(string str, setSubVer)
strSetSubVer += "\"" + str + "\" ";
return strprintf(
"CAlert(\n"
" nVersion = %d\n"
" nRelayUntil = %"PRI64d"\n"
" nExpiration = %"PRI64d"\n"
" nID = %d\n"
" nCancel = %d\n"
" setCancel = %s\n"
" nMinVer = %d\n"
" nMaxVer = %d\n"
" setSubVer = %s\n"
" nPriority = %d\n"
" strComment = \"%s\"\n"
" strStatusBar = \"%s\"\n"
" strRPCError = \"%s\"\n"
")\n",
nVersion,
nRelayUntil,
nExpiration,
nID,
nCancel,
strSetCancel.c_str(),
nMinVer,
nMaxVer,
strSetSubVer.c_str(),
nPriority,
strComment.c_str(),
strStatusBar.c_str(),
strRPCError.c_str());
}
void print() const
{
printf("%s", ToString().c_str());
}
};
class CAlert : public CUnsignedAlert
{
public:
vector<unsigned char> vchMsg;
vector<unsigned char> vchSig;
CAlert()
{
SetNull();
}
IMPLEMENT_SERIALIZE
(
READWRITE(vchMsg);
READWRITE(vchSig);
)
void SetNull()
{
CUnsignedAlert::SetNull();
vchMsg.clear();
vchSig.clear();
}
bool IsNull() const
{
return (nExpiration == 0);
}
uint256 GetHash() const
{
return SerializeHash(*this);
}
bool IsInEffect() const
{
return (GetAdjustedTime() < nExpiration);
}
bool Cancels(const CAlert& alert) const
{
if (!IsInEffect())
false;
return (alert.nID <= nCancel || setCancel.count(alert.nID));
}
bool AppliesTo(int nVersion, string strSubVerIn) const
{
return (IsInEffect() &&
nMinVer <= nVersion && nVersion <= nMaxVer &&
(setSubVer.empty() || setSubVer.count(strSubVerIn)));
}
bool AppliesToMe() const
{
return AppliesTo(VERSION, ::pszSubVer);
}
bool RelayTo(CNode* pnode) const
{
if (!IsInEffect())
return false;
// returns true if wasn't already contained in the set
if (pnode->setKnown.insert(GetHash()).second)
{
if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
AppliesToMe() ||
GetAdjustedTime() < nRelayUntil)
{
pnode->PushMessage("alert", *this);
return true;
}
}
return false;
}
bool CheckSignature()
{
CKey key;
if (!key.SetPubKey(ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284")))
return error("CAlert::CheckSignature() : SetPubKey failed");
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
return error("CAlert::CheckSignature() : verify signature failed");
// Now unserialize the data
CDataStream sMsg(vchMsg);
sMsg >> *(CUnsignedAlert*)this;
return true;
}
bool ProcessAlert();
};
extern map<uint256, CTransaction> mapTransactions; extern map<uint256, CTransaction> mapTransactions;
extern map<uint256, CWalletTx> mapWallet; extern map<uint256, CWalletTx> mapWallet;
extern vector<uint256> vWalletUpdated; extern vector<uint256> vWalletUpdated;

5
net.h
View file

@ -504,6 +504,7 @@ public:
unsigned int nMessageStart; unsigned int nMessageStart;
CAddress addr; CAddress addr;
int nVersion; int nVersion;
string strSubVer;
bool fClient; bool fClient;
bool fInbound; bool fInbound;
bool fNetworkNode; bool fNetworkNode;
@ -520,10 +521,11 @@ public:
uint256 hashLastGetBlocksEnd; uint256 hashLastGetBlocksEnd;
int nStartingHeight; int nStartingHeight;
// flood // flood relay
vector<CAddress> vAddrToSend; vector<CAddress> vAddrToSend;
set<CAddress> setAddrKnown; set<CAddress> setAddrKnown;
bool fGetAddr; bool fGetAddr;
set<uint256> setKnown;
// inventory based relay // inventory based relay
set<CInv> setInventoryKnown; set<CInv> setInventoryKnown;
@ -557,6 +559,7 @@ public:
nMessageStart = -1; nMessageStart = -1;
addr = addrIn; addr = addrIn;
nVersion = 0; nVersion = 0;
strSubVer = "";
fClient = false; // set by version message fClient = false; // set by version message
fInbound = fInboundIn; fInbound = fInboundIn;
fNetworkNode = false; fNetworkNode = false;

View file

@ -247,7 +247,7 @@ Value getinfo(const Array& params, bool fHelp)
obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1))); obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("hashespersec", gethashespersec(params, false))); obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
obj.push_back(Pair("status", strWarning)); obj.push_back(Pair("errors", GetWarnings("statusbar")));
return obj; return obj;
} }
@ -975,8 +975,9 @@ void ThreadRPCServer2(void* parg)
printf("ThreadRPCServer method=%s\n", strMethod.c_str()); printf("ThreadRPCServer method=%s\n", strMethod.c_str());
// Observe lockdown // Observe lockdown
if (IsLockdown() && !mapArgs.count("-overridesafety") && strMethod != "help" && strMethod != "stop" && strMethod != "getgenerate" && strMethod != "setgenerate") string strWarning = GetWarnings("rpc");
throw runtime_error("WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade."); if (strWarning != "" && !mapArgs.count("-overridesafety") && strMethod != "getinfo" && strMethod != "help" && strMethod != "stop" && strMethod != "getgenerate" && strMethod != "setgenerate")
throw runtime_error(strWarning);
// Execute // Execute
map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod); map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);

View file

@ -19,8 +19,11 @@ class CScript;
class CDataStream; class CDataStream;
class CAutoFile; class CAutoFile;
static const int VERSION = 310; static const unsigned int MAX_SIZE = 0x02000000;
static const char* pszSubVer = ".5";
static const int VERSION = 311;
static const char* pszSubVer = ".0";
@ -224,7 +227,7 @@ uint64 ReadCompactSize(Stream& is)
READDATA(is, nSize); READDATA(is, nSize);
nSizeRet = nSize; nSizeRet = nSize;
} }
if (nSizeRet > (uint64)INT_MAX) if (nSizeRet > (uint64)MAX_SIZE)
throw std::ios_base::failure("ReadCompactSize() : size too large"); throw std::ios_base::failure("ReadCompactSize() : size too large");
return nSizeRet; return nSizeRet;
} }

13
ui.cpp
View file

@ -196,7 +196,7 @@ bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* pa
void CalledSetStatusBar(const string& strText, int nField) void CalledSetStatusBar(const string& strText, int nField)
{ {
if (nField == 0 && IsLockdown()) if (nField == 0 && GetWarnings("statusbar") != "")
return; return;
if (pframeMain && pframeMain->m_statusBar) if (pframeMain && pframeMain->m_statusBar)
pframeMain->m_statusBar->SetStatusText(strText, nField); pframeMain->m_statusBar->SetStatusText(strText, nField);
@ -1013,12 +1013,13 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
RefreshStatusColumn(); RefreshStatusColumn();
// Update status bar // Update status bar
static bool fPrevLockdown; static string strPrevWarning;
if (IsLockdown()) string strWarning = GetWarnings("statusbar");
m_statusBar->SetStatusText(string(" ") + _("WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade."), 0); if (strWarning != "")
else if (fPrevLockdown) m_statusBar->SetStatusText(string(" ") + _(strWarning), 0);
else if (strPrevWarning != "")
m_statusBar->SetStatusText("", 0); m_statusBar->SetStatusText("", 0);
fPrevLockdown = IsLockdown(); strPrevWarning = strWarning;
string strGen = ""; string strGen = "";
if (fGenerateBitcoins) if (fGenerateBitcoins)

View file

@ -14,7 +14,7 @@ char pszSetDataDir[MAX_PATH] = "";
bool fShutdown = false; bool fShutdown = false;
bool fDaemon = false; bool fDaemon = false;
bool fCommandLine = false; bool fCommandLine = false;
string strWarning; string strMiscWarning;
@ -104,12 +104,8 @@ void RandAddSeedPerfmon()
RegCloseKey(HKEY_PERFORMANCE_DATA); RegCloseKey(HKEY_PERFORMANCE_DATA);
if (ret == ERROR_SUCCESS) if (ret == ERROR_SUCCESS)
{ {
uint256 hash; RAND_add(pdata, nSize, nSize/100.0);
SHA256(pdata, nSize, (unsigned char*)&hash);
RAND_add(&hash, sizeof(hash), min(nSize/500.0, (double)sizeof(hash)));
hash = 0;
memset(pdata, 0, nSize); memset(pdata, 0, nSize);
printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize); printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize);
} }
#endif #endif
@ -371,11 +367,6 @@ bool ParseMoney(const char* pszIn, int64& nRet)
vector<unsigned char> ParseHex(const char* psz) vector<unsigned char> ParseHex(const char* psz)
{ {
vector<unsigned char> vch;
while (isspace(*psz))
psz++;
vch.reserve((strlen(psz)+1)/3);
static char phexdigit[256] = static char phexdigit[256] =
{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
@ -394,24 +385,22 @@ vector<unsigned char> ParseHex(const char* psz)
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
while (*psz) // convert hex dump to vector
vector<unsigned char> vch;
loop
{ {
while (isspace(*psz))
psz++;
char c = phexdigit[(unsigned char)*psz++]; char c = phexdigit[(unsigned char)*psz++];
if (c == -1) if (c == -1)
break; break;
unsigned char n = (c << 4); unsigned char n = (c << 4);
if (*psz) c = phexdigit[(unsigned char)*psz++];
{ if (c == -1)
char c = phexdigit[(unsigned char)*psz++]; break;
if (c == -1) n |= c;
break; vch.push_back(n);
n |= c;
vch.push_back(n);
}
while (isspace(*psz))
psz++;
} }
return vch; return vch;
} }
@ -761,7 +750,7 @@ void AddTimeData(unsigned int ip, int64 nTime)
{ {
fDone = true; fDone = true;
string strMessage = _("Warning: Check your system date and time, you may not be able to generate or receive the most recent blocks!"); string strMessage = _("Warning: Check your system date and time, you may not be able to generate or receive the most recent blocks!");
strWarning = strMessage; strMiscWarning = strMessage;
printf("*** %s\n", strMessage.c_str()); printf("*** %s\n", strMessage.c_str());
boost::thread(bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1)); boost::thread(bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1));
} }

6
util.h
View file

@ -143,7 +143,7 @@ extern char pszSetDataDir[MAX_PATH];
extern bool fShutdown; extern bool fShutdown;
extern bool fDaemon; extern bool fDaemon;
extern bool fCommandLine; extern bool fCommandLine;
extern string strWarning; extern string strMiscWarning;
void RandAddSeed(); void RandAddSeed();
void RandAddSeedPerfmon(); void RandAddSeedPerfmon();
@ -307,6 +307,8 @@ inline int64 abs64(int64 n)
template<typename T> template<typename T>
string HexStr(const T itbegin, const T itend, bool fSpaces=true) string HexStr(const T itbegin, const T itend, bool fSpaces=true)
{ {
if (itbegin == itend)
return "";
const unsigned char* pbegin = (const unsigned char*)&itbegin[0]; const unsigned char* pbegin = (const unsigned char*)&itbegin[0];
const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]); const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]);
string str; string str;
@ -323,6 +325,8 @@ inline string HexStr(vector<unsigned char> vch, bool fSpaces=true)
template<typename T> template<typename T>
string HexNumStr(const T itbegin, const T itend, bool f0x=true) string HexNumStr(const T itbegin, const T itend, bool f0x=true)
{ {
if (itbegin == itend)
return "";
const unsigned char* pbegin = (const unsigned char*)&itbegin[0]; const unsigned char* pbegin = (const unsigned char*)&itbegin[0];
const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]); const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]);
string str = (f0x ? "0x" : ""); string str = (f0x ? "0x" : "");