upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/main.cpp
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.cpp
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.cpp')
-rw-r--r--src/main.cpp2696
1 files changed, 2696 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..1dbce58
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,2696 @@
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
5#include "headers.h"
6#include "sha.h"
7
8
9
10
11
12//
13// Global state
14//
15
16CCriticalSection cs_main;
17
18map<uint256, CTransaction> mapTransactions;
19CCriticalSection cs_mapTransactions;
20unsigned int nTransactionsUpdated = 0;
21map<COutPoint, CInPoint> mapNextTx;
22
23map<uint256, CBlockIndex*> mapBlockIndex;
24// Bitflash genesis -- mined under RandomX PoW on 2026-07-22
25// (nTime 1753142400, nBits 0x1f0fffff, RandomX key "Bitflash/RandomX/v1/...")
26// Bitflash 2026 stable relaunch genesis (2-min blocks, RandomX). Mined values.
27unsigned int GENESIS_NONCE = 3141;
28uint256 hashGenesisBlock("0x5bd7cb255d814e48cebcdfb72da4dc87b34bd774227f8ceb546c5640f4bdc169");
29uint256 hashGenesisMerkleRoot("0x1a45b4482532abb29b10e234d3f13132230525a339ecea91658ffa675a5b1325");
30CBlockIndex* pindexGenesisBlock = NULL;
31int nBestHeight = -1;
32uint256 hashBestChain = 0;
33CBlockIndex* pindexBest = NULL;
34
35map<uint256, CBlock*> mapOrphanBlocks;
36multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
37
38map<uint256, CDataStream*> mapOrphanTransactions;
39multimap<uint256, CDataStream*> mapOrphanTransactionsByPrev;
40
41map<uint256, CWalletTx> mapWallet;
42vector<pair<uint256, bool> > vWalletUpdated;
43CCriticalSection cs_mapWallet;
44
45map<vector<unsigned char>, CPrivKey> mapKeys;
46map<uint160, vector<unsigned char> > mapPubKeys;
47CCriticalSection cs_mapKeys;
48CKey keyUser;
49
50string strSetDataDir;
51int nDropMessagesTest = 0;
52bool fSoloMineTest = false; // /solomine: mine without requiring a peer (local test)
53
54// Settings
55int fGenerateBitcoins;
56int64 nTransactionFee = 0;
57CAddress addrIncoming;
58
59
60
61
62
63
64
65
66//////////////////////////////////////////////////////////////////////////////
67//
68// mapKeys
69//
70
71bool AddKey(const CKey& key)
72{
73 CRITICAL_BLOCK(cs_mapKeys)
74 {
75 mapKeys[key.GetPubKey()] = key.GetPrivKey();
76 mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
77 }
78 return CWalletDB().WriteKey(key.GetPubKey(), key.GetPrivKey());
79}
80
81vector<unsigned char> GenerateNewKey()
82{
83 CKey key;
84 key.MakeNewKey();
85 if (!AddKey(key))
86 throw runtime_error("GenerateNewKey() : AddKey failed\n");
87 return key.GetPubKey();
88}
89
90
91
92
93//////////////////////////////////////////////////////////////////////////////
94//
95// mapWallet
96//
97
98bool AddToWallet(const CWalletTx& wtxIn)
99{
100 uint256 hash = wtxIn.GetHash();
101 CRITICAL_BLOCK(cs_mapWallet)
102 {
103 // Inserts only if not already there, returns tx inserted or tx found
104 pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
105 CWalletTx& wtx = (*ret.first).second;
106 bool fInsertedNew = ret.second;
107 if (fInsertedNew)
108 wtx.nTimeReceived = GetAdjustedTime();
109
110 //// debug print
111 printf("AddToWallet %s %s\n", wtxIn.GetHash().ToString().substr(0,6).c_str(), fInsertedNew ? "new" : "update");
112
113 if (!fInsertedNew)
114 {
115 // Merge
116 bool fUpdated = false;
117 if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
118 {
119 wtx.hashBlock = wtxIn.hashBlock;
120 fUpdated = true;
121 }
122 if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
123 {
124 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
125 wtx.nIndex = wtxIn.nIndex;
126 fUpdated = true;
127 }
128 if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
129 {
130 wtx.fFromMe = wtxIn.fFromMe;
131 fUpdated = true;
132 }
133 if (wtxIn.fSpent && wtxIn.fSpent != wtx.fSpent)
134 {
135 wtx.fSpent = wtxIn.fSpent;
136 fUpdated = true;
137 }
138 if (!fUpdated)
139 return true;
140 }
141
142 // Write to disk
143 if (!wtx.WriteToDisk())
144 return false;
145
146 // Notify UI
147 vWalletUpdated.push_back(make_pair(hash, fInsertedNew));
148 }
149
150 // Refresh UI
151 MainFrameRepaint();
152 return true;
153}
154
155bool AddToWalletIfMine(const CTransaction& tx, const CBlock* pblock)
156{
157 if (tx.IsMine() || mapWallet.count(tx.GetHash()))
158 {
159 CWalletTx wtx(tx);
160 // Get merkle branch if transaction was found in a block
161 if (pblock)
162 wtx.SetMerkleBranch(pblock);
163 return AddToWallet(wtx);
164 }
165 return true;
166}
167
168bool EraseFromWallet(uint256 hash)
169{
170 CRITICAL_BLOCK(cs_mapWallet)
171 {
172 if (mapWallet.erase(hash))
173 CWalletDB().EraseTx(hash);
174 }
175 return true;
176}
177
178
179
180
181
182
183
184
185
186//////////////////////////////////////////////////////////////////////////////
187//
188// mapOrphanTransactions
189//
190
191void AddOrphanTx(const CDataStream& vMsg)
192{
193 CTransaction tx;
194 CDataStream(vMsg) >> tx;
195 uint256 hash = tx.GetHash();
196 if (mapOrphanTransactions.count(hash))
197 return;
198 CDataStream* pvMsg = mapOrphanTransactions[hash] = new CDataStream(vMsg);
199 foreach(const CTxIn& txin, tx.vin)
200 mapOrphanTransactionsByPrev.insert(make_pair(txin.prevout.hash, pvMsg));
201}
202
203void EraseOrphanTx(uint256 hash)
204{
205 if (!mapOrphanTransactions.count(hash))
206 return;
207 const CDataStream* pvMsg = mapOrphanTransactions[hash];
208 CTransaction tx;
209 CDataStream(*pvMsg) >> tx;
210 foreach(const CTxIn& txin, tx.vin)
211 {
212 for (multimap<uint256, CDataStream*>::iterator mi = mapOrphanTransactionsByPrev.lower_bound(txin.prevout.hash);
213 mi != mapOrphanTransactionsByPrev.upper_bound(txin.prevout.hash);)
214 {
215 if ((*mi).second == pvMsg)
216 mapOrphanTransactionsByPrev.erase(mi++);
217 else
218 mi++;
219 }
220 }
221 delete pvMsg;
222 mapOrphanTransactions.erase(hash);
223}
224
225
226
227
228
229
230
231
232//////////////////////////////////////////////////////////////////////////////
233//
234// CTransaction
235//
236
237bool CTxIn::IsMine() const
238{
239 CRITICAL_BLOCK(cs_mapWallet)
240 {
241 map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
242 if (mi != mapWallet.end())
243 {
244 const CWalletTx& prev = (*mi).second;
245 if (prevout.n < prev.vout.size())
246 if (prev.vout[prevout.n].IsMine())
247 return true;
248 }
249 }
250 return false;
251}
252
253int64 CTxIn::GetDebit() const
254{
255 CRITICAL_BLOCK(cs_mapWallet)
256 {
257 map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
258 if (mi != mapWallet.end())
259 {
260 const CWalletTx& prev = (*mi).second;
261 if (prevout.n < prev.vout.size())
262 if (prev.vout[prevout.n].IsMine())
263 return prev.vout[prevout.n].nValue;
264 }
265 }
266 return 0;
267}
268
269int64 CWalletTx::GetTxTime() const
270{
271 if (!fTimeReceivedIsTxTime && hashBlock != 0)
272 {
273 // If we did not receive the transaction directly, we rely on the block's
274 // time to figure out when it happened. We use the median over a range
275 // of blocks to try to filter out inaccurate block times.
276 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
277 if (mi != mapBlockIndex.end())
278 {
279 CBlockIndex* pindex = (*mi).second;
280 if (pindex)
281 return pindex->GetMedianTime();
282 }
283 }
284 return nTimeReceived;
285}
286
287
288
289
290
291
292int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
293{
294 if (fClient)
295 {
296 if (hashBlock == 0)
297 return 0;
298 }
299 else
300 {
301 CBlock blockTmp;
302 if (pblock == NULL)
303 {
304 // Load the block this tx is in
305 CTxIndex txindex;
306 if (!CTxDB("r").ReadTxIndex(GetHash(), txindex))
307 return 0;
308 if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, true))
309 return 0;
310 pblock = &blockTmp;
311 }
312
313 // Update the tx's hashBlock
314 hashBlock = pblock->GetHash();
315
316 // Locate the transaction
317 for (nIndex = 0; nIndex < pblock->vtx.size(); nIndex++)
318 if (pblock->vtx[nIndex] == *(CTransaction*)this)
319 break;
320 if (nIndex == pblock->vtx.size())
321 {
322 vMerkleBranch.clear();
323 nIndex = -1;
324 printf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
325 return 0;
326 }
327
328 // Fill in merkle branch
329 vMerkleBranch = pblock->GetMerkleBranch(nIndex);
330 }
331
332 // Is the tx in a block that's in the main chain
333 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
334 if (mi == mapBlockIndex.end())
335 return 0;
336 CBlockIndex* pindex = (*mi).second;
337 if (!pindex || !pindex->IsInMainChain())
338 return 0;
339
340 return pindexBest->nHeight - pindex->nHeight + 1;
341}
342
343
344
345void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
346{
347 vtxPrev.clear();
348
349 const int COPY_DEPTH = 3;
350 if (SetMerkleBranch() < COPY_DEPTH)
351 {
352 vector<uint256> vWorkQueue;
353 foreach(const CTxIn& txin, vin)
354 vWorkQueue.push_back(txin.prevout.hash);
355
356 // This critsect is OK because txdb is already open
357 CRITICAL_BLOCK(cs_mapWallet)
358 {
359 map<uint256, const CMerkleTx*> mapWalletPrev;
360 set<uint256> setAlreadyDone;
361 for (int i = 0; i < vWorkQueue.size(); i++)
362 {
363 uint256 hash = vWorkQueue[i];
364 if (setAlreadyDone.count(hash))
365 continue;
366 setAlreadyDone.insert(hash);
367
368 CMerkleTx tx;
369 if (mapWallet.count(hash))
370 {
371 tx = mapWallet[hash];
372 foreach(const CMerkleTx& txWalletPrev, mapWallet[hash].vtxPrev)
373 mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
374 }
375 else if (mapWalletPrev.count(hash))
376 {
377 tx = *mapWalletPrev[hash];
378 }
379 else if (!fClient && txdb.ReadDiskTx(hash, tx))
380 {
381 ;
382 }
383 else
384 {
385 printf("ERROR: AddSupportingTransactions() : unsupported transaction\n");
386 continue;
387 }
388
389 int nDepth = tx.SetMerkleBranch();
390 vtxPrev.push_back(tx);
391
392 if (nDepth < COPY_DEPTH)
393 foreach(const CTxIn& txin, tx.vin)
394 vWorkQueue.push_back(txin.prevout.hash);
395 }
396 }
397 }
398
399 reverse(vtxPrev.begin(), vtxPrev.end());
400}
401
402
403
404
405
406
407
408
409
410
411
412bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs)
413{
414 if (pfMissingInputs)
415 *pfMissingInputs = false;
416
417 // Coinbase is only valid in a block, not as a loose transaction
418 if (IsCoinBase())
419 return error("AcceptTransaction() : coinbase as individual tx");
420
421 if (!CheckTransaction())
422 return error("AcceptTransaction() : CheckTransaction failed");
423
424 // Do we already have it?
425 uint256 hash = GetHash();
426 CRITICAL_BLOCK(cs_mapTransactions)
427 if (mapTransactions.count(hash))
428 return false;
429 if (fCheckInputs)
430 if (txdb.ContainsTx(hash))
431 return false;
432
433 // Check for conflicts with in-memory transactions
434 CTransaction* ptxOld = NULL;
435 for (int i = 0; i < vin.size(); i++)
436 {
437 COutPoint outpoint = vin[i].prevout;
438 if (mapNextTx.count(outpoint))
439 {
440 // Allow replacing with a newer version of the same transaction
441 if (i != 0)
442 return false;
443 ptxOld = mapNextTx[outpoint].ptx;
444 if (!IsNewerThan(*ptxOld))
445 return false;
446 for (int i = 0; i < vin.size(); i++)
447 {
448 COutPoint outpoint = vin[i].prevout;
449 if (!mapNextTx.count(outpoint) || mapNextTx[outpoint].ptx != ptxOld)
450 return false;
451 }
452 break;
453 }
454 }
455
456 // Check against previous transactions
457 map<uint256, CTxIndex> mapUnused;
458 int64 nFees = 0;
459 if (fCheckInputs && !ConnectInputs(txdb, mapUnused, CDiskTxPos(1,1,1), 0, nFees, false, false))
460 {
461 if (pfMissingInputs)
462 *pfMissingInputs = true;
463 return error("AcceptTransaction() : ConnectInputs failed %s", hash.ToString().substr(0,6).c_str());
464 }
465
466 // Store transaction in memory
467 CRITICAL_BLOCK(cs_mapTransactions)
468 {
469 if (ptxOld)
470 {
471 printf("mapTransaction.erase(%s) replacing with new version\n", ptxOld->GetHash().ToString().c_str());
472 mapTransactions.erase(ptxOld->GetHash());
473 }
474 AddToMemoryPool();
475 }
476
477 ///// are we sure this is ok when loading transactions or restoring block txes
478 // If updated, erase old tx from wallet
479 if (ptxOld)
480 EraseFromWallet(ptxOld->GetHash());
481
482 printf("AcceptTransaction(): accepted %s\n", hash.ToString().substr(0,6).c_str());
483 return true;
484}
485
486
487bool CTransaction::AddToMemoryPool()
488{
489 // Add to memory pool without checking anything. Don't call this directly,
490 // call AcceptTransaction to properly check the transaction first.
491 CRITICAL_BLOCK(cs_mapTransactions)
492 {
493 uint256 hash = GetHash();
494 mapTransactions[hash] = *this;
495 for (int i = 0; i < vin.size(); i++)
496 mapNextTx[vin[i].prevout] = CInPoint(&mapTransactions[hash], i);
497 nTransactionsUpdated++;
498 }
499 return true;
500}
501
502
503bool CTransaction::RemoveFromMemoryPool()
504{
505 // Remove transaction from memory pool
506 CRITICAL_BLOCK(cs_mapTransactions)
507 {
508 foreach(const CTxIn& txin, vin)
509 mapNextTx.erase(txin.prevout);
510 mapTransactions.erase(GetHash());
511 nTransactionsUpdated++;
512 }
513 return true;
514}
515
516
517
518
519
520
521int CMerkleTx::GetDepthInMainChain() const
522{
523 if (hashBlock == 0 || nIndex == -1)
524 return 0;
525
526 // Find the block it claims to be in
527 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
528 if (mi == mapBlockIndex.end())
529 return 0;
530 CBlockIndex* pindex = (*mi).second;
531 if (!pindex || !pindex->IsInMainChain())
532 return 0;
533
534 // Make sure the merkle branch connects to this block
535 if (!fMerkleVerified)
536 {
537 if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
538 return 0;
539 fMerkleVerified = true;
540 }
541
542 return pindexBest->nHeight - pindex->nHeight + 1;
543}
544
545
546int CMerkleTx::GetBlocksToMaturity() const
547{
548 if (!IsCoinBase())
549 return 0;
550 return max(0, (COINBASE_MATURITY+20) - GetDepthInMainChain());
551}
552
553
554bool CMerkleTx::AcceptTransaction(CTxDB& txdb, bool fCheckInputs)
555{
556 if (fClient)
557 {
558 if (!IsInMainChain() && !ClientConnectInputs())
559 return false;
560 return CTransaction::AcceptTransaction(txdb, false);
561 }
562 else
563 {
564 return CTransaction::AcceptTransaction(txdb, fCheckInputs);
565 }
566}
567
568
569
570bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
571{
572 CRITICAL_BLOCK(cs_mapTransactions)
573 {
574 foreach(CMerkleTx& tx, vtxPrev)
575 {
576 if (!tx.IsCoinBase())
577 {
578 uint256 hash = tx.GetHash();
579 if (!mapTransactions.count(hash) && !txdb.ContainsTx(hash))
580 tx.AcceptTransaction(txdb, fCheckInputs);
581 }
582 }
583 if (!IsCoinBase())
584 return AcceptTransaction(txdb, fCheckInputs);
585 }
586 return true;
587}
588
589void ReacceptWalletTransactions()
590{
591 // Reaccept any txes of ours that aren't already in a block
592 CTxDB txdb("r");
593 CRITICAL_BLOCK(cs_mapWallet)
594 {
595 foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
596 {
597 CWalletTx& wtx = item.second;
598 if (!wtx.IsCoinBase() && !txdb.ContainsTx(wtx.GetHash()))
599 wtx.AcceptWalletTransaction(txdb, false);
600 }
601 }
602}
603
604
605void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
606{
607 foreach(const CMerkleTx& tx, vtxPrev)
608 {
609 if (!tx.IsCoinBase())
610 {
611 uint256 hash = tx.GetHash();
612 if (!txdb.ContainsTx(hash))
613 RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
614 }
615 }
616 if (!IsCoinBase())
617 {
618 uint256 hash = GetHash();
619 if (!txdb.ContainsTx(hash))
620 {
621 printf("Relaying wtx %s\n", hash.ToString().substr(0,6).c_str());
622 RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
623 }
624 }
625}
626
627void RelayWalletTransactions()
628{
629 static int64 nLastTime;
630 if (GetTime() - nLastTime < 10 * 60)
631 return;
632 nLastTime = GetTime();
633
634 // Rebroadcast any of our txes that aren't in a block yet
635 printf("RelayWalletTransactions()\n");
636 CTxDB txdb("r");
637 CRITICAL_BLOCK(cs_mapWallet)
638 {
639 // Sort them in chronological order
640 multimap<unsigned int, CWalletTx*> mapSorted;
641 foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
642 {
643 CWalletTx& wtx = item.second;
644 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
645 }
646 foreach(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
647 {
648 CWalletTx& wtx = *item.second;
649 wtx.RelayWalletTransaction(txdb);
650 }
651 }
652}
653
654
655
656
657
658
659
660
661
662
663//////////////////////////////////////////////////////////////////////////////
664//
665// CBlock and CBlockIndex
666//
667
668bool CBlock::ReadFromDisk(const CBlockIndex* pblockindex, bool fReadTransactions)
669{
670 return ReadFromDisk(pblockindex->nFile, pblockindex->nBlockPos, fReadTransactions);
671}
672
673uint256 GetOrphanRoot(const CBlock* pblock)
674{
675 // Work back to the first block in the orphan chain
676 while (mapOrphanBlocks.count(pblock->hashPrevBlock))
677 pblock = mapOrphanBlocks[pblock->hashPrevBlock];
678 return pblock->GetHash();
679}
680
681int64 CBlock::GetBlockValue(int64 nFees) const
682{
683 int64 nSubsidy = 50 * COIN;
684
685 // Subsidy is cut in half every 4 years
686 nSubsidy >>= (nBestHeight / 210000);
687
688 return nSubsidy + nFees;
689}
690
691unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast)
692{
693 // Bitflash: 2-minute target block time with a fast retarget (every 30
694 // blocks, ~1h) so difficulty tracks the small, volatile CPU hashrate and
695 // brief disconnections no longer spawn divergent forks.
696 const unsigned int nTargetSpacing = 2 * 60; // 2 minutes
697 const unsigned int nInterval = 30; // retarget window
698 const unsigned int nTargetTimespan = nInterval * nTargetSpacing; // 3600s
699
700 // Genesis block
701 if (pindexLast == NULL)
702 return bnProofOfWorkLimit.GetCompact();
703
704 // Only change once per interval
705 if ((pindexLast->nHeight+1) % nInterval != 0)
706 return pindexLast->nBits;
707
708 // Go back by what we want to be 14 days worth of blocks
709 const CBlockIndex* pindexFirst = pindexLast;
710 for (int i = 0; pindexFirst && i < nInterval-1; i++)
711 pindexFirst = pindexFirst->pprev;
712 assert(pindexFirst);
713
714 // Limit adjustment step
715 unsigned int nActualTimespan = pindexLast->nTime - pindexFirst->nTime;
716 printf(" nActualTimespan = %d before bounds\n", nActualTimespan);
717 if (nActualTimespan < nTargetTimespan/4)
718 nActualTimespan = nTargetTimespan/4;
719 if (nActualTimespan > nTargetTimespan*4)
720 nActualTimespan = nTargetTimespan*4;
721
722 // Retarget
723 CBigNum bnNew;
724 bnNew.SetCompact(pindexLast->nBits);
725 bnNew *= nActualTimespan;
726 bnNew /= nTargetTimespan;
727
728 if (bnNew > bnProofOfWorkLimit)
729 bnNew = bnProofOfWorkLimit;
730
731 /// debug print
732 printf("\n\n\nGetNextWorkRequired RETARGET *****\n");
733 printf("nTargetTimespan = %d nActualTimespan = %d\n", nTargetTimespan, nActualTimespan);
734 printf("Before: %08x %s\n", pindexLast->nBits, CBigNum().SetCompact(pindexLast->nBits).getuint256().ToString().c_str());
735 printf("After: %08x %s\n", bnNew.GetCompact(), bnNew.getuint256().ToString().c_str());
736
737 return bnNew.GetCompact();
738}
739
740
741
742
743
744
745
746
747
748bool CTransaction::DisconnectInputs(CTxDB& txdb)
749{
750 // Relinquish previous transactions' spent pointers
751 if (!IsCoinBase())
752 {
753 foreach(const CTxIn& txin, vin)
754 {
755 COutPoint prevout = txin.prevout;
756
757 // Get prev txindex from disk
758 CTxIndex txindex;
759 if (!txdb.ReadTxIndex(prevout.hash, txindex))
760 return error("DisconnectInputs() : ReadTxIndex failed");
761
762 if (prevout.n >= txindex.vSpent.size())
763 return error("DisconnectInputs() : prevout.n out of range");
764
765 // Mark outpoint as not spent
766 txindex.vSpent[prevout.n].SetNull();
767
768 // Write back
769 txdb.UpdateTxIndex(prevout.hash, txindex);
770 }
771 }
772
773 // Remove transaction from index
774 if (!txdb.EraseTxIndex(*this))
775 return error("DisconnectInputs() : EraseTxPos failed");
776
777 return true;
778}
779
780
781bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx, int nHeight, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee)
782{
783 // Take over previous transactions' spent pointers
784 if (!IsCoinBase())
785 {
786 int64 nValueIn = 0;
787 for (int i = 0; i < vin.size(); i++)
788 {
789 COutPoint prevout = vin[i].prevout;
790
791 // Read txindex
792 CTxIndex txindex;
793 bool fFound = true;
794 if (fMiner && mapTestPool.count(prevout.hash))
795 {
796 // Get txindex from current proposed changes
797 txindex = mapTestPool[prevout.hash];
798 }
799 else
800 {
801 // Read txindex from txdb
802 fFound = txdb.ReadTxIndex(prevout.hash, txindex);
803 }
804 if (!fFound && (fBlock || fMiner))
805 return fMiner ? false : error("ConnectInputs() : %s prev tx %s index entry not found", GetHash().ToString().substr(0,6).c_str(), prevout.hash.ToString().substr(0,6).c_str());
806
807 // Read txPrev
808 CTransaction txPrev;
809 if (!fFound || txindex.pos == CDiskTxPos(1,1,1))
810 {
811 // Get prev tx from single transactions in memory
812 CRITICAL_BLOCK(cs_mapTransactions)
813 {
814 if (!mapTransactions.count(prevout.hash))
815 return error("ConnectInputs() : %s mapTransactions prev not found %s", GetHash().ToString().substr(0,6).c_str(), prevout.hash.ToString().substr(0,6).c_str());
816 txPrev = mapTransactions[prevout.hash];
817 }
818 if (!fFound)
819 txindex.vSpent.resize(txPrev.vout.size());
820 }
821 else
822 {
823 // Get prev tx from disk
824 if (!txPrev.ReadFromDisk(txindex.pos))
825 return error("ConnectInputs() : %s ReadFromDisk prev tx %s failed", GetHash().ToString().substr(0,6).c_str(), prevout.hash.ToString().substr(0,6).c_str());
826 }
827
828 if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size())
829 return error("ConnectInputs() : %s prevout.n out of range %d %d %d", GetHash().ToString().substr(0,6).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size());
830
831 // If prev is coinbase, check that it's matured
832 if (txPrev.IsCoinBase())
833 for (CBlockIndex* pindex = pindexBest; pindex && nBestHeight - pindex->nHeight < COINBASE_MATURITY-1; pindex = pindex->pprev)
834 if (pindex->nBlockPos == txindex.pos.nBlockPos && pindex->nFile == txindex.pos.nFile)
835 return error("ConnectInputs() : tried to spend coinbase at depth %d", nBestHeight - pindex->nHeight);
836
837 // Verify signature
838 if (!VerifySignature(txPrev, *this, i))
839 return error("ConnectInputs() : %s VerifySignature failed", GetHash().ToString().substr(0,6).c_str());
840
841 // Check for conflicts
842 if (!txindex.vSpent[prevout.n].IsNull())
843 return fMiner ? false : error("ConnectInputs() : %s prev tx already used at %s", GetHash().ToString().substr(0,6).c_str(), txindex.vSpent[prevout.n].ToString().c_str());
844
845 // Mark outpoints as spent
846 txindex.vSpent[prevout.n] = posThisTx;
847
848 // Write back
849 if (fBlock)
850 txdb.UpdateTxIndex(prevout.hash, txindex);
851 else if (fMiner)
852 mapTestPool[prevout.hash] = txindex;
853
854 nValueIn += txPrev.vout[prevout.n].nValue;
855 if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
856 return error("ConnectInputs() : txin values out of range");
857 }
858
859 // Tally transaction fees
860 int64 nTxFee = nValueIn - GetValueOut();
861 if (nTxFee < 0)
862 return error("ConnectInputs() : %s nTxFee < 0", GetHash().ToString().substr(0,6).c_str());
863 if (nTxFee < nMinFee)
864 return false;
865 nFees += nTxFee;
866 if (!MoneyRange(nFees))
867 return error("ConnectInputs() : nFees out of range");
868 }
869
870 if (fBlock)
871 {
872 // Add transaction to disk index
873 if (!txdb.AddTxIndex(*this, posThisTx, nHeight))
874 return error("ConnectInputs() : AddTxPos failed");
875 }
876 else if (fMiner)
877 {
878 // Add transaction to test pool
879 mapTestPool[GetHash()] = CTxIndex(CDiskTxPos(1,1,1), vout.size());
880 }
881
882 return true;
883}
884
885
886bool CTransaction::ClientConnectInputs()
887{
888 if (IsCoinBase())
889 return false;
890
891 // Take over previous transactions' spent pointers
892 CRITICAL_BLOCK(cs_mapTransactions)
893 {
894 int64 nValueIn = 0;
895 for (int i = 0; i < vin.size(); i++)
896 {
897 // Get prev tx from single transactions in memory
898 COutPoint prevout = vin[i].prevout;
899 if (!mapTransactions.count(prevout.hash))
900 return false;
901 CTransaction& txPrev = mapTransactions[prevout.hash];
902
903 if (prevout.n >= txPrev.vout.size())
904 return false;
905
906 // Verify signature
907 if (!VerifySignature(txPrev, *this, i))
908 return error("ConnectInputs() : VerifySignature failed");
909
910 ///// this is redundant with the mapNextTx stuff, not sure which I want to get rid of
911 ///// this has to go away now that posNext is gone
912 // // Check for conflicts
913 // if (!txPrev.vout[prevout.n].posNext.IsNull())
914 // return error("ConnectInputs() : prev tx already used");
915 //
916 // // Flag outpoints as used
917 // txPrev.vout[prevout.n].posNext = posThisTx;
918
919 nValueIn += txPrev.vout[prevout.n].nValue;
920 }
921 if (GetValueOut() > nValueIn)
922 return false;
923 }
924
925 return true;
926}
927
928
929
930
931bool CBlock::DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex)
932{
933 // Disconnect in reverse order
934 for (int i = vtx.size()-1; i >= 0; i--)
935 if (!vtx[i].DisconnectInputs(txdb))
936 return false;
937
938 // Update block index on disk without changing it in memory.
939 // The memory index structure will be changed after the db commits.
940 if (pindex->pprev)
941 {
942 CDiskBlockIndex blockindexPrev(pindex->pprev);
943 blockindexPrev.hashNext = 0;
944 txdb.WriteBlockIndex(blockindexPrev);
945 }
946
947 return true;
948}
949
950bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
951{
952 //// issue here: it doesn't know the version
953 unsigned int nTxPos = pindex->nBlockPos + ::GetSerializeSize(CBlock(), SER_DISK) - 1 + GetSizeOfCompactSize(vtx.size());
954
955 map<uint256, CTxIndex> mapUnused;
956 int64 nFees = 0;
957 foreach(CTransaction& tx, vtx)
958 {
959 CDiskTxPos posThisTx(pindex->nFile, pindex->nBlockPos, nTxPos);
960 nTxPos += ::GetSerializeSize(tx, SER_DISK);
961
962 if (!tx.ConnectInputs(txdb, mapUnused, posThisTx, pindex->nHeight, nFees, true, false))
963 return false;
964 }
965
966 if (vtx[0].GetValueOut() > GetBlockValue(nFees))
967 return false;
968
969 // Update block index on disk without changing it in memory.
970 // The memory index structure will be changed after the db commits.
971 if (pindex->pprev)
972 {
973 CDiskBlockIndex blockindexPrev(pindex->pprev);
974 blockindexPrev.hashNext = pindex->GetBlockHash();
975 txdb.WriteBlockIndex(blockindexPrev);
976 }
977
978 // Watch for transactions paying to me
979 foreach(CTransaction& tx, vtx)
980 AddToWalletIfMine(tx, this);
981
982 return true;
983}
984
985
986
987bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
988{
989 printf("*** REORGANIZE ***\n");
990
991 // Find the fork
992 CBlockIndex* pfork = pindexBest;
993 CBlockIndex* plonger = pindexNew;
994 while (pfork != plonger)
995 {
996 if (!(pfork = pfork->pprev))
997 return error("Reorganize() : pfork->pprev is null");
998 while (plonger->nHeight > pfork->nHeight)
999 if (!(plonger = plonger->pprev))
1000 return error("Reorganize() : plonger->pprev is null");
1001 }
1002
1003 // List of what to disconnect
1004 vector<CBlockIndex*> vDisconnect;
1005 for (CBlockIndex* pindex = pindexBest; pindex != pfork; pindex = pindex->pprev)
1006 vDisconnect.push_back(pindex);
1007
1008 // List of what to connect
1009 vector<CBlockIndex*> vConnect;
1010 for (CBlockIndex* pindex = pindexNew; pindex != pfork; pindex = pindex->pprev)
1011 vConnect.push_back(pindex);
1012 reverse(vConnect.begin(), vConnect.end());
1013
1014 // Disconnect shorter branch
1015 vector<CTransaction> vResurrect;
1016 foreach(CBlockIndex* pindex, vDisconnect)
1017 {
1018 CBlock block;
1019 if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos, true))
1020 return error("Reorganize() : ReadFromDisk for disconnect failed");
1021 if (!block.DisconnectBlock(txdb, pindex))
1022 return error("Reorganize() : DisconnectBlock failed");
1023
1024 // Queue memory transactions to resurrect
1025 foreach(const CTransaction& tx, block.vtx)
1026 if (!tx.IsCoinBase())
1027 vResurrect.push_back(tx);
1028 }
1029
1030 // Connect longer branch
1031 vector<CTransaction> vDelete;
1032 for (int i = 0; i < vConnect.size(); i++)
1033 {
1034 CBlockIndex* pindex = vConnect[i];
1035 CBlock block;
1036 if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos, true))
1037 return error("Reorganize() : ReadFromDisk for connect failed");
1038 if (!block.ConnectBlock(txdb, pindex))
1039 {
1040 // Invalid block, delete the rest of this branch
1041 txdb.TxnAbort();
1042 for (int j = i; j < vConnect.size(); j++)
1043 {
1044 CBlockIndex* pindex = vConnect[j];
1045 pindex->EraseBlockFromDisk();
1046 txdb.EraseBlockIndex(pindex->GetBlockHash());
1047 mapBlockIndex.erase(pindex->GetBlockHash());
1048 delete pindex;
1049 }
1050 return error("Reorganize() : ConnectBlock failed");
1051 }
1052
1053 // Queue memory transactions to delete
1054 foreach(const CTransaction& tx, block.vtx)
1055 vDelete.push_back(tx);
1056 }
1057 if (!txdb.WriteHashBestChain(pindexNew->GetBlockHash()))
1058 return error("Reorganize() : WriteHashBestChain failed");
1059
1060 // Commit now because resurrecting could take some time
1061 txdb.TxnCommit();
1062
1063 // Disconnect shorter branch
1064 foreach(CBlockIndex* pindex, vDisconnect)
1065 if (pindex->pprev)
1066 pindex->pprev->pnext = NULL;
1067
1068 // Connect longer branch
1069 foreach(CBlockIndex* pindex, vConnect)
1070 if (pindex->pprev)
1071 pindex->pprev->pnext = pindex;
1072
1073 // Resurrect memory transactions that were in the disconnected branch
1074 foreach(CTransaction& tx, vResurrect)
1075 tx.AcceptTransaction(txdb, false);
1076
1077 // Delete redundant memory transactions that are in the connected branch
1078 foreach(CTransaction& tx, vDelete)
1079 tx.RemoveFromMemoryPool();
1080
1081 return true;
1082}
1083
1084
1085bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
1086{
1087 // Check for duplicate
1088 uint256 hash = GetHash();
1089 if (mapBlockIndex.count(hash))
1090 return error("AddToBlockIndex() : %s already exists", hash.ToString().substr(0,14).c_str());
1091
1092 // Construct new block index object
1093 CBlockIndex* pindexNew = new CBlockIndex(nFile, nBlockPos, *this);
1094 if (!pindexNew)
1095 return error("AddToBlockIndex() : new CBlockIndex failed");
1096 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
1097 pindexNew->phashBlock = &((*mi).first);
1098 map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(hashPrevBlock);
1099 if (miPrev != mapBlockIndex.end())
1100 {
1101 pindexNew->pprev = (*miPrev).second;
1102 pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
1103 }
1104
1105 CTxDB txdb;
1106 txdb.TxnBegin();
1107 txdb.WriteBlockIndex(CDiskBlockIndex(pindexNew));
1108
1109 // New best
1110 if (pindexNew->nHeight > nBestHeight)
1111 {
1112 if (pindexGenesisBlock == NULL && hash == hashGenesisBlock)
1113 {
1114 pindexGenesisBlock = pindexNew;
1115 txdb.WriteHashBestChain(hash);
1116 }
1117 else if (hashPrevBlock == hashBestChain)
1118 {
1119 // Adding to current best branch
1120 if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash))
1121 {
1122 txdb.TxnAbort();
1123 pindexNew->EraseBlockFromDisk();
1124 mapBlockIndex.erase(pindexNew->GetBlockHash());
1125 delete pindexNew;
1126 return error("AddToBlockIndex() : ConnectBlock failed");
1127 }
1128 txdb.TxnCommit();
1129 pindexNew->pprev->pnext = pindexNew;
1130
1131 // Delete redundant memory transactions
1132 foreach(CTransaction& tx, vtx)
1133 tx.RemoveFromMemoryPool();
1134 }
1135 else
1136 {
1137 // New best branch
1138 if (!Reorganize(txdb, pindexNew))
1139 {
1140 txdb.TxnAbort();
1141 return error("AddToBlockIndex() : Reorganize failed");
1142 }
1143 }
1144
1145 // New best link
1146 hashBestChain = hash;
1147 pindexBest = pindexNew;
1148 nBestHeight = pindexBest->nHeight;
1149 nTransactionsUpdated++;
1150 printf("AddToBlockIndex: new best=%s height=%d\n", hashBestChain.ToString().substr(0,14).c_str(), nBestHeight);
1151 }
1152
1153 txdb.TxnCommit();
1154 txdb.Close();
1155
1156 // Relay wallet transactions that haven't gotten in yet
1157 if (pindexNew == pindexBest)
1158 RelayWalletTransactions();
1159
1160 MainFrameRepaint();
1161 return true;
1162}
1163
1164
1165
1166
1167bool CBlock::CheckBlock() const
1168{
1169 // These are checks that are independent of context
1170 // that can be verified before saving an orphan block.
1171
1172 // Size limits
1173 if (vtx.empty() || vtx.size() > MAX_SIZE || ::GetSerializeSize(*this, SER_DISK) > MAX_SIZE)
1174 return error("CheckBlock() : size limits failed");
1175
1176 // Check timestamp
1177 if (nTime > GetAdjustedTime() + 2 * 60 * 60)
1178 return error("CheckBlock() : block timestamp too far in the future");
1179
1180 // First transaction must be coinbase, the rest must not be
1181 if (vtx.empty() || !vtx[0].IsCoinBase())
1182 return error("CheckBlock() : first tx is not coinbase");
1183 for (int i = 1; i < vtx.size(); i++)
1184 if (vtx[i].IsCoinBase())
1185 return error("CheckBlock() : more than one coinbase");
1186
1187 // Check transactions
1188 foreach(const CTransaction& tx, vtx)
1189 if (!tx.CheckTransaction())
1190 return error("CheckBlock() : CheckTransaction failed");
1191
1192 // Check proof of work matches claimed amount (memory-hard RandomX PoW)
1193 if (CBigNum().SetCompact(nBits) > bnProofOfWorkLimit)
1194 return error("CheckBlock() : nBits below minimum work");
1195 if (GetPoWHash() > CBigNum().SetCompact(nBits).getuint256())
1196 return error("CheckBlock() : RandomX proof-of-work does not match nBits");
1197
1198 // Check merkleroot
1199 if (hashMerkleRoot != BuildMerkleTree())
1200 return error("CheckBlock() : hashMerkleRoot mismatch");
1201
1202 return true;
1203}
1204
1205bool CBlock::AcceptBlock()
1206{
1207 // Check for duplicate
1208 uint256 hash = GetHash();
1209 if (mapBlockIndex.count(hash))
1210 return error("AcceptBlock() : block already in mapBlockIndex");
1211
1212 // Get prev block index
1213 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashPrevBlock);
1214 if (mi == mapBlockIndex.end())
1215 return error("AcceptBlock() : prev block not found");
1216 CBlockIndex* pindexPrev = (*mi).second;
1217
1218 // Check timestamp against prev
1219 if (nTime <= pindexPrev->GetMedianTimePast())
1220 return error("AcceptBlock() : block's timestamp is too early");
1221
1222 // Check proof of work
1223 if (nBits != GetNextWorkRequired(pindexPrev))
1224 return error("AcceptBlock() : incorrect proof of work");
1225
1226 // Write block to history file
1227 unsigned int nFile;
1228 unsigned int nBlockPos;
1229 if (!WriteToDisk(!fClient, nFile, nBlockPos))
1230 return error("AcceptBlock() : WriteToDisk failed");
1231 if (!AddToBlockIndex(nFile, nBlockPos))
1232 return error("AcceptBlock() : AddToBlockIndex failed");
1233
1234 if (hashBestChain == hash)
1235 RelayInventory(CInv(MSG_BLOCK, hash));
1236
1237 // // Add atoms to user reviews for coins created
1238 // vector<unsigned char> vchPubKey;
1239 // if (ExtractPubKey(vtx[0].vout[0].scriptPubKey, false, vchPubKey))
1240 // {
1241 // unsigned short nAtom = GetRand(USHRT_MAX - 100) + 100;
1242 // vector<unsigned short> vAtoms(1, nAtom);
1243 // AddAtomsAndPropagate(Hash(vchPubKey.begin(), vchPubKey.end()), vAtoms, true);
1244 // }
1245
1246 return true;
1247}
1248
1249bool ProcessBlock(CNode* pfrom, CBlock* pblock)
1250{
1251 // Check for duplicate
1252 uint256 hash = pblock->GetHash();
1253 if (mapBlockIndex.count(hash))
1254 return error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString().substr(0,14).c_str());
1255 if (mapOrphanBlocks.count(hash))
1256 return error("ProcessBlock() : already have block (orphan) %s", hash.ToString().substr(0,14).c_str());
1257
1258 // Preliminary checks
1259 if (!pblock->CheckBlock())
1260 {
1261 delete pblock;
1262 return error("ProcessBlock() : CheckBlock FAILED");
1263 }
1264
1265 // If don't already have its previous block, shunt it off to holding area until we get it
1266 if (!mapBlockIndex.count(pblock->hashPrevBlock))
1267 {
1268 printf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString().substr(0,14).c_str());
1269 mapOrphanBlocks.insert(make_pair(hash, pblock));
1270 mapOrphanBlocksByPrev.insert(make_pair(pblock->hashPrevBlock, pblock));
1271
1272 // Ask this guy to fill in what we're missing
1273 if (pfrom)
1274 pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), GetOrphanRoot(pblock));
1275 return true;
1276 }
1277
1278 // Store to disk
1279 if (!pblock->AcceptBlock())
1280 {
1281 delete pblock;
1282 return error("ProcessBlock() : AcceptBlock FAILED");
1283 }
1284 delete pblock;
1285
1286 // Recursively process any orphan blocks that depended on this one
1287 vector<uint256> vWorkQueue;
1288 vWorkQueue.push_back(hash);
1289 for (int i = 0; i < vWorkQueue.size(); i++)
1290 {
1291 uint256 hashPrev = vWorkQueue[i];
1292 for (multimap<uint256, CBlock*>::iterator mi = mapOrphanBlocksByPrev.lower_bound(hashPrev);
1293 mi != mapOrphanBlocksByPrev.upper_bound(hashPrev);
1294 ++mi)
1295 {
1296 CBlock* pblockOrphan = (*mi).second;
1297 if (pblockOrphan->AcceptBlock())
1298 vWorkQueue.push_back(pblockOrphan->GetHash());
1299 mapOrphanBlocks.erase(pblockOrphan->GetHash());
1300 delete pblockOrphan;
1301 }
1302 mapOrphanBlocksByPrev.erase(hashPrev);
1303 }
1304
1305 printf("ProcessBlock: ACCEPTED\n");
1306 return true;
1307}
1308
1309
1310
1311
1312
1313
1314
1315
1316template<typename Stream>
1317bool ScanMessageStart(Stream& s)
1318{
1319 // Scan ahead to the next pchMessageStart, which should normally be immediately
1320 // at the file pointer. Leaves file pointer at end of pchMessageStart.
1321 s.clear(0);
1322 short prevmask = s.exceptions(0);
1323 const char* p = BEGIN(pchMessageStart);
1324 try
1325 {
1326 loop
1327 {
1328 char c;
1329 s.read(&c, 1);
1330 if (s.fail())
1331 {
1332 s.clear(0);
1333 s.exceptions(prevmask);
1334 return false;
1335 }
1336 if (*p != c)
1337 p = BEGIN(pchMessageStart);
1338 if (*p == c)
1339 {
1340 if (++p == END(pchMessageStart))
1341 {
1342 s.clear(0);
1343 s.exceptions(prevmask);
1344 return true;
1345 }
1346 }
1347 }
1348 }
1349 catch (...)
1350 {
1351 s.clear(0);
1352 s.exceptions(prevmask);
1353 return false;
1354 }
1355}
1356
1357string GetAppDir()
1358{
1359 string strDir;
1360 if (!strSetDataDir.empty())
1361 {
1362 strDir = strSetDataDir;
1363 }
1364#ifdef _WIN32
1365 else if (getenv("APPDATA"))
1366 {
1367 strDir = strprintf("%s\\Bitflash", getenv("APPDATA"));
1368 }
1369 else if (getenv("USERPROFILE"))
1370 {
1371 string strAppData = strprintf("%s\\Application Data", getenv("USERPROFILE"));
1372 static bool fMkdirDone;
1373 if (!fMkdirDone)
1374 {
1375 fMkdirDone = true;
1376 _mkdir(strAppData.c_str());
1377 }
1378 strDir = strprintf("%s\\Bitflash", strAppData.c_str());
1379 }
1380#else
1381 else if (getenv("HOME"))
1382 {
1383 strDir = strprintf("%s/.bitflash", getenv("HOME"));
1384 }
1385#endif
1386 else
1387 {
1388 return ".";
1389 }
1390 static bool fMkdirDone;
1391 if (!fMkdirDone)
1392 {
1393 fMkdirDone = true;
1394 _mkdir(strDir.c_str());
1395 }
1396 return strDir;
1397}
1398
1399FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode)
1400{
1401 if (nFile == -1)
1402 return NULL;
1403 FILE* file = fopen(strprintf("%s/blk%04d.dat", GetAppDir().c_str(), nFile).c_str(), pszMode);
1404 if (!file)
1405 return NULL;
1406 if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w'))
1407 {
1408 if (fseek(file, nBlockPos, SEEK_SET) != 0)
1409 {
1410 fclose(file);
1411 return NULL;
1412 }
1413 }
1414 return file;
1415}
1416
1417static unsigned int nCurrentBlockFile = 1;
1418
1419FILE* AppendBlockFile(unsigned int& nFileRet)
1420{
1421 nFileRet = 0;
1422 loop
1423 {
1424 FILE* file = OpenBlockFile(nCurrentBlockFile, 0, "ab");
1425 if (!file)
1426 return NULL;
1427 if (fseek(file, 0, SEEK_END) != 0)
1428 return NULL;
1429 // FAT32 filesize max 4GB, fseek and ftell max 2GB, so we must stay under 2GB
1430 if (ftell(file) < 0x7F000000 - MAX_SIZE)
1431 {
1432 nFileRet = nCurrentBlockFile;
1433 return file;
1434 }
1435 fclose(file);
1436 nCurrentBlockFile++;
1437 }
1438}
1439
1440bool LoadBlockIndex(bool fAllowNew)
1441{
1442 // Initialize the RandomX PoW before touching any block (both the genesis
1443 // and verification depend on it).
1444 if (!RandomXInit())
1445 return error("LoadBlockIndex() : RandomXInit failed");
1446
1447 //
1448 // Load block index
1449 //
1450 CTxDB txdb("cr");
1451 if (!txdb.LoadBlockIndex())
1452 return false;
1453 txdb.Close();
1454
1455 //
1456 // Init with genesis block
1457 //
1458 if (mapBlockIndex.empty())
1459 {
1460 if (!fAllowNew)
1461 return false;
1462
1463
1464 // Genesis Block:
1465 // GetHash() = 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
1466 // hashMerkleRoot = 0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
1467 // txNew.vin[0].scriptSig = 486604799 4 0x736B6E616220726F662074756F6C69616220646E6F63657320666F206B6E697262206E6F20726F6C6C65636E61684320393030322F6E614A2F33302073656D695420656854
1468 // txNew.vout[0].nValue = 5000000000
1469 // txNew.vout[0].scriptPubKey = 0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704 OP_CHECKSIG
1470 // block.nVersion = 1
1471 // block.nTime = 1231006505
1472 // block.nBits = 0x1d00ffff
1473 // block.nNonce = 2083236893
1474 // CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
1475 // CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
1476 // CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
1477 // CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
1478 // vMerkleTree: 4a5e1e
1479
1480 // Bitflash genesis block -- own header (fair launch, 2026 stable relaunch)
1481 char* pszTimestamp = "Bitflash 24/Jul/2026 Fair launch: one CPU one vote, no premine";
1482 CTransaction txNew;
1483 txNew.vin.resize(1);
1484 txNew.vout.resize(1);
1485 txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((unsigned char*)pszTimestamp, (unsigned char*)pszTimestamp + strlen(pszTimestamp));
1486 txNew.vout[0].nValue = 50 * COIN;
1487 txNew.vout[0].scriptPubKey = CScript() << CBigNum("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704") << OP_CHECKSIG;
1488 CBlock block;
1489 block.vtx.push_back(txNew);
1490 block.hashPrevBlock = 0;
1491 block.hashMerkleRoot = block.BuildMerkleTree();
1492 block.nVersion = 1;
1493 block.nTime = 1753315200; // 2026-07-24 00:00:00 UTC (stable relaunch)
1494 block.nBits = 0x1f0fffff; // = bnProofOfWorkLimit (Bitflash RandomX floor)
1495 block.nNonce = GENESIS_NONCE;
1496
1497 // If the nonce has not been found yet, mine the genesis once (RandomX)
1498 // and print the values to be hardcoded in the constants above.
1499 if (block.GetHash() != hashGenesisBlock)
1500 {
1501 printf("Mining Bitflash genesis block (RandomX)...\n");
1502 uint256 hashTarget = CBigNum().SetCompact(block.nBits).getuint256();
1503 while (block.GetPoWHash() > hashTarget)
1504 {
1505 if ((block.nNonce & 0x3ff) == 0)
1506 printf("nonce %u\r", block.nNonce);
1507 block.nNonce++;
1508 if (block.nNonce == 0)
1509 {
1510 printf("nonce overflow, incrementing nTime\n");
1511 block.nTime++;
1512 }
1513 }
1514 printf("\n=== BITFLASH GENESIS (RandomX) FOUND ===\n");
1515 printf("nTime = %u\n", block.nTime);
1516 printf("nNonce = %u (0x%08x)\n", block.nNonce, block.nNonce);
1517 printf("powhash = %s\n", block.GetPoWHash().ToString().c_str());
1518 printf("hash = %s\n", block.GetHash().ToString().c_str());
1519 printf("merkle = %s\n", block.hashMerkleRoot.ToString().c_str());
1520 printf("========================================\n");
1521 }
1522
1523 // Asserts only apply once the genesis values are hardcoded
1524 if (hashGenesisBlock != uint256(0))
1525 {
1526 assert(block.hashMerkleRoot == hashGenesisMerkleRoot);
1527 assert(block.GetHash() == hashGenesisBlock);
1528 }
1529
1530 // Start new block file
1531 unsigned int nFile;
1532 unsigned int nBlockPos;
1533 if (!block.WriteToDisk(!fClient, nFile, nBlockPos))
1534 return error("LoadBlockIndex() : writing genesis block to disk failed");
1535 if (!block.AddToBlockIndex(nFile, nBlockPos))
1536 return error("LoadBlockIndex() : genesis block not accepted");
1537 }
1538
1539 return true;
1540}
1541
1542
1543
1544void PrintBlockTree()
1545{
1546 // precompute tree structure
1547 map<CBlockIndex*, vector<CBlockIndex*> > mapNext;
1548 for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
1549 {
1550 CBlockIndex* pindex = (*mi).second;
1551 mapNext[pindex->pprev].push_back(pindex);
1552 // test
1553 //while (rand() % 3 == 0)
1554 // mapNext[pindex->pprev].push_back(pindex);
1555 }
1556
1557 vector<pair<int, CBlockIndex*> > vStack;
1558 vStack.push_back(make_pair(0, pindexGenesisBlock));
1559
1560 int nPrevCol = 0;
1561 while (!vStack.empty())
1562 {
1563 int nCol = vStack.back().first;
1564 CBlockIndex* pindex = vStack.back().second;
1565 vStack.pop_back();
1566
1567 // print split or gap
1568 if (nCol > nPrevCol)
1569 {
1570 for (int i = 0; i < nCol-1; i++)
1571 printf("| ");
1572 printf("|\\\n");
1573 }
1574 else if (nCol < nPrevCol)
1575 {
1576 for (int i = 0; i < nCol; i++)
1577 printf("| ");
1578 printf("|\n");
1579 }
1580 nPrevCol = nCol;
1581
1582 // print columns
1583 for (int i = 0; i < nCol; i++)
1584 printf("| ");
1585
1586 // print item
1587 CBlock block;
1588 block.ReadFromDisk(pindex, true);
1589 printf("%d (%u,%u) %s %s tx %d",
1590 pindex->nHeight,
1591 pindex->nFile,
1592 pindex->nBlockPos,
1593 block.GetHash().ToString().substr(0,14).c_str(),
1594 DateTimeStr(block.nTime).c_str(),
1595 block.vtx.size());
1596
1597 CRITICAL_BLOCK(cs_mapWallet)
1598 {
1599 if (mapWallet.count(block.vtx[0].GetHash()))
1600 {
1601 CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
1602 printf(" mine: %d %d %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
1603 }
1604 }
1605 printf("\n");
1606
1607
1608 // put the main timechain first
1609 vector<CBlockIndex*>& vNext = mapNext[pindex];
1610 for (int i = 0; i < vNext.size(); i++)
1611 {
1612 if (vNext[i]->pnext)
1613 {
1614 swap(vNext[0], vNext[i]);
1615 break;
1616 }
1617 }
1618
1619 // iterate children
1620 for (int i = 0; i < vNext.size(); i++)
1621 vStack.push_back(make_pair(nCol+i, vNext[i]));
1622 }
1623}
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634//////////////////////////////////////////////////////////////////////////////
1635//
1636// Messages
1637//
1638
1639
1640bool AlreadyHave(CTxDB& txdb, const CInv& inv)
1641{
1642 switch (inv.type)
1643 {
1644 case MSG_TX: return mapTransactions.count(inv.hash) || txdb.ContainsTx(inv.hash);
1645 case MSG_BLOCK: return mapBlockIndex.count(inv.hash) || mapOrphanBlocks.count(inv.hash);
1646 case MSG_REVIEW: return true;
1647 case MSG_PRODUCT: return mapProducts.count(inv.hash);
1648 }
1649 // Don't know what it is, just say we already got one
1650 return true;
1651}
1652
1653
1654
1655
1656
1657
1658
1659bool ProcessMessages(CNode* pfrom)
1660{
1661 CDataStream& vRecv = pfrom->vRecv;
1662 if (vRecv.empty())
1663 return true;
1664 printf("ProcessMessages(%d bytes)\n", vRecv.size());
1665
1666 //
1667 // Message format
1668 // (4) message start
1669 // (12) command
1670 // (4) size
1671 // (x) data
1672 //
1673
1674 loop
1675 {
1676 // Scan for message start
1677 CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(pchMessageStart), END(pchMessageStart));
1678 if (vRecv.end() - pstart < sizeof(CMessageHeader))
1679 {
1680 if (vRecv.size() > sizeof(CMessageHeader))
1681 {
1682 printf("\n\nPROCESSMESSAGE MESSAGESTART NOT FOUND\n\n");
1683 vRecv.erase(vRecv.begin(), vRecv.end() - sizeof(CMessageHeader));
1684 }
1685 break;
1686 }
1687 if (pstart - vRecv.begin() > 0)
1688 printf("\n\nPROCESSMESSAGE SKIPPED %d BYTES\n\n", pstart - vRecv.begin());
1689 vRecv.erase(vRecv.begin(), pstart);
1690
1691 // Read header
1692 CMessageHeader hdr;
1693 vRecv >> hdr;
1694 if (!hdr.IsValid())
1695 {
1696 printf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", hdr.GetCommand().c_str());
1697 continue;
1698 }
1699 string strCommand = hdr.GetCommand();
1700
1701 // Message size
1702 unsigned int nMessageSize = hdr.nMessageSize;
1703 if (nMessageSize > vRecv.size())
1704 {
1705 // Rewind and wait for rest of message
1706 ///// need a mechanism to give up waiting for overlong message size error
1707 printf("MESSAGE-BREAK 2\n");
1708 vRecv.insert(vRecv.begin(), BEGIN(hdr), END(hdr));
1709 Sleep(100);
1710 break;
1711 }
1712
1713 // Copy message to its own buffer
1714 CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);
1715 vRecv.ignore(nMessageSize);
1716
1717 // Process message
1718 bool fRet = false;
1719 try
1720 {
1721 CheckForShutdown(2);
1722 CRITICAL_BLOCK(cs_main)
1723 fRet = ProcessMessage(pfrom, strCommand, vMsg);
1724 CheckForShutdown(2);
1725 }
1726 CATCH_PRINT_EXCEPTION("ProcessMessage()")
1727 if (!fRet)
1728 printf("ProcessMessage(%s, %d bytes) from %s to %s FAILED\n", strCommand.c_str(), nMessageSize, pfrom->addr.ToString().c_str(), addrLocalHost.ToString().c_str());
1729 }
1730
1731 vRecv.Compact();
1732 return true;
1733}
1734
1735
1736
1737
1738bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
1739{
1740 static map<unsigned int, vector<unsigned char> > mapReuseKey;
1741 printf("received: %-12s (%d bytes) ", strCommand.c_str(), vRecv.size());
1742 for (int i = 0; i < min(vRecv.size(), (unsigned int)25); i++)
1743 printf("%02x ", vRecv[i] & 0xff);
1744 printf("\n");
1745 if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0)
1746 {
1747 printf("dropmessages DROPPING RECV MESSAGE\n");
1748 return true;
1749 }
1750
1751
1752
1753 if (strCommand == "version")
1754 {
1755 // Can only do this once
1756 if (pfrom->nVersion != 0)
1757 return false;
1758
1759 int64 nTime;
1760 CAddress addrMe;
1761 vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;
1762 if (pfrom->nVersion == 0)
1763 return false;
1764
1765 pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION));
1766 pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));
1767
1768 pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);
1769 if (pfrom->fClient)
1770 {
1771 pfrom->vSend.nType |= SER_BLOCKHEADERONLY;
1772 pfrom->vRecv.nType |= SER_BLOCKHEADERONLY;
1773 }
1774
1775 AddTimeData(pfrom->addr.ip, nTime);
1776
1777 // Ask the first connected node for block updates
1778 static bool fAskedForBlocks;
1779 if (!fAskedForBlocks && !pfrom->fClient)
1780 {
1781 fAskedForBlocks = true;
1782 pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), uint256(0));
1783 }
1784
1785 printf("version addrMe = %s\n", addrMe.ToString().c_str());
1786 }
1787
1788
1789 else if (pfrom->nVersion == 0)
1790 {
1791 // Must have a version message before anything else
1792 return false;
1793 }
1794
1795
1796 else if (strCommand == "addr")
1797 {
1798 vector<CAddress> vAddr;
1799 vRecv >> vAddr;
1800
1801 // Store the new addresses
1802 CAddrDB addrdb;
1803 foreach(const CAddress& addr, vAddr)
1804 {
1805 if (fShutdown)
1806 return true;
1807 if (AddAddress(addrdb, addr))
1808 {
1809 // Put on lists to send to other nodes
1810 pfrom->setAddrKnown.insert(addr);
1811 CRITICAL_BLOCK(cs_vNodes)
1812 foreach(CNode* pnode, vNodes)
1813 if (!pnode->setAddrKnown.count(addr))
1814 pnode->vAddrToSend.push_back(addr);
1815 }
1816 }
1817 }
1818
1819
1820 else if (strCommand == "inv")
1821 {
1822 vector<CInv> vInv;
1823 vRecv >> vInv;
1824
1825 CTxDB txdb("r");
1826 foreach(const CInv& inv, vInv)
1827 {
1828 if (fShutdown)
1829 return true;
1830 pfrom->AddInventoryKnown(inv);
1831
1832 bool fAlreadyHave = AlreadyHave(txdb, inv);
1833 printf(" got inventory: %s %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new");
1834
1835 if (!fAlreadyHave)
1836 pfrom->AskFor(inv);
1837 else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
1838 pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), GetOrphanRoot(mapOrphanBlocks[inv.hash]));
1839 }
1840 }
1841
1842
1843 else if (strCommand == "getdata")
1844 {
1845 vector<CInv> vInv;
1846 vRecv >> vInv;
1847
1848 foreach(const CInv& inv, vInv)
1849 {
1850 if (fShutdown)
1851 return true;
1852 printf("received getdata for: %s\n", inv.ToString().c_str());
1853
1854 if (inv.type == MSG_BLOCK)
1855 {
1856 // Send block from disk
1857 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(inv.hash);
1858 if (mi != mapBlockIndex.end())
1859 {
1860 //// could optimize this to send header straight from blockindex for client
1861 CBlock block;
1862 block.ReadFromDisk((*mi).second, !pfrom->fClient);
1863 pfrom->PushMessage("block", block);
1864 }
1865 }
1866 else if (inv.IsKnownType())
1867 {
1868 // Send stream from relay memory
1869 CRITICAL_BLOCK(cs_mapRelay)
1870 {
1871 map<CInv, CDataStream>::iterator mi = mapRelay.find(inv);
1872 if (mi != mapRelay.end())
1873 pfrom->PushMessage(inv.GetCommand(), (*mi).second);
1874 }
1875 }
1876 }
1877 }
1878
1879
1880 else if (strCommand == "getblocks")
1881 {
1882 CBlockLocator locator;
1883 uint256 hashStop;
1884 vRecv >> locator >> hashStop;
1885
1886 // Find the first block the caller has in the main chain
1887 CBlockIndex* pindex = locator.GetBlockIndex();
1888
1889 // Send the rest of the chain
1890 if (pindex)
1891 pindex = pindex->pnext;
1892 printf("getblocks %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,14).c_str());
1893 for (; pindex; pindex = pindex->pnext)
1894 {
1895 if (pindex->GetBlockHash() == hashStop)
1896 {
1897 printf(" getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,14).c_str());
1898 break;
1899 }
1900
1901 // Bypass setInventoryKnown in case an inventory message got lost
1902 CRITICAL_BLOCK(pfrom->cs_inventory)
1903 {
1904 CInv inv(MSG_BLOCK, pindex->GetBlockHash());
1905 // returns true if wasn't already contained in the set
1906 if (pfrom->setInventoryKnown2.insert(inv).second)
1907 {
1908 pfrom->setInventoryKnown.erase(inv);
1909 pfrom->vInventoryToSend.push_back(inv);
1910 }
1911 }
1912 }
1913 }
1914
1915
1916 else if (strCommand == "tx")
1917 {
1918 vector<uint256> vWorkQueue;
1919 CDataStream vMsg(vRecv);
1920 CTransaction tx;
1921 vRecv >> tx;
1922
1923 CInv inv(MSG_TX, tx.GetHash());
1924 pfrom->AddInventoryKnown(inv);
1925
1926 bool fMissingInputs = false;
1927 if (tx.AcceptTransaction(true, &fMissingInputs))
1928 {
1929 AddToWalletIfMine(tx, NULL);
1930 RelayMessage(inv, vMsg);
1931 mapAlreadyAskedFor.erase(inv);
1932 vWorkQueue.push_back(inv.hash);
1933
1934 // Recursively process any orphan transactions that depended on this one
1935 for (int i = 0; i < vWorkQueue.size(); i++)
1936 {
1937 uint256 hashPrev = vWorkQueue[i];
1938 for (multimap<uint256, CDataStream*>::iterator mi = mapOrphanTransactionsByPrev.lower_bound(hashPrev);
1939 mi != mapOrphanTransactionsByPrev.upper_bound(hashPrev);
1940 ++mi)
1941 {
1942 const CDataStream& vMsg = *((*mi).second);
1943 CTransaction tx;
1944 CDataStream(vMsg) >> tx;
1945 CInv inv(MSG_TX, tx.GetHash());
1946
1947 if (tx.AcceptTransaction(true))
1948 {
1949 printf(" accepted orphan tx %s\n", inv.hash.ToString().substr(0,6).c_str());
1950 AddToWalletIfMine(tx, NULL);
1951 RelayMessage(inv, vMsg);
1952 mapAlreadyAskedFor.erase(inv);
1953 vWorkQueue.push_back(inv.hash);
1954 }
1955 }
1956 }
1957
1958 foreach(uint256 hash, vWorkQueue)
1959 EraseOrphanTx(hash);
1960 }
1961 else if (fMissingInputs)
1962 {
1963 printf("storing orphan tx %s\n", inv.hash.ToString().substr(0,6).c_str());
1964 AddOrphanTx(vMsg);
1965 }
1966 }
1967
1968
1969 else if (strCommand == "review")
1970 {
1971 CDataStream vMsg(vRecv);
1972 CReview review;
1973 vRecv >> review;
1974
1975 CInv inv(MSG_REVIEW, review.GetHash());
1976 pfrom->AddInventoryKnown(inv);
1977
1978 if (review.AcceptReview())
1979 {
1980 // Relay the original message as-is in case it's a higher version than we know how to parse
1981 RelayMessage(inv, vMsg);
1982 mapAlreadyAskedFor.erase(inv);
1983 }
1984 }
1985
1986
1987 else if (strCommand == "block")
1988 {
1989 auto_ptr<CBlock> pblock(new CBlock);
1990 vRecv >> *pblock;
1991
1992 //// debug print
1993 printf("received block:\n"); pblock->print();
1994
1995 CInv inv(MSG_BLOCK, pblock->GetHash());
1996 pfrom->AddInventoryKnown(inv);
1997
1998 if (ProcessBlock(pfrom, pblock.release()))
1999 mapAlreadyAskedFor.erase(inv);
2000 }
2001
2002
2003 else if (strCommand == "getaddr")
2004 {
2005 pfrom->vAddrToSend.clear();
2006 //// need to expand the time range if not enough found
2007 int64 nSince = GetAdjustedTime() - 60 * 60; // in the last hour
2008 CRITICAL_BLOCK(cs_mapAddresses)
2009 {
2010 foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
2011 {
2012 if (fShutdown)
2013 return true;
2014 const CAddress& addr = item.second;
2015 if (addr.nTime > nSince)
2016 pfrom->vAddrToSend.push_back(addr);
2017 }
2018 }
2019 }
2020
2021
2022 else if (strCommand == "checkorder")
2023 {
2024 uint256 hashReply;
2025 CWalletTx order;
2026 vRecv >> hashReply >> order;
2027
2028 /// we have a chance to check the order here
2029
2030 // Keep giving the same key to the same ip until they use it
2031 if (!mapReuseKey.count(pfrom->addr.ip))
2032 mapReuseKey[pfrom->addr.ip] = GenerateNewKey();
2033
2034 // Send back approval of order and pubkey to use
2035 CScript scriptPubKey;
2036 scriptPubKey << mapReuseKey[pfrom->addr.ip] << OP_CHECKSIG;
2037 pfrom->PushMessage("reply", hashReply, (int)0, scriptPubKey);
2038 }
2039
2040
2041 else if (strCommand == "submitorder")
2042 {
2043 uint256 hashReply;
2044 CWalletTx wtxNew;
2045 vRecv >> hashReply >> wtxNew;
2046
2047 // Broadcast
2048 if (!wtxNew.AcceptWalletTransaction())
2049 {
2050 pfrom->PushMessage("reply", hashReply, (int)1);
2051 return error("submitorder AcceptWalletTransaction() failed, returning error 1");
2052 }
2053 wtxNew.fTimeReceivedIsTxTime = true;
2054 AddToWallet(wtxNew);
2055 wtxNew.RelayWalletTransaction();
2056 mapReuseKey.erase(pfrom->addr.ip);
2057
2058 // Send back confirmation
2059 pfrom->PushMessage("reply", hashReply, (int)0);
2060 }
2061
2062
2063 else if (strCommand == "reply")
2064 {
2065 uint256 hashReply;
2066 vRecv >> hashReply;
2067
2068 CRequestTracker tracker;
2069 CRITICAL_BLOCK(pfrom->cs_mapRequests)
2070 {
2071 map<uint256, CRequestTracker>::iterator mi = pfrom->mapRequests.find(hashReply);
2072 if (mi != pfrom->mapRequests.end())
2073 {
2074 tracker = (*mi).second;
2075 pfrom->mapRequests.erase(mi);
2076 }
2077 }
2078 if (!tracker.IsNull())
2079 tracker.fn(tracker.param1, vRecv);
2080 }
2081
2082
2083 else
2084 {
2085 // Ignore unknown commands for extensibility
2086 printf("ProcessMessage(%s) : Ignored unknown message\n", strCommand.c_str());
2087 }
2088
2089
2090 if (!vRecv.empty())
2091 printf("ProcessMessage(%s) : %d extra bytes\n", strCommand.c_str(), vRecv.size());
2092
2093 return true;
2094}
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104bool SendMessages(CNode* pto)
2105{
2106 CheckForShutdown(2);
2107 CRITICAL_BLOCK(cs_main)
2108 {
2109 // Don't send anything until we get their version message
2110 if (pto->nVersion == 0)
2111 return true;
2112
2113
2114 //
2115 // Message: addr
2116 //
2117 vector<CAddress> vAddrToSend;
2118 vAddrToSend.reserve(pto->vAddrToSend.size());
2119 foreach(const CAddress& addr, pto->vAddrToSend)
2120 if (!pto->setAddrKnown.count(addr))
2121 vAddrToSend.push_back(addr);
2122 pto->vAddrToSend.clear();
2123 if (!vAddrToSend.empty())
2124 pto->PushMessage("addr", vAddrToSend);
2125
2126
2127 //
2128 // Message: inventory
2129 //
2130 vector<CInv> vInventoryToSend;
2131 CRITICAL_BLOCK(pto->cs_inventory)
2132 {
2133 vInventoryToSend.reserve(pto->vInventoryToSend.size());
2134 foreach(const CInv& inv, pto->vInventoryToSend)
2135 {
2136 // returns true if wasn't already contained in the set
2137 if (pto->setInventoryKnown.insert(inv).second)
2138 vInventoryToSend.push_back(inv);
2139 }
2140 pto->vInventoryToSend.clear();
2141 pto->setInventoryKnown2.clear();
2142 }
2143 if (!vInventoryToSend.empty())
2144 pto->PushMessage("inv", vInventoryToSend);
2145
2146
2147 //
2148 // Message: getdata
2149 //
2150 vector<CInv> vAskFor;
2151 int64 nNow = GetTime() * 1000000;
2152 CTxDB txdb("r");
2153 while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow)
2154 {
2155 const CInv& inv = (*pto->mapAskFor.begin()).second;
2156 printf("sending getdata: %s\n", inv.ToString().c_str());
2157 if (!AlreadyHave(txdb, inv))
2158 vAskFor.push_back(inv);
2159 pto->mapAskFor.erase(pto->mapAskFor.begin());
2160 }
2161 if (!vAskFor.empty())
2162 pto->PushMessage("getdata", vAskFor);
2163
2164 }
2165 return true;
2166}
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181//////////////////////////////////////////////////////////////////////////////
2182//
2183// BitcoinMiner
2184//
2185
2186int FormatHashBlocks(void* pbuffer, unsigned int len)
2187{
2188 unsigned char* pdata = (unsigned char*)pbuffer;
2189 unsigned int blocks = 1 + ((len + 8) / 64);
2190 unsigned char* pend = pdata + 64 * blocks;
2191 memset(pdata + len, 0, 64 * blocks - len);
2192 pdata[len] = 0x80;
2193 unsigned int bits = len * 8;
2194 pend[-1] = (bits >> 0) & 0xff;
2195 pend[-2] = (bits >> 8) & 0xff;
2196 pend[-3] = (bits >> 16) & 0xff;
2197 pend[-4] = (bits >> 24) & 0xff;
2198 return blocks;
2199}
2200
2201using CryptoPP::ByteReverse;
2202static int detectlittleendian = 1;
2203
2204void BlockSHA256(const void* pin, unsigned int nBlocks, void* pout)
2205{
2206 unsigned int* pinput = (unsigned int*)pin;
2207 unsigned int* pstate = (unsigned int*)pout;
2208
2209 CryptoPP::SHA256::InitState(pstate);
2210
2211 if (*(char*)&detectlittleendian != 0)
2212 {
2213 for (int n = 0; n < nBlocks; n++)
2214 {
2215 unsigned int pbuf[16];
2216 for (int i = 0; i < 16; i++)
2217 pbuf[i] = ByteReverse(pinput[n * 16 + i]);
2218 CryptoPP::SHA256::Transform(pstate, pbuf);
2219 }
2220 for (int i = 0; i < 8; i++)
2221 pstate[i] = ByteReverse(pstate[i]);
2222 }
2223 else
2224 {
2225 for (int n = 0; n < nBlocks; n++)
2226 CryptoPP::SHA256::Transform(pstate, pinput + n * 16);
2227 }
2228}
2229
2230
2231bool BitcoinMiner()
2232{
2233 printf("BitcoinMiner started\n");
2234 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
2235
2236 CKey key;
2237 key.MakeNewKey();
2238 CBigNum bnExtraNonce = 0;
2239 while (fGenerateBitcoins)
2240 {
2241 Sleep(50);
2242 CheckForShutdown(3);
2243 while (vNodes.empty() && !fSoloMineTest)
2244 {
2245 Sleep(1000);
2246 CheckForShutdown(3);
2247 }
2248
2249 unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
2250 CBlockIndex* pindexPrev = pindexBest;
2251 unsigned int nBits = GetNextWorkRequired(pindexPrev);
2252
2253
2254 //
2255 // Create coinbase tx
2256 //
2257 CTransaction txNew;
2258 txNew.vin.resize(1);
2259 txNew.vin[0].prevout.SetNull();
2260 txNew.vin[0].scriptSig << nBits << ++bnExtraNonce;
2261 txNew.vout.resize(1);
2262 txNew.vout[0].scriptPubKey << key.GetPubKey() << OP_CHECKSIG;
2263
2264
2265 //
2266 // Create new block
2267 //
2268 auto_ptr<CBlock> pblock(new CBlock());
2269 if (!pblock.get())
2270 return false;
2271
2272 // Add our coinbase tx as first transaction
2273 pblock->vtx.push_back(txNew);
2274
2275 // Collect the latest transactions into the block
2276 int64 nFees = 0;
2277 CRITICAL_BLOCK(cs_main)
2278 CRITICAL_BLOCK(cs_mapTransactions)
2279 {
2280 CTxDB txdb("r");
2281 map<uint256, CTxIndex> mapTestPool;
2282 vector<char> vfAlreadyAdded(mapTransactions.size());
2283 bool fFoundSomething = true;
2284 unsigned int nBlockSize = 0;
2285 while (fFoundSomething && nBlockSize < MAX_SIZE/2)
2286 {
2287 fFoundSomething = false;
2288 unsigned int n = 0;
2289 for (map<uint256, CTransaction>::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi, ++n)
2290 {
2291 if (vfAlreadyAdded[n])
2292 continue;
2293 CTransaction& tx = (*mi).second;
2294 if (tx.IsCoinBase() || !tx.IsFinal())
2295 continue;
2296
2297 // Transaction fee requirements, mainly only needed for flood control
2298 // Under 10K (about 80 inputs) is free for first 100 transactions
2299 // Base rate is 0.01 per KB
2300 int64 nMinFee = tx.GetMinFee(pblock->vtx.size() < 100);
2301
2302 map<uint256, CTxIndex> mapTestPoolTmp(mapTestPool);
2303 if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), 0, nFees, false, true, nMinFee))
2304 continue;
2305 swap(mapTestPool, mapTestPoolTmp);
2306
2307 pblock->vtx.push_back(tx);
2308 nBlockSize += ::GetSerializeSize(tx, SER_NETWORK);
2309 vfAlreadyAdded[n] = true;
2310 fFoundSomething = true;
2311 }
2312 }
2313 }
2314 pblock->nBits = nBits;
2315 pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(nFees);
2316 printf("\n\nRunning BitcoinMiner with %d transactions in block\n", pblock->vtx.size());
2317
2318
2319 //
2320 // Prepare the block header
2321 //
2322 pblock->hashPrevBlock = (pindexPrev ? pindexPrev->GetBlockHash() : 0);
2323 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
2324 pblock->nTime = max((pindexPrev ? pindexPrev->GetMedianTimePast()+1 : 0), GetAdjustedTime());
2325 pblock->nBits = nBits;
2326 pblock->nNonce = 1;
2327
2328
2329 //
2330 // Search (memory-hard RandomX PoW) -- each thread uses its own VM
2331 //
2332 void* rxvm = RandomXCreateMinerVM();
2333 if (!rxvm)
2334 {
2335 printf("BitcoinMiner: failed to create RandomX VM\n");
2336 Sleep(1000);
2337 continue;
2338 }
2339 printf("BitcoinMiner: mining with RandomX (%s)\n",
2340 RandomXFastReady() ? "fast 2GB" : "light 256MB");
2341
2342 unsigned int nStart = GetTime();
2343 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
2344 loop
2345 {
2346 uint256 hash = RandomXHashWithVM(rxvm, (const void*)BEGIN(pblock->nVersion),
2347 END(pblock->nNonce) - BEGIN(pblock->nVersion));
2348
2349 if (hash <= hashTarget)
2350 {
2351 //// debug print
2352 printf("BitcoinMiner:\n");
2353 printf("RandomX proof-of-work found \n powhash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
2354 pblock->print();
2355
2356 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
2357 CRITICAL_BLOCK(cs_main)
2358 {
2359 // Save key
2360 if (!AddKey(key))
2361 {
2362 RandomXDestroyMinerVM(rxvm);
2363 return false;
2364 }
2365 key.MakeNewKey();
2366
2367 // Process this block the same as if we had received it from another node
2368 if (!ProcessBlock(NULL, pblock.release()))
2369 printf("ERROR in BitcoinMiner, ProcessBlock, block not accepted\n");
2370 }
2371 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
2372
2373 Sleep(500);
2374 break;
2375 }
2376
2377 // Check stop conditions periodically (RandomX is slow, so every
2378 // ~256 hashes is already plenty of time)
2379 if ((++pblock->nNonce & 0xff) == 0)
2380 {
2381 CheckForShutdown(3);
2382 if (pblock->nNonce == 0)
2383 break;
2384 if (pindexPrev != pindexBest)
2385 break;
2386 if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)
2387 break;
2388 if (!fGenerateBitcoins)
2389 break;
2390 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
2391 }
2392 }
2393 RandomXDestroyMinerVM(rxvm);
2394 }
2395
2396 return true;
2397}
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416//////////////////////////////////////////////////////////////////////////////
2417//
2418// Actions
2419//
2420
2421
2422int64 GetBalance()
2423{
2424 int64 nStart, nEnd;
2425 QueryPerformanceCounter((LARGE_INTEGER*)&nStart);
2426
2427 int64 nTotal = 0;
2428 CRITICAL_BLOCK(cs_mapWallet)
2429 {
2430 for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
2431 {
2432 CWalletTx* pcoin = &(*it).second;
2433 if (!pcoin->IsFinal() || pcoin->fSpent)
2434 continue;
2435 nTotal += pcoin->GetCredit();
2436 }
2437 }
2438
2439 QueryPerformanceCounter((LARGE_INTEGER*)&nEnd);
2440 ///printf(" GetBalance() time = %16I64d\n", nEnd - nStart);
2441 return nTotal;
2442}
2443
2444
2445
2446bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
2447{
2448 setCoinsRet.clear();
2449
2450 // List of values less than target
2451 int64 nLowestLarger = _I64_MAX;
2452 CWalletTx* pcoinLowestLarger = NULL;
2453 vector<pair<int64, CWalletTx*> > vValue;
2454 int64 nTotalLower = 0;
2455
2456 CRITICAL_BLOCK(cs_mapWallet)
2457 {
2458 for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
2459 {
2460 CWalletTx* pcoin = &(*it).second;
2461 if (!pcoin->IsFinal() || pcoin->fSpent)
2462 continue;
2463 int64 n = pcoin->GetCredit();
2464 if (n <= 0)
2465 continue;
2466 if (n < nTargetValue)
2467 {
2468 vValue.push_back(make_pair(n, pcoin));
2469 nTotalLower += n;
2470 }
2471 else if (n == nTargetValue)
2472 {
2473 setCoinsRet.insert(pcoin);
2474 return true;
2475 }
2476 else if (n < nLowestLarger)
2477 {
2478 nLowestLarger = n;
2479 pcoinLowestLarger = pcoin;
2480 }
2481 }
2482 }
2483
2484 if (nTotalLower < nTargetValue)
2485 {
2486 if (pcoinLowestLarger == NULL)
2487 return false;
2488 setCoinsRet.insert(pcoinLowestLarger);
2489 return true;
2490 }
2491
2492 // Solve subset sum by stochastic approximation
2493 sort(vValue.rbegin(), vValue.rend());
2494 vector<char> vfIncluded;
2495 vector<char> vfBest(vValue.size(), true);
2496 int64 nBest = nTotalLower;
2497
2498 for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)
2499 {
2500 vfIncluded.assign(vValue.size(), false);
2501 int64 nTotal = 0;
2502 bool fReachedTarget = false;
2503 for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
2504 {
2505 for (int i = 0; i < vValue.size(); i++)
2506 {
2507 if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
2508 {
2509 nTotal += vValue[i].first;
2510 vfIncluded[i] = true;
2511 if (nTotal >= nTargetValue)
2512 {
2513 fReachedTarget = true;
2514 if (nTotal < nBest)
2515 {
2516 nBest = nTotal;
2517 vfBest = vfIncluded;
2518 }
2519 nTotal -= vValue[i].first;
2520 vfIncluded[i] = false;
2521 }
2522 }
2523 }
2524 }
2525 }
2526
2527 // If the next larger is still closer, return it
2528 if (pcoinLowestLarger && nLowestLarger - nTargetValue <= nBest - nTargetValue)
2529 setCoinsRet.insert(pcoinLowestLarger);
2530 else
2531 {
2532 for (int i = 0; i < vValue.size(); i++)
2533 if (vfBest[i])
2534 setCoinsRet.insert(vValue[i].second);
2535
2536 //// debug print
2537 printf("SelectCoins() best subset: ");
2538 for (int i = 0; i < vValue.size(); i++)
2539 if (vfBest[i])
2540 printf("%s ", FormatMoney(vValue[i].first).c_str());
2541 printf("total %s\n", FormatMoney(nBest).c_str());
2542 }
2543
2544 return true;
2545}
2546
2547
2548
2549
2550bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, int64& nFeeRequiredRet)
2551{
2552 nFeeRequiredRet = 0;
2553 CRITICAL_BLOCK(cs_main)
2554 {
2555 // txdb must be opened before the mapWallet lock
2556 CTxDB txdb("r");
2557 CRITICAL_BLOCK(cs_mapWallet)
2558 {
2559 int64 nFee = nTransactionFee;
2560 loop
2561 {
2562 wtxNew.vin.clear();
2563 wtxNew.vout.clear();
2564 if (nValue < 0)
2565 return false;
2566 int64 nValueOut = nValue;
2567 nValue += nFee;
2568
2569 // Choose coins to use
2570 set<CWalletTx*> setCoins;
2571 if (!SelectCoins(nValue, setCoins))
2572 return false;
2573 int64 nValueIn = 0;
2574 foreach(CWalletTx* pcoin, setCoins)
2575 nValueIn += pcoin->GetCredit();
2576
2577 // Fill vout[0] to the payee
2578 wtxNew.vout.push_back(CTxOut(nValueOut, scriptPubKey));
2579
2580 // Fill vout[1] back to self with any change
2581 if (nValueIn > nValue)
2582 {
2583 // Use the same key as one of the coins
2584 vector<unsigned char> vchPubKey;
2585 CTransaction& txFirst = *(*setCoins.begin());
2586 foreach(const CTxOut& txout, txFirst.vout)
2587 if (txout.IsMine())
2588 if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
2589 break;
2590 if (vchPubKey.empty())
2591 return false;
2592
2593 // Fill vout[1] to ourself
2594 CScript scriptPubKey;
2595 scriptPubKey << vchPubKey << OP_CHECKSIG;
2596 wtxNew.vout.push_back(CTxOut(nValueIn - nValue, scriptPubKey));
2597 }
2598
2599 // Fill vin
2600 foreach(CWalletTx* pcoin, setCoins)
2601 for (int nOut = 0; nOut < pcoin->vout.size(); nOut++)
2602 if (pcoin->vout[nOut].IsMine())
2603 wtxNew.vin.push_back(CTxIn(pcoin->GetHash(), nOut));
2604
2605 // Sign
2606 int nIn = 0;
2607 foreach(CWalletTx* pcoin, setCoins)
2608 for (int nOut = 0; nOut < pcoin->vout.size(); nOut++)
2609 if (pcoin->vout[nOut].IsMine())
2610 SignSignature(*pcoin, wtxNew, nIn++);
2611
2612 // Check that enough fee is included
2613 if (nFee < wtxNew.GetMinFee(true))
2614 {
2615 nFee = nFeeRequiredRet = wtxNew.GetMinFee(true);
2616 continue;
2617 }
2618
2619 // Fill vtxPrev by copying from previous transactions vtxPrev
2620 wtxNew.AddSupportingTransactions(txdb);
2621 wtxNew.fTimeReceivedIsTxTime = true;
2622
2623 break;
2624 }
2625 }
2626 }
2627 return true;
2628}
2629
2630// Call after CreateTransaction unless you want to abort
2631bool CommitTransactionSpent(const CWalletTx& wtxNew)
2632{
2633 CRITICAL_BLOCK(cs_main)
2634 CRITICAL_BLOCK(cs_mapWallet)
2635 {
2636 //// todo: make this transactional, never want to add a transaction
2637 //// without marking spent transactions
2638
2639 // Add tx to wallet, because if it has change it's also ours,
2640 // otherwise just for transaction history.
2641 AddToWallet(wtxNew);
2642
2643 // Mark old coins as spent
2644 set<CWalletTx*> setCoins;
2645 foreach(const CTxIn& txin, wtxNew.vin)
2646 setCoins.insert(&mapWallet[txin.prevout.hash]);
2647 foreach(CWalletTx* pcoin, setCoins)
2648 {
2649 pcoin->fSpent = true;
2650 pcoin->WriteToDisk();
2651 vWalletUpdated.push_back(make_pair(pcoin->GetHash(), false));
2652 }
2653 }
2654 MainFrameRepaint();
2655 return true;
2656}
2657
2658
2659
2660
2661bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
2662{
2663 CRITICAL_BLOCK(cs_main)
2664 {
2665 int64 nFeeRequired;
2666 if (!CreateTransaction(scriptPubKey, nValue, wtxNew, nFeeRequired))
2667 {
2668 string strError;
2669 if (nValue + nFeeRequired > GetBalance())
2670 strError = strprintf("Error: This is an oversized transaction that requires a transaction fee of %s ", FormatMoney(nFeeRequired).c_str());
2671 else
2672 strError = "Error: Transaction creation failed ";
2673 wxMessageBox(strError, "Sending...");
2674 return error("SendMoney() : %s\n", strError.c_str());
2675 }
2676 if (!CommitTransactionSpent(wtxNew))
2677 {
2678 wxMessageBox("Error finalizing transaction", "Sending...");
2679 return error("SendMoney() : Error finalizing transaction");
2680 }
2681
2682 printf("SendMoney: %s\n", wtxNew.GetHash().ToString().substr(0,6).c_str());
2683
2684 // Broadcast
2685 if (!wtxNew.AcceptTransaction())
2686 {
2687 // This must not fail. The transaction has already been signed and recorded.
2688 throw runtime_error("SendMoney() : wtxNew.AcceptTransaction() failed\n");
2689 wxMessageBox("Error: Transaction not valid", "Sending...");
2690 return error("SendMoney() : Error: Transaction not valid");
2691 }
2692 wtxNew.RelayWalletTransaction();
2693 }
2694 MainFrameRepaint();
2695 return true;
2696}