]> Git Repo - VerusCoin.git/blame - src/main.h
Remove wxWidgets
[VerusCoin.git] / src / main.h
CommitLineData
0a61b0df 1// Copyright (c) 2009-2010 Satoshi Nakamoto
b2120e22 2// Copyright (c) 2011 The Bitcoin developers
0a61b0df 3// Distributed under the MIT/X11 software license, see the accompanying
4// file license.txt or http://www.opensource.org/licenses/mit-license.php.
223b6f1b
WL
5#ifndef BITCOIN_MAIN_H
6#define BITCOIN_MAIN_H
7
8#include "bignum.h"
9#include "net.h"
10#include "key.h"
223b6f1b 11#include "script.h"
64c7ee7e 12#include "db.h"
223b6f1b
WL
13
14#include <list>
0a61b0df 15
0a61b0df 16class CBlock;
17class CBlockIndex;
18class CWalletTx;
e89b9f6a 19class CWallet;
0a61b0df 20class CKeyItem;
64c7ee7e
PW
21class CReserveKey;
22class CWalletDB;
0a61b0df 23
40c2614e
JL
24class CAddress;
25class CInv;
26class CRequestTracker;
27class CNode;
28class CBlockIndex;
29
0a61b0df 30static const unsigned int MAX_BLOCK_SIZE = 1000000;
3df62878 31static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
f1e1fb4b 32static const int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
0a61b0df 33static const int64 COIN = 100000000;
34static const int64 CENT = 1000000;
352b4ea5 35static const int64 MIN_TX_FEE = 50000;
6de1326b 36static const int64 MIN_RELAY_TX_FEE = 10000;
0a61b0df 37static const int64 MAX_MONEY = 21000000 * COIN;
38inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
39static const int COINBASE_MATURITY = 100;
aa496b75
WL
40// Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp.
41static const int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
8bb5edc1
MC
42#ifdef USE_UPNP
43static const int fHaveUPnP = true;
44#else
45static const int fHaveUPnP = false;
46#endif
0a61b0df 47
48
49
50
51
52
53extern CCriticalSection cs_main;
223b6f1b 54extern std::map<uint256, CBlockIndex*> mapBlockIndex;
5cbf7532 55extern uint256 hashGenesisBlock;
0a61b0df 56extern CBlockIndex* pindexGenesisBlock;
57extern int nBestHeight;
58extern CBigNum bnBestChainWork;
59extern CBigNum bnBestInvalidWork;
60extern uint256 hashBestChain;
61extern CBlockIndex* pindexBest;
62extern unsigned int nTransactionsUpdated;
0a61b0df 63extern double dHashesPerSec;
64extern int64 nHPSTimerStart;
e89b9f6a 65extern int64 nTimeBestReceived;
64c7ee7e
PW
66extern CCriticalSection cs_setpwalletRegistered;
67extern std::set<CWallet*> setpwalletRegistered;
0a61b0df 68
69// Settings
70extern int fGenerateBitcoins;
71extern int64 nTransactionFee;
0a61b0df 72extern int fLimitProcessors;
73extern int nLimitProcessors;
74extern int fMinimizeToTray;
75extern int fMinimizeOnClose;
8bb5edc1 76extern int fUseUPnP;
0a61b0df 77
78
79
80
81
1512d5ce
JL
82class CReserveKey;
83class CTxDB;
84class CTxIndex;
0a61b0df 85
64c7ee7e
PW
86void RegisterWallet(CWallet* pwalletIn);
87void UnregisterWallet(CWallet* pwalletIn);
0a61b0df 88bool CheckDiskSpace(uint64 nAdditionalBytes=0);
89FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
90FILE* AppendBlockFile(unsigned int& nFileRet);
0a61b0df 91bool LoadBlockIndex(bool fAllowNew=true);
92void PrintBlockTree();
93bool ProcessMessages(CNode* pfrom);
0a61b0df 94bool SendMessages(CNode* pto, bool fSendTrickle);
64c7ee7e 95void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
776d0f34 96CBlock* CreateNewBlock(CReserveKey& reservekey);
83f4cd15 97void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
776d0f34 98void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
64c7ee7e 99bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
0a61b0df 100bool CheckProofOfWork(uint256 hash, unsigned int nBits);
eade2131 101int GetTotalBlocksEstimate();
d33cc2b5 102int GetNumBlocksOfPeers();
0a61b0df 103bool IsInitialBlockDownload();
223b6f1b 104std::string GetWarnings(std::string strFor);
0a61b0df 105
106
107
108
109
110
111
112
113
114
115
116
64c7ee7e
PW
117bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
118
119template<typename T>
120bool WriteSetting(const std::string& strKey, const T& value)
121{
122 bool fOk = false;
123 BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
124 {
125 std::string strWalletFile;
126 if (!GetWalletFile(pwallet, strWalletFile))
127 continue;
128 fOk |= CWalletDB(strWalletFile).WriteSetting(strKey, value);
129 }
130 return fOk;
131}
132
133
0a61b0df 134class CDiskTxPos
135{
136public:
137 unsigned int nFile;
138 unsigned int nBlockPos;
139 unsigned int nTxPos;
140
141 CDiskTxPos()
142 {
143 SetNull();
144 }
145
146 CDiskTxPos(unsigned int nFileIn, unsigned int nBlockPosIn, unsigned int nTxPosIn)
147 {
148 nFile = nFileIn;
149 nBlockPos = nBlockPosIn;
150 nTxPos = nTxPosIn;
151 }
152
153 IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
154 void SetNull() { nFile = -1; nBlockPos = 0; nTxPos = 0; }
155 bool IsNull() const { return (nFile == -1); }
156
157 friend bool operator==(const CDiskTxPos& a, const CDiskTxPos& b)
158 {
159 return (a.nFile == b.nFile &&
160 a.nBlockPos == b.nBlockPos &&
161 a.nTxPos == b.nTxPos);
162 }
163
164 friend bool operator!=(const CDiskTxPos& a, const CDiskTxPos& b)
165 {
166 return !(a == b);
167 }
168
223b6f1b 169 std::string ToString() const
0a61b0df 170 {
171 if (IsNull())
172 return strprintf("null");
173 else
174 return strprintf("(nFile=%d, nBlockPos=%d, nTxPos=%d)", nFile, nBlockPos, nTxPos);
175 }
176
177 void print() const
178 {
179 printf("%s", ToString().c_str());
180 }
181};
182
183
184
185
186class CInPoint
187{
188public:
189 CTransaction* ptx;
190 unsigned int n;
191
192 CInPoint() { SetNull(); }
193 CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; }
194 void SetNull() { ptx = NULL; n = -1; }
195 bool IsNull() const { return (ptx == NULL && n == -1); }
196};
197
198
199
200
201class COutPoint
202{
203public:
204 uint256 hash;
205 unsigned int n;
206
207 COutPoint() { SetNull(); }
208 COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; }
209 IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
210 void SetNull() { hash = 0; n = -1; }
211 bool IsNull() const { return (hash == 0 && n == -1); }
212
213 friend bool operator<(const COutPoint& a, const COutPoint& b)
214 {
215 return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n));
216 }
217
218 friend bool operator==(const COutPoint& a, const COutPoint& b)
219 {
220 return (a.hash == b.hash && a.n == b.n);
221 }
222
223 friend bool operator!=(const COutPoint& a, const COutPoint& b)
224 {
225 return !(a == b);
226 }
227
223b6f1b 228 std::string ToString() const
0a61b0df 229 {
b22c8842 230 return strprintf("COutPoint(%s, %d)", hash.ToString().substr(0,10).c_str(), n);
0a61b0df 231 }
232
233 void print() const
234 {
235 printf("%s\n", ToString().c_str());
236 }
237};
238
239
240
241
242//
243// An input of a transaction. It contains the location of the previous
244// transaction's output that it claims and a signature that matches the
245// output's public key.
246//
247class CTxIn
248{
249public:
250 COutPoint prevout;
251 CScript scriptSig;
252 unsigned int nSequence;
253
254 CTxIn()
255 {
256 nSequence = UINT_MAX;
257 }
258
259 explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)
260 {
261 prevout = prevoutIn;
262 scriptSig = scriptSigIn;
263 nSequence = nSequenceIn;
264 }
265
266 CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)
267 {
268 prevout = COutPoint(hashPrevTx, nOut);
269 scriptSig = scriptSigIn;
270 nSequence = nSequenceIn;
271 }
272
273 IMPLEMENT_SERIALIZE
274 (
275 READWRITE(prevout);
276 READWRITE(scriptSig);
277 READWRITE(nSequence);
278 )
279
280 bool IsFinal() const
281 {
282 return (nSequence == UINT_MAX);
283 }
284
285 friend bool operator==(const CTxIn& a, const CTxIn& b)
286 {
287 return (a.prevout == b.prevout &&
288 a.scriptSig == b.scriptSig &&
289 a.nSequence == b.nSequence);
290 }
291
292 friend bool operator!=(const CTxIn& a, const CTxIn& b)
293 {
294 return !(a == b);
295 }
296
223b6f1b 297 std::string ToString() const
0a61b0df 298 {
223b6f1b 299 std::string str;
0a61b0df 300 str += strprintf("CTxIn(");
301 str += prevout.ToString();
302 if (prevout.IsNull())
f1e1fb4b 303 str += strprintf(", coinbase %s", HexStr(scriptSig).c_str());
0a61b0df 304 else
305 str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
306 if (nSequence != UINT_MAX)
307 str += strprintf(", nSequence=%u", nSequence);
308 str += ")";
309 return str;
310 }
311
312 void print() const
313 {
314 printf("%s\n", ToString().c_str());
315 }
0a61b0df 316};
317
318
319
320
321//
322// An output of a transaction. It contains the public key that the next input
323// must be able to sign with to claim it.
324//
325class CTxOut
326{
327public:
328 int64 nValue;
329 CScript scriptPubKey;
330
331 CTxOut()
332 {
333 SetNull();
334 }
335
336 CTxOut(int64 nValueIn, CScript scriptPubKeyIn)
337 {
338 nValue = nValueIn;
339 scriptPubKey = scriptPubKeyIn;
340 }
341
342 IMPLEMENT_SERIALIZE
343 (
344 READWRITE(nValue);
345 READWRITE(scriptPubKey);
346 )
347
348 void SetNull()
349 {
350 nValue = -1;
351 scriptPubKey.clear();
352 }
353
354 bool IsNull()
355 {
356 return (nValue == -1);
357 }
358
359 uint256 GetHash() const
360 {
361 return SerializeHash(*this);
362 }
363
0a61b0df 364 friend bool operator==(const CTxOut& a, const CTxOut& b)
365 {
366 return (a.nValue == b.nValue &&
367 a.scriptPubKey == b.scriptPubKey);
368 }
369
370 friend bool operator!=(const CTxOut& a, const CTxOut& b)
371 {
372 return !(a == b);
373 }
374
223b6f1b 375 std::string ToString() const
0a61b0df 376 {
377 if (scriptPubKey.size() < 6)
378 return "CTxOut(error)";
10384941 379 return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30).c_str());
0a61b0df 380 }
381
382 void print() const
383 {
384 printf("%s\n", ToString().c_str());
385 }
386};
387
388
389
390
391//
392// The basic transaction that is broadcasted on the network and contained in
393// blocks. A transaction can contain multiple inputs and outputs.
394//
395class CTransaction
396{
397public:
398 int nVersion;
223b6f1b
WL
399 std::vector<CTxIn> vin;
400 std::vector<CTxOut> vout;
0a61b0df 401 unsigned int nLockTime;
402
3e52aaf2
GA
403 // Denial-of-service detection:
404 mutable int nDoS;
405 bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; }
0a61b0df 406
407 CTransaction()
408 {
409 SetNull();
410 }
411
412 IMPLEMENT_SERIALIZE
413 (
414 READWRITE(this->nVersion);
415 nVersion = this->nVersion;
416 READWRITE(vin);
417 READWRITE(vout);
418 READWRITE(nLockTime);
419 )
420
421 void SetNull()
422 {
423 nVersion = 1;
424 vin.clear();
425 vout.clear();
426 nLockTime = 0;
3e52aaf2 427 nDoS = 0; // Denial-of-service prevention
0a61b0df 428 }
429
430 bool IsNull() const
431 {
432 return (vin.empty() && vout.empty());
433 }
434
435 uint256 GetHash() const
436 {
437 return SerializeHash(*this);
438 }
439
440 bool IsFinal(int nBlockHeight=0, int64 nBlockTime=0) const
441 {
442 // Time based nLockTime implemented in 0.1.6
443 if (nLockTime == 0)
444 return true;
445 if (nBlockHeight == 0)
446 nBlockHeight = nBestHeight;
447 if (nBlockTime == 0)
448 nBlockTime = GetAdjustedTime();
aa496b75 449 if ((int64)nLockTime < (nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
0a61b0df 450 return true;
223b6f1b 451 BOOST_FOREACH(const CTxIn& txin, vin)
0a61b0df 452 if (!txin.IsFinal())
453 return false;
454 return true;
455 }
456
457 bool IsNewerThan(const CTransaction& old) const
458 {
459 if (vin.size() != old.vin.size())
460 return false;
461 for (int i = 0; i < vin.size(); i++)
462 if (vin[i].prevout != old.vin[i].prevout)
463 return false;
464
465 bool fNewer = false;
466 unsigned int nLowest = UINT_MAX;
467 for (int i = 0; i < vin.size(); i++)
468 {
469 if (vin[i].nSequence != old.vin[i].nSequence)
470 {
471 if (vin[i].nSequence <= nLowest)
472 {
473 fNewer = false;
474 nLowest = vin[i].nSequence;
475 }
476 if (old.vin[i].nSequence < nLowest)
477 {
478 fNewer = true;
479 nLowest = old.vin[i].nSequence;
480 }
481 }
482 }
483 return fNewer;
484 }
485
486 bool IsCoinBase() const
487 {
488 return (vin.size() == 1 && vin[0].prevout.IsNull());
489 }
490
f1e1fb4b 491 int GetSigOpCount() const
492 {
493 int n = 0;
223b6f1b 494 BOOST_FOREACH(const CTxIn& txin, vin)
f1e1fb4b 495 n += txin.scriptSig.GetSigOpCount();
223b6f1b 496 BOOST_FOREACH(const CTxOut& txout, vout)
f1e1fb4b 497 n += txout.scriptPubKey.GetSigOpCount();
498 return n;
499 }
500
a206a239 501 bool IsStandard() const
502 {
223b6f1b 503 BOOST_FOREACH(const CTxIn& txin, vin)
a206a239 504 if (!txin.scriptSig.IsPushOnly())
505 return error("nonstandard txin: %s", txin.scriptSig.ToString().c_str());
223b6f1b 506 BOOST_FOREACH(const CTxOut& txout, vout)
a206a239 507 if (!::IsStandard(txout.scriptPubKey))
508 return error("nonstandard txout: %s", txout.scriptPubKey.ToString().c_str());
509 return true;
510 }
511
0a61b0df 512 int64 GetValueOut() const
513 {
514 int64 nValueOut = 0;
223b6f1b 515 BOOST_FOREACH(const CTxOut& txout, vout)
0a61b0df 516 {
517 nValueOut += txout.nValue;
518 if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut))
223b6f1b 519 throw std::runtime_error("CTransaction::GetValueOut() : value out of range");
0a61b0df 520 }
521 return nValueOut;
522 }
523
395c1f44
GA
524 static bool AllowFree(double dPriority)
525 {
526 // Large (in bytes) low-priority (new, small-coin) transactions
527 // need a fee.
528 return dPriority > COIN * 144 / 250;
529 }
530
2bfda1be 531 int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, bool fForRelay=false) const
0a61b0df 532 {
2bfda1be
PW
533 // Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE
534 int64 nBaseFee = fForRelay ? MIN_RELAY_TX_FEE : MIN_TX_FEE;
535
0a61b0df 536 unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK);
9b8eb4d6 537 unsigned int nNewBlockSize = nBlockSize + nBytes;
2bfda1be 538 int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee;
0a61b0df 539
f35e21e2 540 if (fAllowFree)
541 {
298a7714 542 if (nBlockSize == 1)
543 {
544 // Transactions under 10K are free
545 // (about 4500bc if made of 50bc inputs)
546 if (nBytes < 10000)
547 nMinFee = 0;
548 }
549 else
550 {
551 // Free transaction area
552 if (nNewBlockSize < 27000)
553 nMinFee = 0;
554 }
f35e21e2 555 }
0a61b0df 556
2bfda1be
PW
557 // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01
558 if (nMinFee < nBaseFee)
223b6f1b 559 BOOST_FOREACH(const CTxOut& txout, vout)
0a61b0df 560 if (txout.nValue < CENT)
2bfda1be 561 nMinFee = nBaseFee;
0a61b0df 562
f1e1fb4b 563 // Raise the price as the block approaches full
9b8eb4d6 564 if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2)
565 {
566 if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN)
567 return MAX_MONEY;
568 nMinFee *= MAX_BLOCK_SIZE_GEN / (MAX_BLOCK_SIZE_GEN - nNewBlockSize);
569 }
570
f1e1fb4b 571 if (!MoneyRange(nMinFee))
572 nMinFee = MAX_MONEY;
0a61b0df 573 return nMinFee;
574 }
575
576
0a61b0df 577 bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL)
578 {
579 CAutoFile filein = OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb");
580 if (!filein)
581 return error("CTransaction::ReadFromDisk() : OpenBlockFile failed");
582
583 // Read transaction
584 if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
585 return error("CTransaction::ReadFromDisk() : fseek failed");
586 filein >> *this;
587
588 // Return file pointer
589 if (pfileRet)
590 {
591 if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
592 return error("CTransaction::ReadFromDisk() : second fseek failed");
593 *pfileRet = filein.release();
594 }
595 return true;
596 }
597
0a61b0df 598 friend bool operator==(const CTransaction& a, const CTransaction& b)
599 {
600 return (a.nVersion == b.nVersion &&
601 a.vin == b.vin &&
602 a.vout == b.vout &&
603 a.nLockTime == b.nLockTime);
604 }
605
606 friend bool operator!=(const CTransaction& a, const CTransaction& b)
607 {
608 return !(a == b);
609 }
610
611
223b6f1b 612 std::string ToString() const
0a61b0df 613 {
223b6f1b 614 std::string str;
0a61b0df 615 str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n",
b22c8842 616 GetHash().ToString().substr(0,10).c_str(),
0a61b0df 617 nVersion,
618 vin.size(),
619 vout.size(),
620 nLockTime);
621 for (int i = 0; i < vin.size(); i++)
622 str += " " + vin[i].ToString() + "\n";
623 for (int i = 0; i < vout.size(); i++)
624 str += " " + vout[i].ToString() + "\n";
625 return str;
626 }
627
628 void print() const
629 {
630 printf("%s", ToString().c_str());
631 }
632
633
461764cb 634 bool ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet);
635 bool ReadFromDisk(CTxDB& txdb, COutPoint prevout);
636 bool ReadFromDisk(COutPoint prevout);
0a61b0df 637 bool DisconnectInputs(CTxDB& txdb);
223b6f1b 638 bool ConnectInputs(CTxDB& txdb, std::map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx,
0a61b0df 639 CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee=0);
640 bool ClientConnectInputs();
a790fa46 641 bool CheckTransaction() const;
f1e1fb4b 642 bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
e89b9f6a 643 bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL);
0a61b0df 644protected:
f1e1fb4b 645 bool AddToMemoryPoolUnchecked();
0a61b0df 646public:
647 bool RemoveFromMemoryPool();
648};
649
650
651
652
653
654//
655// A transaction with a merkle branch linking it to the block chain
656//
657class CMerkleTx : public CTransaction
658{
659public:
660 uint256 hashBlock;
223b6f1b 661 std::vector<uint256> vMerkleBranch;
0a61b0df 662 int nIndex;
663
664 // memory only
a790fa46 665 mutable char fMerkleVerified;
0a61b0df 666
667
668 CMerkleTx()
669 {
670 Init();
671 }
672
673 CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
674 {
675 Init();
676 }
677
678 void Init()
679 {
680 hashBlock = 0;
681 nIndex = -1;
682 fMerkleVerified = false;
0a61b0df 683 }
684
335e878b 685
0a61b0df 686 IMPLEMENT_SERIALIZE
687 (
688 nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);
689 nVersion = this->nVersion;
690 READWRITE(hashBlock);
691 READWRITE(vMerkleBranch);
692 READWRITE(nIndex);
693 )
694
0a61b0df 695
696 int SetMerkleBranch(const CBlock* pblock=NULL);
697 int GetDepthInMainChain(int& nHeightRet) const;
698 int GetDepthInMainChain() const { int nHeight; return GetDepthInMainChain(nHeight); }
699 bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
700 int GetBlocksToMaturity() const;
f1e1fb4b 701 bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true);
e89b9f6a 702 bool AcceptToMemoryPool();
0a61b0df 703};
704
705
706
707
708//
709// A txdb record that contains the disk location of a transaction and the
710// locations of transactions that spend its outputs. vSpent is really only
711// used as a flag, but having the location is very helpful for debugging.
712//
713class CTxIndex
714{
715public:
716 CDiskTxPos pos;
223b6f1b 717 std::vector<CDiskTxPos> vSpent;
0a61b0df 718
719 CTxIndex()
720 {
721 SetNull();
722 }
723
724 CTxIndex(const CDiskTxPos& posIn, unsigned int nOutputs)
725 {
726 pos = posIn;
727 vSpent.resize(nOutputs);
728 }
729
730 IMPLEMENT_SERIALIZE
731 (
732 if (!(nType & SER_GETHASH))
733 READWRITE(nVersion);
734 READWRITE(pos);
735 READWRITE(vSpent);
736 )
737
738 void SetNull()
739 {
740 pos.SetNull();
741 vSpent.clear();
742 }
743
744 bool IsNull()
745 {
746 return pos.IsNull();
747 }
748
749 friend bool operator==(const CTxIndex& a, const CTxIndex& b)
750 {
f1e1fb4b 751 return (a.pos == b.pos &&
752 a.vSpent == b.vSpent);
0a61b0df 753 }
754
755 friend bool operator!=(const CTxIndex& a, const CTxIndex& b)
756 {
757 return !(a == b);
758 }
395c1f44 759 int GetDepthInMainChain() const;
0a61b0df 760};
761
762
763
764
765
766//
767// Nodes collect new transactions into a block, hash them into a hash tree,
768// and scan through nonce values to make the block's hash satisfy proof-of-work
769// requirements. When they solve the proof-of-work, they broadcast the block
770// to everyone and the block is added to the block chain. The first transaction
771// in the block is a special one that creates a new coin owned by the creator
772// of the block.
773//
774// Blocks are appended to blk0001.dat files on disk. Their location on disk
775// is indexed by CBlockIndex objects in memory.
776//
777class CBlock
778{
779public:
780 // header
781 int nVersion;
782 uint256 hashPrevBlock;
783 uint256 hashMerkleRoot;
784 unsigned int nTime;
785 unsigned int nBits;
786 unsigned int nNonce;
787
788 // network and disk
223b6f1b 789 std::vector<CTransaction> vtx;
0a61b0df 790
791 // memory only
223b6f1b 792 mutable std::vector<uint256> vMerkleTree;
0a61b0df 793
3e52aaf2
GA
794 // Denial-of-service detection:
795 mutable int nDoS;
796 bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; }
0a61b0df 797
798 CBlock()
799 {
800 SetNull();
801 }
802
803 IMPLEMENT_SERIALIZE
804 (
805 READWRITE(this->nVersion);
806 nVersion = this->nVersion;
807 READWRITE(hashPrevBlock);
808 READWRITE(hashMerkleRoot);
809 READWRITE(nTime);
810 READWRITE(nBits);
811 READWRITE(nNonce);
812
813 // ConnectBlock depends on vtx being last so it can calculate offset
814 if (!(nType & (SER_GETHASH|SER_BLOCKHEADERONLY)))
815 READWRITE(vtx);
816 else if (fRead)
817 const_cast<CBlock*>(this)->vtx.clear();
818 )
819
820 void SetNull()
821 {
822 nVersion = 1;
823 hashPrevBlock = 0;
824 hashMerkleRoot = 0;
825 nTime = 0;
826 nBits = 0;
827 nNonce = 0;
828 vtx.clear();
829 vMerkleTree.clear();
3e52aaf2 830 nDoS = 0;
0a61b0df 831 }
832
833 bool IsNull() const
834 {
835 return (nBits == 0);
836 }
837
838 uint256 GetHash() const
839 {
840 return Hash(BEGIN(nVersion), END(nNonce));
841 }
842
843 int64 GetBlockTime() const
844 {
845 return (int64)nTime;
846 }
847
f1e1fb4b 848 int GetSigOpCount() const
849 {
850 int n = 0;
223b6f1b 851 BOOST_FOREACH(const CTransaction& tx, vtx)
f1e1fb4b 852 n += tx.GetSigOpCount();
853 return n;
854 }
855
0a61b0df 856
857 uint256 BuildMerkleTree() const
858 {
859 vMerkleTree.clear();
223b6f1b 860 BOOST_FOREACH(const CTransaction& tx, vtx)
0a61b0df 861 vMerkleTree.push_back(tx.GetHash());
862 int j = 0;
863 for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
864 {
865 for (int i = 0; i < nSize; i += 2)
866 {
223b6f1b 867 int i2 = std::min(i+1, nSize-1);
0a61b0df 868 vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]),
869 BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
870 }
871 j += nSize;
872 }
873 return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
874 }
875
223b6f1b 876 std::vector<uint256> GetMerkleBranch(int nIndex) const
0a61b0df 877 {
878 if (vMerkleTree.empty())
879 BuildMerkleTree();
223b6f1b 880 std::vector<uint256> vMerkleBranch;
0a61b0df 881 int j = 0;
882 for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
883 {
223b6f1b 884 int i = std::min(nIndex^1, nSize-1);
0a61b0df 885 vMerkleBranch.push_back(vMerkleTree[j+i]);
886 nIndex >>= 1;
887 j += nSize;
888 }
889 return vMerkleBranch;
890 }
891
223b6f1b 892 static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
0a61b0df 893 {
894 if (nIndex == -1)
895 return 0;
223b6f1b 896 BOOST_FOREACH(const uint256& otherside, vMerkleBranch)
0a61b0df 897 {
898 if (nIndex & 1)
899 hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
900 else
901 hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));
902 nIndex >>= 1;
903 }
904 return hash;
905 }
906
907
f03304a9 908 bool WriteToDisk(unsigned int& nFileRet, unsigned int& nBlockPosRet)
0a61b0df 909 {
910 // Open history file to append
911 CAutoFile fileout = AppendBlockFile(nFileRet);
912 if (!fileout)
913 return error("CBlock::WriteToDisk() : AppendBlockFile failed");
0a61b0df 914
915 // Write index header
916 unsigned int nSize = fileout.GetSerializeSize(*this);
917 fileout << FLATDATA(pchMessageStart) << nSize;
918
919 // Write block
920 nBlockPosRet = ftell(fileout);
921 if (nBlockPosRet == -1)
922 return error("CBlock::WriteToDisk() : ftell failed");
923 fileout << *this;
924
925 // Flush stdio buffers and commit to disk before returning
926 fflush(fileout);
927 if (!IsInitialBlockDownload() || (nBestHeight+1) % 500 == 0)
928 {
929#ifdef __WXMSW__
930 _commit(_fileno(fileout));
931#else
932 fsync(fileno(fileout));
933#endif
934 }
935
936 return true;
937 }
938
939 bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions=true)
940 {
941 SetNull();
942
943 // Open history file to read
944 CAutoFile filein = OpenBlockFile(nFile, nBlockPos, "rb");
945 if (!filein)
946 return error("CBlock::ReadFromDisk() : OpenBlockFile failed");
947 if (!fReadTransactions)
948 filein.nType |= SER_BLOCKHEADERONLY;
949
950 // Read block
951 filein >> *this;
952
953 // Check the header
954 if (!CheckProofOfWork(GetHash(), nBits))
955 return error("CBlock::ReadFromDisk() : errors in block header");
956
957 return true;
958 }
959
960
961
962 void print() const
963 {
964 printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%d)\n",
965 GetHash().ToString().substr(0,20).c_str(),
966 nVersion,
967 hashPrevBlock.ToString().substr(0,20).c_str(),
b22c8842 968 hashMerkleRoot.ToString().substr(0,10).c_str(),
0a61b0df 969 nTime, nBits, nNonce,
970 vtx.size());
971 for (int i = 0; i < vtx.size(); i++)
972 {
973 printf(" ");
974 vtx[i].print();
975 }
976 printf(" vMerkleTree: ");
977 for (int i = 0; i < vMerkleTree.size(); i++)
b22c8842 978 printf("%s ", vMerkleTree[i].ToString().substr(0,10).c_str());
0a61b0df 979 printf("\n");
980 }
981
982
0a61b0df 983 bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);
984 bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex);
985 bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true);
986 bool SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew);
987 bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);
988 bool CheckBlock() const;
989 bool AcceptBlock();
990};
991
992
993
994
995
996
997//
998// The block chain is a tree shaped structure starting with the
999// genesis block at the root, with each block potentially having multiple
1000// candidates to be the next block. pprev and pnext link a path through the
1001// main/longest chain. A blockindex may have multiple pprev pointing back
1002// to it, but pnext will only point forward to the longest branch, or will
1003// be null if the block is not part of the longest chain.
1004//
1005class CBlockIndex
1006{
1007public:
1008 const uint256* phashBlock;
1009 CBlockIndex* pprev;
1010 CBlockIndex* pnext;
1011 unsigned int nFile;
1012 unsigned int nBlockPos;
1013 int nHeight;
1014 CBigNum bnChainWork;
1015
1016 // block header
1017 int nVersion;
1018 uint256 hashMerkleRoot;
1019 unsigned int nTime;
1020 unsigned int nBits;
1021 unsigned int nNonce;
1022
1023
1024 CBlockIndex()
1025 {
1026 phashBlock = NULL;
1027 pprev = NULL;
1028 pnext = NULL;
1029 nFile = 0;
1030 nBlockPos = 0;
1031 nHeight = 0;
1032 bnChainWork = 0;
1033
1034 nVersion = 0;
1035 hashMerkleRoot = 0;
1036 nTime = 0;
1037 nBits = 0;
1038 nNonce = 0;
1039 }
1040
1041 CBlockIndex(unsigned int nFileIn, unsigned int nBlockPosIn, CBlock& block)
1042 {
1043 phashBlock = NULL;
1044 pprev = NULL;
1045 pnext = NULL;
1046 nFile = nFileIn;
1047 nBlockPos = nBlockPosIn;
1048 nHeight = 0;
1049 bnChainWork = 0;
1050
1051 nVersion = block.nVersion;
1052 hashMerkleRoot = block.hashMerkleRoot;
1053 nTime = block.nTime;
1054 nBits = block.nBits;
1055 nNonce = block.nNonce;
1056 }
1057
f03304a9 1058 CBlock GetBlockHeader() const
1059 {
1060 CBlock block;
1061 block.nVersion = nVersion;
1062 if (pprev)
1063 block.hashPrevBlock = pprev->GetBlockHash();
1064 block.hashMerkleRoot = hashMerkleRoot;
1065 block.nTime = nTime;
1066 block.nBits = nBits;
1067 block.nNonce = nNonce;
1068 return block;
1069 }
1070
0a61b0df 1071 uint256 GetBlockHash() const
1072 {
1073 return *phashBlock;
1074 }
1075
1076 int64 GetBlockTime() const
1077 {
1078 return (int64)nTime;
1079 }
1080
1081 CBigNum GetBlockWork() const
1082 {
9b8eb4d6 1083 CBigNum bnTarget;
1084 bnTarget.SetCompact(nBits);
1085 if (bnTarget <= 0)
0a61b0df 1086 return 0;
9b8eb4d6 1087 return (CBigNum(1)<<256) / (bnTarget+1);
0a61b0df 1088 }
1089
1090 bool IsInMainChain() const
1091 {
1092 return (pnext || this == pindexBest);
1093 }
1094
1095 bool CheckIndex() const
1096 {
1097 return CheckProofOfWork(GetBlockHash(), nBits);
1098 }
1099
1100 bool EraseBlockFromDisk()
1101 {
1102 // Open history file
1103 CAutoFile fileout = OpenBlockFile(nFile, nBlockPos, "rb+");
1104 if (!fileout)
1105 return false;
1106
1107 // Overwrite with empty null block
1108 CBlock block;
1109 block.SetNull();
1110 fileout << block;
1111
1112 return true;
1113 }
1114
1115 enum { nMedianTimeSpan=11 };
1116
1117 int64 GetMedianTimePast() const
1118 {
1119 int64 pmedian[nMedianTimeSpan];
1120 int64* pbegin = &pmedian[nMedianTimeSpan];
1121 int64* pend = &pmedian[nMedianTimeSpan];
1122
1123 const CBlockIndex* pindex = this;
1124 for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
1125 *(--pbegin) = pindex->GetBlockTime();
1126
223b6f1b 1127 std::sort(pbegin, pend);
0a61b0df 1128 return pbegin[(pend - pbegin)/2];
1129 }
1130
1131 int64 GetMedianTime() const
1132 {
1133 const CBlockIndex* pindex = this;
1134 for (int i = 0; i < nMedianTimeSpan/2; i++)
1135 {
1136 if (!pindex->pnext)
1137 return GetBlockTime();
1138 pindex = pindex->pnext;
1139 }
1140 return pindex->GetMedianTimePast();
1141 }
1142
1143
1144
223b6f1b 1145 std::string ToString() const
0a61b0df 1146 {
1147 return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)",
1148 pprev, pnext, nFile, nBlockPos, nHeight,
b22c8842 1149 hashMerkleRoot.ToString().substr(0,10).c_str(),
0a61b0df 1150 GetBlockHash().ToString().substr(0,20).c_str());
1151 }
1152
1153 void print() const
1154 {
1155 printf("%s\n", ToString().c_str());
1156 }
1157};
1158
1159
1160
1161//
1162// Used to marshal pointers into hashes for db storage.
1163//
1164class CDiskBlockIndex : public CBlockIndex
1165{
1166public:
1167 uint256 hashPrev;
1168 uint256 hashNext;
1169
1170 CDiskBlockIndex()
1171 {
1172 hashPrev = 0;
1173 hashNext = 0;
1174 }
1175
1176 explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex)
1177 {
1178 hashPrev = (pprev ? pprev->GetBlockHash() : 0);
1179 hashNext = (pnext ? pnext->GetBlockHash() : 0);
1180 }
1181
1182 IMPLEMENT_SERIALIZE
1183 (
1184 if (!(nType & SER_GETHASH))
1185 READWRITE(nVersion);
1186
1187 READWRITE(hashNext);
1188 READWRITE(nFile);
1189 READWRITE(nBlockPos);
1190 READWRITE(nHeight);
1191
1192 // block header
1193 READWRITE(this->nVersion);
1194 READWRITE(hashPrev);
1195 READWRITE(hashMerkleRoot);
1196 READWRITE(nTime);
1197 READWRITE(nBits);
1198 READWRITE(nNonce);
1199 )
1200
1201 uint256 GetBlockHash() const
1202 {
1203 CBlock block;
1204 block.nVersion = nVersion;
1205 block.hashPrevBlock = hashPrev;
1206 block.hashMerkleRoot = hashMerkleRoot;
1207 block.nTime = nTime;
1208 block.nBits = nBits;
1209 block.nNonce = nNonce;
1210 return block.GetHash();
1211 }
1212
1213
223b6f1b 1214 std::string ToString() const
0a61b0df 1215 {
223b6f1b 1216 std::string str = "CDiskBlockIndex(";
0a61b0df 1217 str += CBlockIndex::ToString();
1218 str += strprintf("\n hashBlock=%s, hashPrev=%s, hashNext=%s)",
1219 GetBlockHash().ToString().c_str(),
1220 hashPrev.ToString().substr(0,20).c_str(),
1221 hashNext.ToString().substr(0,20).c_str());
1222 return str;
1223 }
1224
1225 void print() const
1226 {
1227 printf("%s\n", ToString().c_str());
1228 }
1229};
1230
1231
1232
1233
1234
1235
1236
1237
1238//
1239// Describes a place in the block chain to another node such that if the
1240// other node doesn't have the same branch, it can find a recent common trunk.
1241// The further back it is, the further before the fork it may be.
1242//
1243class CBlockLocator
1244{
1245protected:
223b6f1b 1246 std::vector<uint256> vHave;
0a61b0df 1247public:
1248
1249 CBlockLocator()
1250 {
1251 }
1252
1253 explicit CBlockLocator(const CBlockIndex* pindex)
1254 {
1255 Set(pindex);
1256 }
1257
1258 explicit CBlockLocator(uint256 hashBlock)
1259 {
223b6f1b 1260 std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
0a61b0df 1261 if (mi != mapBlockIndex.end())
1262 Set((*mi).second);
1263 }
1264
1265 IMPLEMENT_SERIALIZE
1266 (
1267 if (!(nType & SER_GETHASH))
1268 READWRITE(nVersion);
1269 READWRITE(vHave);
1270 )
1271
f03304a9 1272 void SetNull()
1273 {
1274 vHave.clear();
1275 }
1276
1277 bool IsNull()
1278 {
1279 return vHave.empty();
1280 }
1281
0a61b0df 1282 void Set(const CBlockIndex* pindex)
1283 {
1284 vHave.clear();
1285 int nStep = 1;
1286 while (pindex)
1287 {
1288 vHave.push_back(pindex->GetBlockHash());
1289
1290 // Exponentially larger steps back
1291 for (int i = 0; pindex && i < nStep; i++)
1292 pindex = pindex->pprev;
1293 if (vHave.size() > 10)
1294 nStep *= 2;
1295 }
1296 vHave.push_back(hashGenesisBlock);
1297 }
1298
1299 int GetDistanceBack()
1300 {
1301 // Retrace how far back it was in the sender's branch
1302 int nDistance = 0;
1303 int nStep = 1;
223b6f1b 1304 BOOST_FOREACH(const uint256& hash, vHave)
0a61b0df 1305 {
223b6f1b 1306 std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
0a61b0df 1307 if (mi != mapBlockIndex.end())
1308 {
1309 CBlockIndex* pindex = (*mi).second;
1310 if (pindex->IsInMainChain())
1311 return nDistance;
1312 }
1313 nDistance += nStep;
1314 if (nDistance > 10)
1315 nStep *= 2;
1316 }
1317 return nDistance;
1318 }
1319
1320 CBlockIndex* GetBlockIndex()
1321 {
1322 // Find the first block the caller has in the main chain
223b6f1b 1323 BOOST_FOREACH(const uint256& hash, vHave)
0a61b0df 1324 {
223b6f1b 1325 std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
0a61b0df 1326 if (mi != mapBlockIndex.end())
1327 {
1328 CBlockIndex* pindex = (*mi).second;
1329 if (pindex->IsInMainChain())
1330 return pindex;
1331 }
1332 }
1333 return pindexGenesisBlock;
1334 }
1335
1336 uint256 GetBlockHash()
1337 {
1338 // Find the first block the caller has in the main chain
223b6f1b 1339 BOOST_FOREACH(const uint256& hash, vHave)
0a61b0df 1340 {
223b6f1b 1341 std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
0a61b0df 1342 if (mi != mapBlockIndex.end())
1343 {
1344 CBlockIndex* pindex = (*mi).second;
1345 if (pindex->IsInMainChain())
1346 return hash;
1347 }
1348 }
1349 return hashGenesisBlock;
1350 }
1351
1352 int GetHeight()
1353 {
1354 CBlockIndex* pindex = GetBlockIndex();
1355 if (!pindex)
1356 return 0;
1357 return pindex->nHeight;
1358 }
1359};
1360
1361
1362
1363
1364
1365
e4ff4e68 1366
1367
1368
0a61b0df 1369//
629e37dd 1370// Alerts are for notifying old versions if they become too obsolete and
1371// need to upgrade. The message is displayed in the status bar.
0a61b0df 1372// Alert messages are broadcast as a vector of signed data. Unserializing may
1373// not read the entire buffer if the alert is for a newer version, but older
1374// versions can still relay the original data.
1375//
1376class CUnsignedAlert
1377{
1378public:
1379 int nVersion;
1380 int64 nRelayUntil; // when newer nodes stop relaying to newer nodes
1381 int64 nExpiration;
1382 int nID;
1383 int nCancel;
223b6f1b 1384 std::set<int> setCancel;
0a61b0df 1385 int nMinVer; // lowest version inclusive
1386 int nMaxVer; // highest version inclusive
223b6f1b 1387 std::set<std::string> setSubVer; // empty matches all
0a61b0df 1388 int nPriority;
1389
1390 // Actions
223b6f1b
WL
1391 std::string strComment;
1392 std::string strStatusBar;
1393 std::string strReserved;
0a61b0df 1394
1395 IMPLEMENT_SERIALIZE
1396 (
1397 READWRITE(this->nVersion);
1398 nVersion = this->nVersion;
1399 READWRITE(nRelayUntil);
1400 READWRITE(nExpiration);
1401 READWRITE(nID);
1402 READWRITE(nCancel);
1403 READWRITE(setCancel);
1404 READWRITE(nMinVer);
1405 READWRITE(nMaxVer);
1406 READWRITE(setSubVer);
1407 READWRITE(nPriority);
1408
1409 READWRITE(strComment);
1410 READWRITE(strStatusBar);
986b5e25 1411 READWRITE(strReserved);
0a61b0df 1412 )
1413
1414 void SetNull()
1415 {
1416 nVersion = 1;
1417 nRelayUntil = 0;
1418 nExpiration = 0;
1419 nID = 0;
1420 nCancel = 0;
1421 setCancel.clear();
1422 nMinVer = 0;
1423 nMaxVer = 0;
1424 setSubVer.clear();
1425 nPriority = 0;
1426
1427 strComment.clear();
1428 strStatusBar.clear();
986b5e25 1429 strReserved.clear();
0a61b0df 1430 }
1431
223b6f1b 1432 std::string ToString() const
0a61b0df 1433 {
223b6f1b
WL
1434 std::string strSetCancel;
1435 BOOST_FOREACH(int n, setCancel)
0a61b0df 1436 strSetCancel += strprintf("%d ", n);
223b6f1b
WL
1437 std::string strSetSubVer;
1438 BOOST_FOREACH(std::string str, setSubVer)
0a61b0df 1439 strSetSubVer += "\"" + str + "\" ";
1440 return strprintf(
1441 "CAlert(\n"
1442 " nVersion = %d\n"
1443 " nRelayUntil = %"PRI64d"\n"
1444 " nExpiration = %"PRI64d"\n"
1445 " nID = %d\n"
1446 " nCancel = %d\n"
1447 " setCancel = %s\n"
1448 " nMinVer = %d\n"
1449 " nMaxVer = %d\n"
1450 " setSubVer = %s\n"
1451 " nPriority = %d\n"
1452 " strComment = \"%s\"\n"
1453 " strStatusBar = \"%s\"\n"
0a61b0df 1454 ")\n",
1455 nVersion,
1456 nRelayUntil,
1457 nExpiration,
1458 nID,
1459 nCancel,
1460 strSetCancel.c_str(),
1461 nMinVer,
1462 nMaxVer,
1463 strSetSubVer.c_str(),
1464 nPriority,
1465 strComment.c_str(),
986b5e25 1466 strStatusBar.c_str());
0a61b0df 1467 }
1468
1469 void print() const
1470 {
1471 printf("%s", ToString().c_str());
1472 }
1473};
1474
1475class CAlert : public CUnsignedAlert
1476{
1477public:
223b6f1b
WL
1478 std::vector<unsigned char> vchMsg;
1479 std::vector<unsigned char> vchSig;
0a61b0df 1480
1481 CAlert()
1482 {
1483 SetNull();
1484 }
1485
1486 IMPLEMENT_SERIALIZE
1487 (
1488 READWRITE(vchMsg);
1489 READWRITE(vchSig);
1490 )
1491
1492 void SetNull()
1493 {
1494 CUnsignedAlert::SetNull();
1495 vchMsg.clear();
1496 vchSig.clear();
1497 }
1498
1499 bool IsNull() const
1500 {
1501 return (nExpiration == 0);
1502 }
1503
1504 uint256 GetHash() const
1505 {
1506 return SerializeHash(*this);
1507 }
1508
1509 bool IsInEffect() const
1510 {
1511 return (GetAdjustedTime() < nExpiration);
1512 }
1513
1514 bool Cancels(const CAlert& alert) const
1515 {
1516 if (!IsInEffect())
461764cb 1517 return false; // this was a no-op before 31403
0a61b0df 1518 return (alert.nID <= nCancel || setCancel.count(alert.nID));
1519 }
1520
223b6f1b 1521 bool AppliesTo(int nVersion, std::string strSubVerIn) const
0a61b0df 1522 {
1523 return (IsInEffect() &&
1524 nMinVer <= nVersion && nVersion <= nMaxVer &&
1525 (setSubVer.empty() || setSubVer.count(strSubVerIn)));
1526 }
1527
1528 bool AppliesToMe() const
1529 {
1530 return AppliesTo(VERSION, ::pszSubVer);
1531 }
1532
1533 bool RelayTo(CNode* pnode) const
1534 {
1535 if (!IsInEffect())
1536 return false;
1537 // returns true if wasn't already contained in the set
1538 if (pnode->setKnown.insert(GetHash()).second)
1539 {
1540 if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
1541 AppliesToMe() ||
1542 GetAdjustedTime() < nRelayUntil)
1543 {
1544 pnode->PushMessage("alert", *this);
1545 return true;
1546 }
1547 }
1548 return false;
1549 }
1550
1551 bool CheckSignature()
1552 {
1553 CKey key;
1554 if (!key.SetPubKey(ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284")))
1555 return error("CAlert::CheckSignature() : SetPubKey failed");
1556 if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
1557 return error("CAlert::CheckSignature() : verify signature failed");
1558
1559 // Now unserialize the data
1560 CDataStream sMsg(vchMsg);
1561 sMsg >> *(CUnsignedAlert*)this;
1562 return true;
1563 }
1564
1565 bool ProcessAlert();
1566};
1567
223b6f1b 1568#endif
This page took 0.222717 seconds and 4 git commands to generate.