upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/main.h
diff options
context:
space:
mode:
authorBitflash-sh <btf01@proton.me>2026-07-24 11:18:11 -0300
committerBitflash-sh <btf01@proton.me>2026-07-24 11:18:11 -0300
commit51d617e70f90a972185917ea0096c1ecef2bfa8b (patch)
tree9fbbcd867de9de9d0776afdd02f594ba312c46eb /src/main.h
Bitflash: fair-launch release
Satoshi's bitcoin-0.1.0 reborn with RandomX CPU proof of work, anonymous .btf addressing over Nostr with CGNAT rendezvous, automatic peer discovery, a headless Linux node, and Windows GUI wallet. Fair launch, no premine, 21M cap.
Diffstat (limited to 'src/main.h')
-rw-r--r--src/main.h1361
1 files changed, 1361 insertions, 0 deletions
diff --git a/src/main.h b/src/main.h
new file mode 100644
index 0000000..a369476
--- /dev/null
+++ b/src/main.h
@@ -0,0 +1,1361 @@
1// Copyright (c) 2009 Satoshi Nakamoto
2// Distributed under the MIT/X11 software license, see the accompanying
3// file license.txt or http://www.opensource.org/licenses/mit-license.php.
4
5class COutPoint;
6class CInPoint;
7class CDiskTxPos;
8class CCoinBase;
9class CTxIn;
10class CTxOut;
11class CTransaction;
12class CBlock;
13class CBlockIndex;
14class CWalletTx;
15class CKeyItem;
16
17static const unsigned int MAX_SIZE = 0x02000000;
18static const int64 COIN = 100000000;
19// Total Bitflash emission: identical to Bitcoin (21 million).
20// MAX_MONEY guards against the value overflow bug (CVE-2010-5139), which in
21// 2010 allowed creating 184 billion coins in a single transaction.
22static const int64 MAX_MONEY = 21000000 * COIN;
23inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
24static const int64 CENT = 1000000;
25static const int COINBASE_MATURITY = 100;
26
27// Bitflash difficulty floor. The PoW is RandomX (memory-hard), ~1000x slower
28// per hash than SHA-256d, so the target is much easier than Bitcoin's to let a
29// CPU network start with little hashrate. Difficulty rises on its own (retarget
30// toward 10-min blocks) as miners join. This does NOT affect emission
31// (21 million, halving every 210,000 blocks). Tunable.
32static const CBigNum bnProofOfWorkLimit(~uint256(0) >> 12);
33
34
35
36
37
38
39extern CCriticalSection cs_main;
40extern map<uint256, CBlockIndex*> mapBlockIndex;
41extern uint256 hashGenesisBlock;
42extern uint256 hashGenesisMerkleRoot;
43extern unsigned int GENESIS_NONCE;
44extern CBlockIndex* pindexGenesisBlock;
45extern int nBestHeight;
46extern uint256 hashBestChain;
47extern CBlockIndex* pindexBest;
48extern unsigned int nTransactionsUpdated;
49extern string strSetDataDir;
50extern int nDropMessagesTest;
51extern bool fSoloMineTest; // /solomine: mine without requiring a peer (local test)
52
53// Settings
54extern int fGenerateBitcoins;
55extern int64 nTransactionFee;
56extern CAddress addrIncoming;
57
58
59
60
61
62
63
64string GetAppDir();
65FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
66FILE* AppendBlockFile(unsigned int& nFileRet);
67bool AddKey(const CKey& key);
68vector<unsigned char> GenerateNewKey();
69bool AddToWallet(const CWalletTx& wtxIn);
70void ReacceptWalletTransactions();
71void RelayWalletTransactions();
72bool LoadBlockIndex(bool fAllowNew=true);
73void PrintBlockTree();
74bool BitcoinMiner();
75bool ProcessMessages(CNode* pfrom);
76bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv);
77bool SendMessages(CNode* pto);
78int64 GetBalance();
79bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& txNew, int64& nFeeRequiredRet);
80bool CommitTransactionSpent(const CWalletTx& wtxNew);
81bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew);
82
83
84
85
86
87
88
89
90
91
92
93class CDiskTxPos
94{
95public:
96 unsigned int nFile;
97 unsigned int nBlockPos;
98 unsigned int nTxPos;
99
100 CDiskTxPos()
101 {
102 SetNull();
103 }
104
105 CDiskTxPos(unsigned int nFileIn, unsigned int nBlockPosIn, unsigned int nTxPosIn)
106 {
107 nFile = nFileIn;
108 nBlockPos = nBlockPosIn;
109 nTxPos = nTxPosIn;
110 }
111
112 IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
113 void SetNull() { nFile = -1; nBlockPos = 0; nTxPos = 0; }
114 bool IsNull() const { return (nFile == -1); }
115
116 friend bool operator==(const CDiskTxPos& a, const CDiskTxPos& b)
117 {
118 return (a.nFile == b.nFile &&
119 a.nBlockPos == b.nBlockPos &&
120 a.nTxPos == b.nTxPos);
121 }
122
123 friend bool operator!=(const CDiskTxPos& a, const CDiskTxPos& b)
124 {
125 return !(a == b);
126 }
127
128 string ToString() const
129 {
130 if (IsNull())
131 return strprintf("null");
132 else
133 return strprintf("(nFile=%d, nBlockPos=%d, nTxPos=%d)", nFile, nBlockPos, nTxPos);
134 }
135
136 void print() const
137 {
138 printf("%s", ToString().c_str());
139 }
140};
141
142
143
144
145class CInPoint
146{
147public:
148 CTransaction* ptx;
149 unsigned int n;
150
151 CInPoint() { SetNull(); }
152 CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; }
153 void SetNull() { ptx = NULL; n = -1; }
154 bool IsNull() const { return (ptx == NULL && n == -1); }
155};
156
157
158
159
160class COutPoint
161{
162public:
163 uint256 hash;
164 unsigned int n;
165
166 COutPoint() { SetNull(); }
167 COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; }
168 IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
169 void SetNull() { hash = 0; n = -1; }
170 bool IsNull() const { return (hash == 0 && n == -1); }
171
172 friend bool operator<(const COutPoint& a, const COutPoint& b)
173 {
174 return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n));
175 }
176
177 friend bool operator==(const COutPoint& a, const COutPoint& b)
178 {
179 return (a.hash == b.hash && a.n == b.n);
180 }
181
182 friend bool operator!=(const COutPoint& a, const COutPoint& b)
183 {
184 return !(a == b);
185 }
186
187 string ToString() const
188 {
189 return strprintf("COutPoint(%s, %d)", hash.ToString().substr(0,6).c_str(), n);
190 }
191
192 void print() const
193 {
194 printf("%s\n", ToString().c_str());
195 }
196};
197
198
199
200
201//
202// An input of a transaction. It contains the location of the previous
203// transaction's output that it claims and a signature that matches the
204// output's public key.
205//
206class CTxIn
207{
208public:
209 COutPoint prevout;
210 CScript scriptSig;
211 unsigned int nSequence;
212
213 CTxIn()
214 {
215 nSequence = UINT_MAX;
216 }
217
218 explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)
219 {
220 prevout = prevoutIn;
221 scriptSig = scriptSigIn;
222 nSequence = nSequenceIn;
223 }
224
225 CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)
226 {
227 prevout = COutPoint(hashPrevTx, nOut);
228 scriptSig = scriptSigIn;
229 nSequence = nSequenceIn;
230 }
231
232 IMPLEMENT_SERIALIZE
233 (
234 READWRITE(prevout);
235 READWRITE(scriptSig);
236 READWRITE(nSequence);
237 )
238
239 bool IsFinal() const
240 {
241 return (nSequence == UINT_MAX);
242 }
243
244 friend bool operator==(const CTxIn& a, const CTxIn& b)
245 {
246 return (a.prevout == b.prevout &&
247 a.scriptSig == b.scriptSig &&
248 a.nSequence == b.nSequence);
249 }
250
251 friend bool operator!=(const CTxIn& a, const CTxIn& b)
252 {
253 return !(a == b);
254 }
255
256 string ToString() const
257 {
258 string str;
259 str += strprintf("CTxIn(");
260 str += prevout.ToString();
261 if (prevout.IsNull())
262 str += strprintf(", coinbase %s", HexStr(scriptSig.begin(), scriptSig.end(), false).c_str());
263 else
264 str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
265 if (nSequence != UINT_MAX)
266 str += strprintf(", nSequence=%u", nSequence);
267 str += ")";
268 return str;
269 }
270
271 void print() const
272 {
273 printf("%s\n", ToString().c_str());
274 }
275
276 bool IsMine() const;
277 int64 GetDebit() const;
278};
279
280
281
282
283//
284// An output of a transaction. It contains the public key that the next input
285// must be able to sign with to claim it.
286//
287class CTxOut
288{
289public:
290 int64 nValue;
291 CScript scriptPubKey;
292
293public:
294 CTxOut()
295 {
296 SetNull();
297 }
298
299 CTxOut(int64 nValueIn, CScript scriptPubKeyIn)
300 {
301 nValue = nValueIn;
302 scriptPubKey = scriptPubKeyIn;
303 }
304
305 IMPLEMENT_SERIALIZE
306 (
307 READWRITE(nValue);
308 READWRITE(scriptPubKey);
309 )
310
311 void SetNull()
312 {
313 nValue = -1;
314 scriptPubKey.clear();
315 }
316
317 bool IsNull()
318 {
319 return (nValue == -1);
320 }
321
322 uint256 GetHash() const
323 {
324 return SerializeHash(*this);
325 }
326
327 bool IsMine() const
328 {
329 return ::IsMine(scriptPubKey);
330 }
331
332 int64 GetCredit() const
333 {
334 if (IsMine())
335 return nValue;
336 return 0;
337 }
338
339 friend bool operator==(const CTxOut& a, const CTxOut& b)
340 {
341 return (a.nValue == b.nValue &&
342 a.scriptPubKey == b.scriptPubKey);
343 }
344
345 friend bool operator!=(const CTxOut& a, const CTxOut& b)
346 {
347 return !(a == b);
348 }
349
350 string ToString() const
351 {
352 if (scriptPubKey.size() < 6)
353 return "CTxOut(error)";
354 return strprintf("CTxOut(nValue=%I64d.%08I64d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,24).c_str());
355 }
356
357 void print() const
358 {
359 printf("%s\n", ToString().c_str());
360 }
361};
362
363
364
365
366//
367// The basic transaction that is broadcasted on the network and contained in
368// blocks. A transaction can contain multiple inputs and outputs.
369//
370class CTransaction
371{
372public:
373 int nVersion;
374 vector<CTxIn> vin;
375 vector<CTxOut> vout;
376 int nLockTime;
377
378
379 CTransaction()
380 {
381 SetNull();
382 }
383
384 IMPLEMENT_SERIALIZE
385 (
386 READWRITE(this->nVersion);
387 nVersion = this->nVersion;
388 READWRITE(vin);
389 READWRITE(vout);
390 READWRITE(nLockTime);
391 )
392
393 void SetNull()
394 {
395 nVersion = 1;
396 vin.clear();
397 vout.clear();
398 nLockTime = 0;
399 }
400
401 bool IsNull() const
402 {
403 return (vin.empty() && vout.empty());
404 }
405
406 uint256 GetHash() const
407 {
408 return SerializeHash(*this);
409 }
410
411 bool IsFinal() const
412 {
413 if (nLockTime == 0 || nLockTime < nBestHeight)
414 return true;
415 foreach(const CTxIn& txin, vin)
416 if (!txin.IsFinal())
417 return false;
418 return true;
419 }
420
421 bool IsNewerThan(const CTransaction& old) const
422 {
423 if (vin.size() != old.vin.size())
424 return false;
425 for (int i = 0; i < vin.size(); i++)
426 if (vin[i].prevout != old.vin[i].prevout)
427 return false;
428
429 bool fNewer = false;
430 unsigned int nLowest = UINT_MAX;
431 for (int i = 0; i < vin.size(); i++)
432 {
433 if (vin[i].nSequence != old.vin[i].nSequence)
434 {
435 if (vin[i].nSequence <= nLowest)
436 {
437 fNewer = false;
438 nLowest = vin[i].nSequence;
439 }
440 if (old.vin[i].nSequence < nLowest)
441 {
442 fNewer = true;
443 nLowest = old.vin[i].nSequence;
444 }
445 }
446 }
447 return fNewer;
448 }
449
450 bool IsCoinBase() const
451 {
452 return (vin.size() == 1 && vin[0].prevout.IsNull());
453 }
454
455 bool CheckTransaction() const
456 {
457 // Basic checks that don't depend on any context
458 if (vin.empty() || vout.empty())
459 return error("CTransaction::CheckTransaction() : vin or vout empty");
460
461 // Check for negative or overflow output values (CVE-2010-5139)
462 int64 nValueOut = 0;
463 foreach(const CTxOut& txout, vout)
464 {
465 if (txout.nValue < 0)
466 return error("CTransaction::CheckTransaction() : txout.nValue negative");
467 if (txout.nValue > MAX_MONEY)
468 return error("CTransaction::CheckTransaction() : txout.nValue too high");
469 nValueOut += txout.nValue;
470 if (!MoneyRange(nValueOut))
471 return error("CTransaction::CheckTransaction() : txout total out of range");
472 }
473
474 if (IsCoinBase())
475 {
476 if (vin[0].scriptSig.size() < 2 || vin[0].scriptSig.size() > 100)
477 return error("CTransaction::CheckTransaction() : coinbase script size");
478 }
479 else
480 {
481 foreach(const CTxIn& txin, vin)
482 if (txin.prevout.IsNull())
483 return error("CTransaction::CheckTransaction() : prevout is null");
484 }
485
486 // Check for duplicate inputs (a tx spending the same output twice)
487 set<COutPoint> vInOutPoints;
488 foreach(const CTxIn& txin, vin)
489 {
490 if (vInOutPoints.count(txin.prevout))
491 return error("CTransaction::CheckTransaction() : duplicate inputs");
492 vInOutPoints.insert(txin.prevout);
493 }
494
495 return true;
496 }
497
498 bool IsMine() const
499 {
500 foreach(const CTxOut& txout, vout)
501 if (txout.IsMine())
502 return true;
503 return false;
504 }
505
506 int64 GetDebit() const
507 {
508 int64 nDebit = 0;
509 foreach(const CTxIn& txin, vin)
510 nDebit += txin.GetDebit();
511 return nDebit;
512 }
513
514 int64 GetCredit() const
515 {
516 int64 nCredit = 0;
517 foreach(const CTxOut& txout, vout)
518 nCredit += txout.GetCredit();
519 return nCredit;
520 }
521
522 int64 GetValueOut() const
523 {
524 int64 nValueOut = 0;
525 foreach(const CTxOut& txout, vout)
526 {
527 if (txout.nValue < 0)
528 throw runtime_error("CTransaction::GetValueOut() : negative value");
529 if (txout.nValue > MAX_MONEY)
530 throw runtime_error("CTransaction::GetValueOut() : value too high");
531 nValueOut += txout.nValue;
532 if (!MoneyRange(nValueOut))
533 throw runtime_error("CTransaction::GetValueOut() : total out of range");
534 }
535 return nValueOut;
536 }
537
538 int64 GetMinFee(bool fDiscount=false) const
539 {
540 unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK);
541 if (fDiscount && nBytes < 10000)
542 return 0;
543 return (1 + (int64)nBytes / 1000) * CENT;
544 }
545
546
547
548 bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL)
549 {
550 CAutoFile filein = OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb");
551 if (!filein)
552 return error("CTransaction::ReadFromDisk() : OpenBlockFile failed");
553
554 // Read transaction
555 if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
556 return error("CTransaction::ReadFromDisk() : fseek failed");
557 filein >> *this;
558
559 // Return file pointer
560 if (pfileRet)
561 {
562 if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
563 return error("CTransaction::ReadFromDisk() : second fseek failed");
564 *pfileRet = filein.release();
565 }
566 return true;
567 }
568
569
570 friend bool operator==(const CTransaction& a, const CTransaction& b)
571 {
572 return (a.nVersion == b.nVersion &&
573 a.vin == b.vin &&
574 a.vout == b.vout &&
575 a.nLockTime == b.nLockTime);
576 }
577
578 friend bool operator!=(const CTransaction& a, const CTransaction& b)
579 {
580 return !(a == b);
581 }
582
583
584 string ToString() const
585 {
586 string str;
587 str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n",
588 GetHash().ToString().substr(0,6).c_str(),
589 nVersion,
590 vin.size(),
591 vout.size(),
592 nLockTime);
593 for (int i = 0; i < vin.size(); i++)
594 str += " " + vin[i].ToString() + "\n";
595 for (int i = 0; i < vout.size(); i++)
596 str += " " + vout[i].ToString() + "\n";
597 return str;
598 }
599
600 void print() const
601 {
602 printf("%s", ToString().c_str());
603 }
604
605
606
607 bool DisconnectInputs(CTxDB& txdb);
608 bool ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx, int nHeight, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee=0);
609 bool ClientConnectInputs();
610
611 bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
612
613 bool AcceptTransaction(bool fCheckInputs=true, bool* pfMissingInputs=NULL)
614 {
615 CTxDB txdb("r");
616 return AcceptTransaction(txdb, fCheckInputs, pfMissingInputs);
617 }
618
619protected:
620 bool AddToMemoryPool();
621public:
622 bool RemoveFromMemoryPool();
623};
624
625
626
627
628
629//
630// A transaction with a merkle branch linking it to the block chain
631//
632class CMerkleTx : public CTransaction
633{
634public:
635 uint256 hashBlock;
636 vector<uint256> vMerkleBranch;
637 int nIndex;
638
639 // memory only
640 mutable bool fMerkleVerified;
641
642
643 CMerkleTx()
644 {
645 Init();
646 }
647
648 CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
649 {
650 Init();
651 }
652
653 void Init()
654 {
655 hashBlock = 0;
656 nIndex = -1;
657 fMerkleVerified = false;
658 }
659
660 int64 GetCredit() const
661 {
662 // Must wait until coinbase is safely deep enough in the chain before valuing it
663 if (IsCoinBase() && GetBlocksToMaturity() > 0)
664 return 0;
665 return CTransaction::GetCredit();
666 }
667
668 IMPLEMENT_SERIALIZE
669 (
670 nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);
671 nVersion = this->nVersion;
672 READWRITE(hashBlock);
673 READWRITE(vMerkleBranch);
674 READWRITE(nIndex);
675 )
676
677
678 int SetMerkleBranch(const CBlock* pblock=NULL);
679 int GetDepthInMainChain() const;
680 bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
681 int GetBlocksToMaturity() const;
682 bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true);
683 bool AcceptTransaction() { CTxDB txdb("r"); return AcceptTransaction(txdb); }
684};
685
686
687
688
689//
690// A transaction with a bunch of additional info that only the owner cares
691// about. It includes any unrecorded transactions needed to link it back
692// to the block chain.
693//
694class CWalletTx : public CMerkleTx
695{
696public:
697 vector<CMerkleTx> vtxPrev;
698 map<string, string> mapValue;
699 vector<pair<string, string> > vOrderForm;
700 unsigned int fTimeReceivedIsTxTime;
701 unsigned int nTimeReceived; // time received by this node
702 char fFromMe;
703 char fSpent;
704 //// probably need to sign the order info so know it came from payer
705
706 // memory only
707 mutable unsigned int nTimeDisplayed;
708
709
710 CWalletTx()
711 {
712 Init();
713 }
714
715 CWalletTx(const CMerkleTx& txIn) : CMerkleTx(txIn)
716 {
717 Init();
718 }
719
720 CWalletTx(const CTransaction& txIn) : CMerkleTx(txIn)
721 {
722 Init();
723 }
724
725 void Init()
726 {
727 fTimeReceivedIsTxTime = false;
728 nTimeReceived = 0;
729 fFromMe = false;
730 fSpent = false;
731 nTimeDisplayed = 0;
732 }
733
734 IMPLEMENT_SERIALIZE
735 (
736 nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion, ser_action);
737 nVersion = this->nVersion;
738 READWRITE(vtxPrev);
739 READWRITE(mapValue);
740 READWRITE(vOrderForm);
741 READWRITE(fTimeReceivedIsTxTime);
742 READWRITE(nTimeReceived);
743 READWRITE(fFromMe);
744 READWRITE(fSpent);
745 )
746
747 bool WriteToDisk()
748 {
749 return CWalletDB().WriteTx(GetHash(), *this);
750 }
751
752
753 int64 GetTxTime() const;
754
755 void AddSupportingTransactions(CTxDB& txdb);
756
757 bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);
758 bool AcceptWalletTransaction() { CTxDB txdb("r"); return AcceptWalletTransaction(txdb); }
759
760 void RelayWalletTransaction(CTxDB& txdb);
761 void RelayWalletTransaction() { CTxDB txdb("r"); RelayWalletTransaction(txdb); }
762};
763
764
765
766
767//
768// A txdb record that contains the disk location of a transaction and the
769// locations of transactions that spend its outputs. vSpent is really only
770// used as a flag, but having the location is very helpful for debugging.
771//
772class CTxIndex
773{
774public:
775 CDiskTxPos pos;
776 vector<CDiskTxPos> vSpent;
777
778 CTxIndex()
779 {
780 SetNull();
781 }
782
783 CTxIndex(const CDiskTxPos& posIn, unsigned int nOutputs)
784 {
785 pos = posIn;
786 vSpent.resize(nOutputs);
787 }
788
789 IMPLEMENT_SERIALIZE
790 (
791 if (!(nType & SER_GETHASH))
792 READWRITE(nVersion);
793 READWRITE(pos);
794 READWRITE(vSpent);
795 )
796
797 void SetNull()
798 {
799 pos.SetNull();
800 vSpent.clear();
801 }
802
803 bool IsNull()
804 {
805 return pos.IsNull();
806 }
807
808 friend bool operator==(const CTxIndex& a, const CTxIndex& b)
809 {
810 if (a.pos != b.pos || a.vSpent.size() != b.vSpent.size())
811 return false;
812 for (int i = 0; i < a.vSpent.size(); i++)
813 if (a.vSpent[i] != b.vSpent[i])
814 return false;
815 return true;
816 }
817
818 friend bool operator!=(const CTxIndex& a, const CTxIndex& b)
819 {
820 return !(a == b);
821 }
822};
823
824
825
826
827
828//
829// Nodes collect new transactions into a block, hash them into a hash tree,
830// and scan through nonce values to make the block's hash satisfy proof-of-work
831// requirements. When they solve the proof-of-work, they broadcast the block
832// to everyone and the block is added to the block chain. The first transaction
833// in the block is a special one that creates a new coin owned by the creator
834// of the block.
835//
836// Blocks are appended to blk0001.dat files on disk. Their location on disk
837// is indexed by CBlockIndex objects in memory.
838//
839class CBlock
840{
841public:
842 // header
843 int nVersion;
844 uint256 hashPrevBlock;
845 uint256 hashMerkleRoot;
846 unsigned int nTime;
847 unsigned int nBits;
848 unsigned int nNonce;
849
850 // network and disk
851 vector<CTransaction> vtx;
852
853 // memory only
854 mutable vector<uint256> vMerkleTree;
855
856
857 CBlock()
858 {
859 SetNull();
860 }
861
862 IMPLEMENT_SERIALIZE
863 (
864 READWRITE(this->nVersion);
865 nVersion = this->nVersion;
866 READWRITE(hashPrevBlock);
867 READWRITE(hashMerkleRoot);
868 READWRITE(nTime);
869 READWRITE(nBits);
870 READWRITE(nNonce);
871
872 // ConnectBlock depends on vtx being last so it can calculate offset
873 if (!(nType & (SER_GETHASH|SER_BLOCKHEADERONLY)))
874 READWRITE(vtx);
875 else if (fRead)
876 const_cast<CBlock*>(this)->vtx.clear();
877 )
878
879 void SetNull()
880 {
881 nVersion = 1;
882 hashPrevBlock = 0;
883 hashMerkleRoot = 0;
884 nTime = 0;
885 nBits = 0;
886 nNonce = 0;
887 vtx.clear();
888 vMerkleTree.clear();
889 }
890
891 bool IsNull() const
892 {
893 return (nBits == 0);
894 }
895
896 uint256 GetHash() const
897 {
898 // Block IDENTITY hash (SHA-256d), used for indexing.
899 return Hash(BEGIN(nVersion), END(nNonce));
900 }
901
902 uint256 GetPoWHash() const
903 {
904 // Memory-hard PROOF-OF-WORK hash (RandomX) over the 80-byte header.
905 // This is the one that must be <= target (nBits).
906 return RandomXPoWHash((const void*)BEGIN(nVersion), END(nNonce) - BEGIN(nVersion));
907 }
908
909
910 uint256 BuildMerkleTree() const
911 {
912 vMerkleTree.clear();
913 foreach(const CTransaction& tx, vtx)
914 vMerkleTree.push_back(tx.GetHash());
915 int j = 0;
916 for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
917 {
918 for (int i = 0; i < nSize; i += 2)
919 {
920 int i2 = min(i+1, nSize-1);
921 vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]),
922 BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
923 }
924 j += nSize;
925 }
926 return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
927 }
928
929 vector<uint256> GetMerkleBranch(int nIndex) const
930 {
931 if (vMerkleTree.empty())
932 BuildMerkleTree();
933 vector<uint256> vMerkleBranch;
934 int j = 0;
935 for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
936 {
937 int i = min(nIndex^1, nSize-1);
938 vMerkleBranch.push_back(vMerkleTree[j+i]);
939 nIndex >>= 1;
940 j += nSize;
941 }
942 return vMerkleBranch;
943 }
944
945 static uint256 CheckMerkleBranch(uint256 hash, const vector<uint256>& vMerkleBranch, int nIndex)
946 {
947 if (nIndex == -1)
948 return 0;
949 foreach(const uint256& otherside, vMerkleBranch)
950 {
951 if (nIndex & 1)
952 hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
953 else
954 hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));
955 nIndex >>= 1;
956 }
957 return hash;
958 }
959
960
961 bool WriteToDisk(bool fWriteTransactions, unsigned int& nFileRet, unsigned int& nBlockPosRet)
962 {
963 // Open history file to append
964 CAutoFile fileout = AppendBlockFile(nFileRet);
965 if (!fileout)
966 return error("CBlock::WriteToDisk() : AppendBlockFile failed");
967 if (!fWriteTransactions)
968 fileout.nType |= SER_BLOCKHEADERONLY;
969
970 // Write index header
971 unsigned int nSize = fileout.GetSerializeSize(*this);
972 fileout << FLATDATA(pchMessageStart) << nSize;
973
974 // Write block
975 nBlockPosRet = ftell(fileout);
976 if (nBlockPosRet == -1)
977 return error("CBlock::WriteToDisk() : ftell failed");
978 fileout << *this;
979
980 return true;
981 }
982
983 bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions)
984 {
985 SetNull();
986
987 // Open history file to read
988 CAutoFile filein = OpenBlockFile(nFile, nBlockPos, "rb");
989 if (!filein)
990 return error("CBlock::ReadFromDisk() : OpenBlockFile failed");
991 if (!fReadTransactions)
992 filein.nType |= SER_BLOCKHEADERONLY;
993
994 // Read block
995 filein >> *this;
996
997 // Check the header
998 if (CBigNum().SetCompact(nBits) > bnProofOfWorkLimit)
999 return error("CBlock::ReadFromDisk() : nBits errors in block header");
1000 // NOTE: the proof of work is RandomX (GetPoWHash), validated once by
1001 // CheckBlock when the block is accepted. Re-checking it on every disk
1002 // read would be prohibitively slow, and checking the SHA-256d GetHash()
1003 // here (a leftover from Bitcoin) is simply wrong for a RandomX chain.
1004
1005 return true;
1006 }
1007
1008
1009
1010 void print() const
1011 {
1012 printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%d)\n",
1013 GetHash().ToString().substr(0,14).c_str(),
1014 nVersion,
1015 hashPrevBlock.ToString().substr(0,14).c_str(),
1016 hashMerkleRoot.ToString().substr(0,6).c_str(),
1017 nTime, nBits, nNonce,
1018 vtx.size());
1019 for (int i = 0; i < vtx.size(); i++)
1020 {
1021 printf(" ");
1022 vtx[i].print();
1023 }
1024 printf(" vMerkleTree: ");
1025 for (int i = 0; i < vMerkleTree.size(); i++)
1026 printf("%s ", vMerkleTree[i].ToString().substr(0,6).c_str());
1027 printf("\n");
1028 }
1029
1030
1031 int64 GetBlockValue(int64 nFees) const;
1032 bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);
1033 bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex);
1034 bool ReadFromDisk(const CBlockIndex* blockindex, bool fReadTransactions);
1035 bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);
1036 bool CheckBlock() const;
1037 bool AcceptBlock();
1038};
1039
1040
1041
1042
1043
1044
1045//
1046// The block chain is a tree shaped structure starting with the
1047// genesis block at the root, with each block potentially having multiple
1048// candidates to be the next block. pprev and pnext link a path through the
1049// main/longest chain. A blockindex may have multiple pprev pointing back
1050// to it, but pnext will only point forward to the longest branch, or will
1051// be null if the block is not part of the longest chain.
1052//
1053class CBlockIndex
1054{
1055public:
1056 const uint256* phashBlock;
1057 CBlockIndex* pprev;
1058 CBlockIndex* pnext;
1059 unsigned int nFile;
1060 unsigned int nBlockPos;
1061 int nHeight;
1062
1063 // block header
1064 int nVersion;
1065 uint256 hashMerkleRoot;
1066 unsigned int nTime;
1067 unsigned int nBits;
1068 unsigned int nNonce;
1069
1070
1071 CBlockIndex()
1072 {
1073 phashBlock = NULL;
1074 pprev = NULL;
1075 pnext = NULL;
1076 nFile = 0;
1077 nBlockPos = 0;
1078 nHeight = 0;
1079
1080 nVersion = 0;
1081 hashMerkleRoot = 0;
1082 nTime = 0;
1083 nBits = 0;
1084 nNonce = 0;
1085 }
1086
1087 CBlockIndex(unsigned int nFileIn, unsigned int nBlockPosIn, CBlock& block)
1088 {
1089 phashBlock = NULL;
1090 pprev = NULL;
1091 pnext = NULL;
1092 nFile = nFileIn;
1093 nBlockPos = nBlockPosIn;
1094 nHeight = 0;
1095
1096 nVersion = block.nVersion;
1097 hashMerkleRoot = block.hashMerkleRoot;
1098 nTime = block.nTime;
1099 nBits = block.nBits;
1100 nNonce = block.nNonce;
1101 }
1102
1103 uint256 GetBlockHash() const
1104 {
1105 return *phashBlock;
1106 }
1107
1108 bool IsInMainChain() const
1109 {
1110 return (pnext || this == pindexBest);
1111 }
1112
1113 bool EraseBlockFromDisk()
1114 {
1115 // Open history file
1116 CAutoFile fileout = OpenBlockFile(nFile, nBlockPos, "rb+");
1117 if (!fileout)
1118 return false;
1119
1120 // Overwrite with empty null block
1121 CBlock block;
1122 block.SetNull();
1123 fileout << block;
1124
1125 return true;
1126 }
1127
1128 enum { nMedianTimeSpan=11 };
1129
1130 int64 GetMedianTimePast() const
1131 {
1132 unsigned int pmedian[nMedianTimeSpan];
1133 unsigned int* pbegin = &pmedian[nMedianTimeSpan];
1134 unsigned int* pend = &pmedian[nMedianTimeSpan];
1135
1136 const CBlockIndex* pindex = this;
1137 for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
1138 *(--pbegin) = pindex->nTime;
1139
1140 sort(pbegin, pend);
1141 return pbegin[(pend - pbegin)/2];
1142 }
1143
1144 int64 GetMedianTime() const
1145 {
1146 const CBlockIndex* pindex = this;
1147 for (int i = 0; i < nMedianTimeSpan/2; i++)
1148 {
1149 if (!pindex->pnext)
1150 return nTime;
1151 pindex = pindex->pnext;
1152 }
1153 return pindex->GetMedianTimePast();
1154 }
1155
1156
1157
1158 string ToString() const
1159 {
1160 return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)",
1161 pprev, pnext, nFile, nBlockPos, nHeight,
1162 hashMerkleRoot.ToString().substr(0,6).c_str(),
1163 GetBlockHash().ToString().substr(0,14).c_str());
1164 }
1165
1166 void print() const
1167 {
1168 printf("%s\n", ToString().c_str());
1169 }
1170};
1171
1172
1173
1174//
1175// Used to marshal pointers into hashes for db storage.
1176//
1177class CDiskBlockIndex : public CBlockIndex
1178{
1179public:
1180 uint256 hashPrev;
1181 uint256 hashNext;
1182
1183 CDiskBlockIndex()
1184 {
1185 hashPrev = 0;
1186 hashNext = 0;
1187 }
1188
1189 explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex)
1190 {
1191 hashPrev = (pprev ? pprev->GetBlockHash() : 0);
1192 hashNext = (pnext ? pnext->GetBlockHash() : 0);
1193 }
1194
1195 IMPLEMENT_SERIALIZE
1196 (
1197 if (!(nType & SER_GETHASH))
1198 READWRITE(nVersion);
1199
1200 READWRITE(hashNext);
1201 READWRITE(nFile);
1202 READWRITE(nBlockPos);
1203 READWRITE(nHeight);
1204
1205 // block header
1206 READWRITE(this->nVersion);
1207 READWRITE(hashPrev);
1208 READWRITE(hashMerkleRoot);
1209 READWRITE(nTime);
1210 READWRITE(nBits);
1211 READWRITE(nNonce);
1212 )
1213
1214 uint256 GetBlockHash() const
1215 {
1216 CBlock block;
1217 block.nVersion = nVersion;
1218 block.hashPrevBlock = hashPrev;
1219 block.hashMerkleRoot = hashMerkleRoot;
1220 block.nTime = nTime;
1221 block.nBits = nBits;
1222 block.nNonce = nNonce;
1223 return block.GetHash();
1224 }
1225
1226
1227 string ToString() const
1228 {
1229 string str = "CDiskBlockIndex(";
1230 str += CBlockIndex::ToString();
1231 str += strprintf("\n hashBlock=%s, hashPrev=%s, hashNext=%s)",
1232 GetBlockHash().ToString().c_str(),
1233 hashPrev.ToString().substr(0,14).c_str(),
1234 hashNext.ToString().substr(0,14).c_str());
1235 return str;
1236 }
1237
1238 void print() const
1239 {
1240 printf("%s\n", ToString().c_str());
1241 }
1242};
1243
1244
1245
1246
1247
1248
1249
1250
1251//
1252// Describes a place in the block chain to another node such that if the
1253// other node doesn't have the same branch, it can find a recent common trunk.
1254// The further back it is, the further before the fork it may be.
1255//
1256class CBlockLocator
1257{
1258protected:
1259 vector<uint256> vHave;
1260public:
1261
1262 CBlockLocator()
1263 {
1264 }
1265
1266 explicit CBlockLocator(const CBlockIndex* pindex)
1267 {
1268 Set(pindex);
1269 }
1270
1271 explicit CBlockLocator(uint256 hashBlock)
1272 {
1273 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
1274 if (mi != mapBlockIndex.end())
1275 Set((*mi).second);
1276 }
1277
1278 IMPLEMENT_SERIALIZE
1279 (
1280 if (!(nType & SER_GETHASH))
1281 READWRITE(nVersion);
1282 READWRITE(vHave);
1283 )
1284
1285 void Set(const CBlockIndex* pindex)
1286 {
1287 vHave.clear();
1288 int nStep = 1;
1289 while (pindex)
1290 {
1291 vHave.push_back(pindex->GetBlockHash());
1292
1293 // Exponentially larger steps back
1294 for (int i = 0; pindex && i < nStep; i++)
1295 pindex = pindex->pprev;
1296 if (vHave.size() > 10)
1297 nStep *= 2;
1298 }
1299 vHave.push_back(hashGenesisBlock);
1300 }
1301
1302 CBlockIndex* GetBlockIndex()
1303 {
1304 // Find the first block the caller has in the main chain
1305 foreach(const uint256& hash, vHave)
1306 {
1307 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
1308 if (mi != mapBlockIndex.end())
1309 {
1310 CBlockIndex* pindex = (*mi).second;
1311 if (pindex->IsInMainChain())
1312 return pindex;
1313 }
1314 }
1315 return pindexGenesisBlock;
1316 }
1317
1318 uint256 GetBlockHash()
1319 {
1320 // Find the first block the caller has in the main chain
1321 foreach(const uint256& hash, vHave)
1322 {
1323 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
1324 if (mi != mapBlockIndex.end())
1325 {
1326 CBlockIndex* pindex = (*mi).second;
1327 if (pindex->IsInMainChain())
1328 return hash;
1329 }
1330 }
1331 return hashGenesisBlock;
1332 }
1333
1334 int GetHeight()
1335 {
1336 CBlockIndex* pindex = GetBlockIndex();
1337 if (!pindex)
1338 return 0;
1339 return pindex->nHeight;
1340 }
1341};
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354extern map<uint256, CTransaction> mapTransactions;
1355extern map<uint256, CWalletTx> mapWallet;
1356extern vector<pair<uint256, bool> > vWalletUpdated;
1357extern CCriticalSection cs_mapWallet;
1358extern map<vector<unsigned char>, CPrivKey> mapKeys;
1359extern map<uint160, vector<unsigned char> > mapPubKeys;
1360extern CCriticalSection cs_mapKeys;
1361extern CKey keyUser;