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-coin <bookofshamers@outlook.com>2026-08-04 06:34:32 -0700
committerbitflash-coin <bookofshamers@outlook.com>2026-08-04 06:34:32 -0700
commit5ce650382352c1503f40abf08129ada69402af55 (patch)
tree6a18198901f1e2c4933f1ac53c9365eec512bf63 /src/main.cpp
parentf34113291da7e5e3dc7d2468d4f9c212c05c584b (diff)
public commit
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp4609
1 files changed, 4609 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..0342650
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,4609 @@
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#pragma push_macro("snprintf")
6#undef snprintf
7#include <nlohmann/json.hpp>
8#pragma pop_macro("snprintf")
9#ifdef snprintf
10#undef snprintf
11#endif
12#include "headers.h"
13#include "sha.h"
14#include <atomic>
15#include <mutex>
16#include <thread>
17#include "bip32.h"
18#include "btfaddr.h"
19#include "btftunnel.h"
20#ifndef _WIN32
21#include <sys/socket.h>
22#include <netinet/in.h>
23#include <arpa/inet.h>
24#include <netdb.h>
25#include <unistd.h>
26#endif
27
28
29
30
31
32//
33// Global state
34//
35
36CCriticalSection cs_main;
37
38map<uint256, CTransaction> mapTransactions;
39CCriticalSection cs_mapTransactions;
40unsigned int nTransactionsUpdated = 0;
41map<COutPoint, CInPoint> mapNextTx;
42
43map<uint256, CBlockIndex*> mapBlockIndex;
44// Bitflash genesis -- mined under RandomX PoW on 2026-07-22
45// (nTime 1753142400, nBits 0x1f0fffff, RandomX key "Bitflash/RandomX/v1/...")
46// Bitflash 2026 stable relaunch genesis (2-min blocks, RandomX). Mined values.
47unsigned int GENESIS_NONCE = 3141;
48uint256 hashGenesisBlock("0x5bd7cb255d814e48cebcdfb72da4dc87b34bd774227f8ceb546c5640f4bdc169");
49uint256 hashGenesisMerkleRoot("0x1a45b4482532abb29b10e234d3f13132230525a339ecea91658ffa675a5b1325");
50CBlockIndex* pindexGenesisBlock = NULL;
51int nBestHeight = -1;
52uint256 hashBestChain = 0;
53// Blocks at the tip to re-verify on startup. 0 means the whole chain. 288 is
54// about ten hours at a two-minute target -- far enough back to catch a bad tip,
55// short enough that startup does not pay a RandomX hash per block for the whole
56// history. /checkblocks=N overrides it.
57int nCheckBlocksOnLoad = 288;
58// Set by CTxDB::LoadBlockIndex when the tail of the chain fails verification.
59// The repair runs in LoadBlockIndex() below, once that read-only handle and its
60// cursor are closed.
61CBlockIndex* pindexBadChainFork = NULL;
62CBlockIndex* pindexBest = NULL;
63
64map<uint256, CBlock*> mapOrphanBlocks;
65multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
66
67map<uint256, CDataStream*> mapOrphanTransactions;
68multimap<uint256, CDataStream*> mapOrphanTransactionsByPrev;
69
70map<uint256, CWalletTx> mapWallet;
71vector<pair<uint256, bool> > vWalletUpdated;
72CCriticalSection cs_mapWallet;
73
74map<vector<unsigned char>, CPrivKey> mapKeys;
75map<vector<unsigned char>, vector<unsigned char> > mapCryptedKeys;
76map<uint160, vector<unsigned char> > mapPubKeys;
77map<unsigned int, CWalletMasterKey> mapMasterKeys;
78unsigned int nWalletMasterKeyMaxID = 0;
79CKeyingMaterial vWalletMasterKey;
80vector<unsigned char> vchCryptedHDMaster;
81vector<unsigned char> vchCryptedHDChainCode;
82bool fWalletEncrypted = false;
83bool fWalletLocked = true;
84CCriticalSection cs_mapKeys;
85CKey keyUser;
86
87string strSetDataDir;
88int nDropMessagesTest = 0;
89bool fSoloMineTest = false; // /solomine: mine without requiring a peer (local test)
90
91// Settings
92int fGenerateBitcoins;
93// How many threads to hash with. 0 means "decide from the hardware" -- see
94// MinerThreadCount(). This was effectively 1 forever, because Bitcoin 0.1.0
95// started exactly one miner thread and nothing here ever changed that. It made
96// sense for SHA-256d in 2009; RandomX is built to be fed by every core at once,
97// so a 32-core machine was mining at a thirty-second of its capacity and the
98// only visible symptom was a suspiciously idle CPU.
99int nMinerThreads = 0;
100int64 nTransactionFee = 0;
101CAddress addrIncoming;
102int nMineMode = MINE_RELAY;
103bool fMineModeFromCommandLine = false;
104string strParticipantPool; // participant mode: pool .btf address
105string strPoolName = "Bitflash Pool";
106string strPoolDashboardUrl;
107double dPoolFeePercent = 0.0;
108
109static std::atomic<uint64> gParticipantSharesSent{0};
110static std::atomic<uint64> gParticipantSharesAccepted{0};
111static std::atomic<uint64> gParticipantHashes{0};
112static std::atomic<uint64> gParticipantHashRateX1000{0};
113static std::mutex gParticipantStatusMutex;
114static std::string gParticipantStatus;
115
116void SetParticipantMiningStatus(const std::string& status)
117{
118 // Updates the GUI status string only. Logging is done at each call site
119 // with full context; duplicating it here just adds noise to the log.
120 std::lock_guard<std::mutex> lk(gParticipantStatusMutex);
121 gParticipantStatus = status;
122}
123
124std::string GetParticipantMiningStatus()
125{
126 std::lock_guard<std::mutex> lk(gParticipantStatusMutex);
127 return gParticipantStatus;
128}
129
130void GetParticipantMiningStats(uint64& sharesSent, uint64& sharesAccepted, double& hashRate)
131{
132 sharesSent = gParticipantSharesSent.load();
133 sharesAccepted = gParticipantSharesAccepted.load();
134 hashRate = (double)gParticipantHashRateX1000.load() / 1000.0;
135}
136
137
138
139
140
141
142
143//////////////////////////////////////////////////////////////////////////////
144//
145// mapKeys
146//
147
148// Threads to hash with, resolving the automatic case.
149//
150// Automatic leaves one core to the rest of the node -- accepting blocks,
151// talking to peers, serving the GUI -- because a machine that mines perfectly
152// while falling behind the chain has won nothing. Anyone who disagrees can say
153// so with /genproclimit and get exactly what they ask for.
154//
155// Memory is not the reason to hold back: the ~2 GB RandomX dataset is shared by
156// every thread, and each one adds only its own 2 MB scratchpad. Sixteen threads
157// cost about 32 MB more than one.
158int MinerThreadCount()
159{
160 if (nMinerThreads > 0)
161 return nMinerThreads;
162 unsigned int nCores = std::thread::hardware_concurrency();
163 if (nCores <= 1)
164 return 1;
165 return (int)(nCores - 1);
166}
167
168bool AddKey(const CKey& key)
169{
170 if (IsWalletEncrypted())
171 {
172 string strError;
173 CPrivKey vchPrivKey = key.GetPrivKey();
174 vector<unsigned char> vchCryptedSecret;
175 if (IsWalletLocked())
176 return error("AddKey() : wallet is locked\n");
177 if (!EncryptSecret(vWalletMasterKey, vector<unsigned char>(vchPrivKey.begin(), vchPrivKey.end()),
178 WalletKeyIV(key.GetPubKey()), vchCryptedSecret))
179 return error("AddKey() : encrypting key failed\n");
180 if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
181 return false;
182 return CWalletDB().WriteCryptedKey(key.GetPubKey(), vchCryptedSecret);
183 }
184
185 CRITICAL_BLOCK(cs_mapKeys)
186 {
187 mapKeys[key.GetPubKey()] = key.GetPrivKey();
188 mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
189 }
190 return CWalletDB().WriteKey(key.GetPubKey(), key.GetPrivKey());
191}
192
193bool IsWalletEncrypted()
194{
195 return fWalletEncrypted;
196}
197
198bool IsWalletLocked()
199{
200 return fWalletEncrypted && fWalletLocked;
201}
202
203void LockWallet()
204{
205 if (!fWalletEncrypted)
206 return;
207 CRITICAL_BLOCK(cs_mapKeys)
208 {
209 vWalletMasterKey.clear();
210 if (!vchCryptedHDMaster.empty())
211 vchHDMaster.clear();
212 if (!vchCryptedHDChainCode.empty())
213 vchHDChainCode.clear();
214 fWalletLocked = true;
215 }
216}
217
218bool DeriveWalletPassphraseKey(const string& strPassphrase,
219 const vector<unsigned char>& vchSalt,
220 unsigned int nDeriveIterations,
221 CKeyingMaterial& vchKeyRet,
222 vector<unsigned char>& vchIVRet)
223{
224 vchKeyRet.clear();
225 vchIVRet.clear();
226 if (vchSalt.size() != 8 || nDeriveIterations < 1)
227 return false;
228
229 unsigned char chKey[32];
230 unsigned char chIV[16];
231 int n = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &vchSalt[0],
232 (const unsigned char*)strPassphrase.data(),
233 (int)strPassphrase.size(),
234 (int)nDeriveIterations,
235 chKey, chIV);
236 if (n != 32)
237 {
238 memset(chKey, 0, sizeof(chKey));
239 memset(chIV, 0, sizeof(chIV));
240 return false;
241 }
242 vchKeyRet.assign(chKey, chKey + sizeof(chKey));
243 vchIVRet.assign(chIV, chIV + sizeof(chIV));
244 memset(chKey, 0, sizeof(chKey));
245 memset(chIV, 0, sizeof(chIV));
246 return true;
247}
248
249bool EncryptSecret(const CKeyingMaterial& vchKey,
250 const vector<unsigned char>& vchPlaintext,
251 const vector<unsigned char>& vchIV,
252 vector<unsigned char>& vchCiphertextRet)
253{
254 vchCiphertextRet.clear();
255 if (vchKey.size() != 32 || vchIV.size() != 16)
256 return false;
257
258 EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
259 if (!ctx)
260 return false;
261
262 bool fOk = false;
263 int nLen = 0;
264 int nFinal = 0;
265 vector<unsigned char> vchOut(vchPlaintext.size() + EVP_CIPHER_block_size(EVP_aes_256_cbc()));
266 if (EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, &vchKey[0], &vchIV[0]) &&
267 EVP_EncryptUpdate(ctx, &vchOut[0], &nLen,
268 vchPlaintext.empty() ? NULL : &vchPlaintext[0],
269 (int)vchPlaintext.size()) &&
270 EVP_EncryptFinal_ex(ctx, &vchOut[0] + nLen, &nFinal))
271 {
272 vchOut.resize(nLen + nFinal);
273 vchCiphertextRet.swap(vchOut);
274 fOk = true;
275 }
276 EVP_CIPHER_CTX_free(ctx);
277 return fOk;
278}
279
280bool DecryptSecret(const CKeyingMaterial& vchKey,
281 const vector<unsigned char>& vchCiphertext,
282 const vector<unsigned char>& vchIV,
283 vector<unsigned char>& vchPlaintextRet)
284{
285 vchPlaintextRet.clear();
286 if (vchKey.size() != 32 || vchIV.size() != 16 || vchCiphertext.empty())
287 return false;
288
289 EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
290 if (!ctx)
291 return false;
292
293 bool fOk = false;
294 int nLen = 0;
295 int nFinal = 0;
296 vector<unsigned char> vchOut(vchCiphertext.size());
297 if (EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, &vchKey[0], &vchIV[0]) &&
298 EVP_DecryptUpdate(ctx, &vchOut[0], &nLen, &vchCiphertext[0],
299 (int)vchCiphertext.size()) &&
300 EVP_DecryptFinal_ex(ctx, &vchOut[0] + nLen, &nFinal))
301 {
302 vchOut.resize(nLen + nFinal);
303 vchPlaintextRet.swap(vchOut);
304 fOk = true;
305 }
306 EVP_CIPHER_CTX_free(ctx);
307 return fOk;
308}
309
310vector<unsigned char> WalletKeyIV(const vector<unsigned char>& vchPubKey)
311{
312 uint256 hash = Hash(vchPubKey.begin(), vchPubKey.end());
313 vector<unsigned char> vchIV(16);
314 memcpy(&vchIV[0], hash.begin(), vchIV.size());
315 return vchIV;
316}
317
318vector<unsigned char> WalletSecretIV(const string& strLabel)
319{
320 uint256 hash = Hash(strLabel.begin(), strLabel.end());
321 vector<unsigned char> vchIV(16);
322 memcpy(&vchIV[0], hash.begin(), vchIV.size());
323 return vchIV;
324}
325
326bool AddCryptedKey(const vector<unsigned char>& vchPubKey,
327 const vector<unsigned char>& vchCryptedSecret)
328{
329 if (vchPubKey.empty() || vchCryptedSecret.empty())
330 return false;
331 CRITICAL_BLOCK(cs_mapKeys)
332 {
333 fWalletEncrypted = true;
334 mapCryptedKeys[vchPubKey] = vchCryptedSecret;
335 mapPubKeys[Hash160(vchPubKey)] = vchPubKey;
336 }
337 return true;
338}
339
340bool WalletCanSpendKey(const vector<unsigned char>& vchPubKey)
341{
342 CRITICAL_BLOCK(cs_mapKeys)
343 return mapKeys.count(vchPubKey) > 0 || mapCryptedKeys.count(vchPubKey) > 0;
344 return false;
345}
346
347bool GetWalletPrivKey(const vector<unsigned char>& vchPubKey,
348 CPrivKey& vchPrivKeyRet,
349 string& strErrorRet)
350{
351 vchPrivKeyRet.clear();
352 CRITICAL_BLOCK(cs_mapKeys)
353 {
354 map<vector<unsigned char>, CPrivKey>::iterator mi = mapKeys.find(vchPubKey);
355 if (mi != mapKeys.end())
356 {
357 vchPrivKeyRet = (*mi).second;
358 return true;
359 }
360
361 map<vector<unsigned char>, vector<unsigned char> >::iterator mci = mapCryptedKeys.find(vchPubKey);
362 if (mci == mapCryptedKeys.end())
363 {
364 strErrorRet = "private key not found";
365 return false;
366 }
367 if (IsWalletLocked())
368 {
369 strErrorRet = "wallet is locked";
370 return false;
371 }
372
373 vector<unsigned char> vchPlaintext;
374 if (!DecryptSecret(vWalletMasterKey, (*mci).second, WalletKeyIV(vchPubKey), vchPlaintext))
375 {
376 strErrorRet = "could not decrypt private key";
377 return false;
378 }
379
380 CPrivKey vchPrivKey(vchPlaintext.begin(), vchPlaintext.end());
381 CKey key;
382 if (!key.SetPrivKey(vchPrivKey) || key.GetPubKey() != vchPubKey)
383 {
384 strErrorRet = "decrypted private key does not match its public key";
385 return false;
386 }
387 vchPrivKeyRet = vchPrivKey;
388 return true;
389 }
390 return false;
391}
392
393bool UnlockWallet(const string& strPassphrase, string& strErrorRet)
394{
395 strErrorRet.clear();
396 if (!IsWalletEncrypted())
397 return true;
398
399 CRITICAL_BLOCK(cs_mapKeys)
400 {
401 for (map<unsigned int, CWalletMasterKey>::iterator mi = mapMasterKeys.begin();
402 mi != mapMasterKeys.end(); ++mi)
403 {
404 const CWalletMasterKey& kMasterKey = (*mi).second;
405 CKeyingMaterial vchPassKey;
406 vector<unsigned char> vchPassIV;
407 if (!DeriveWalletPassphraseKey(strPassphrase, kMasterKey.vchSalt,
408 kMasterKey.nDeriveIterations,
409 vchPassKey, vchPassIV))
410 continue;
411
412 vector<unsigned char> vchMasterPlain;
413 if (!DecryptSecret(vchPassKey, kMasterKey.vchCryptedKey,
414 vchPassIV, vchMasterPlain))
415 continue;
416 if (vchMasterPlain.size() != 32)
417 continue;
418
419 CKeyingMaterial vchCandidate(vchMasterPlain.begin(), vchMasterPlain.end());
420 bool fValid = mapCryptedKeys.empty();
421 for (map<vector<unsigned char>, vector<unsigned char> >::iterator mci = mapCryptedKeys.begin();
422 mci != mapCryptedKeys.end(); ++mci)
423 {
424 vector<unsigned char> vchPlaintext;
425 if (!DecryptSecret(vchCandidate, (*mci).second, WalletKeyIV((*mci).first), vchPlaintext))
426 break;
427 CPrivKey vchPrivKey(vchPlaintext.begin(), vchPlaintext.end());
428 CKey key;
429 if (key.SetPrivKey(vchPrivKey) && key.GetPubKey() == (*mci).first)
430 fValid = true;
431 break;
432 }
433 if (fValid)
434 {
435 vWalletMasterKey = vchCandidate;
436 if (!vchCryptedHDMaster.empty())
437 {
438 vector<unsigned char> vchPlainHDMaster;
439 if (!DecryptSecret(vWalletMasterKey, vchCryptedHDMaster,
440 WalletSecretIV("hdmaster"), vchPlainHDMaster) ||
441 vchPlainHDMaster.size() != 32)
442 {
443 strErrorRet = "could not decrypt HD master key";
444 return false;
445 }
446 vchHDMaster = vchPlainHDMaster;
447 }
448 if (!vchCryptedHDChainCode.empty())
449 {
450 vector<unsigned char> vchPlainHDChainCode;
451 if (!DecryptSecret(vWalletMasterKey, vchCryptedHDChainCode,
452 WalletSecretIV("hdchaincode"), vchPlainHDChainCode) ||
453 vchPlainHDChainCode.size() != 32)
454 {
455 strErrorRet = "could not decrypt HD chain code";
456 return false;
457 }
458 vchHDChainCode = vchPlainHDChainCode;
459 }
460 fWalletLocked = false;
461 return true;
462 }
463 }
464 }
465
466 strErrorRet = "passphrase did not unlock the wallet";
467 return false;
468}
469
470static bool WalletAlreadyHasKey(const vector<unsigned char>& vchPubKey)
471{
472 CRITICAL_BLOCK(cs_mapKeys)
473 return mapKeys.count(vchPubKey) > 0 || mapCryptedKeys.count(vchPubKey) > 0;
474 return false;
475}
476
477static bool AddKeyIfMissing(const CKey& key)
478{
479 if (WalletAlreadyHasKey(key.GetPubKey()))
480 return true;
481 return AddKey(key);
482}
483
484static bool DeriveNextHDReceiveKey(vector<unsigned char>& vchPubKeyRet, string& strErrorRet)
485{
486 vchPubKeyRet.clear();
487 CRITICAL_BLOCK(cs_keyPool)
488 {
489 if (!HaveHDSeed())
490 {
491 strErrorRet = "no seed";
492 return false;
493 }
494
495 CKey key;
496 unsigned int nIndex = 0;
497 if (nHDKeySchema == HD_SCHEMA_BIP44)
498 nIndex = nHDReceiveNext;
499 else
500 nIndex = nHDNext;
501 if (!DeriveHDKey(nIndex, key, strErrorRet))
502 return false;
503 if (!AddKeyIfMissing(key))
504 {
505 strErrorRet = "could not write the derived key to wallet.dat";
506 return false;
507 }
508
509 unsigned int nNext = nIndex + 1;
510 if (nHDKeySchema == HD_SCHEMA_BIP44)
511 {
512 if (!CWalletDB().WriteHDReceiveNext(nNext))
513 {
514 strErrorRet = "could not advance the receive derivation counter";
515 return false;
516 }
517 nHDReceiveNext = nNext;
518 }
519 else
520 {
521 if (!CWalletDB().WriteHDNext(nNext))
522 {
523 strErrorRet = "could not advance the derivation counter";
524 return false;
525 }
526 nHDNext = nNext;
527 }
528
529 vchPubKeyRet = key.GetPubKey();
530 }
531 return true;
532}
533
534static bool DeriveNextHDChangeKey(vector<unsigned char>& vchPubKeyRet, string& strErrorRet)
535{
536 vchPubKeyRet.clear();
537 CRITICAL_BLOCK(cs_keyPool)
538 {
539 if (!HaveHDSeed())
540 {
541 strErrorRet = "no seed";
542 return false;
543 }
544
545 CKey key;
546 if (nHDKeySchema == HD_SCHEMA_BIP44)
547 {
548 if (!DeriveHDChangeKey(nHDChangeNext, key, strErrorRet))
549 return false;
550 if (!AddKeyIfMissing(key))
551 {
552 strErrorRet = "could not write the derived change key to wallet.dat";
553 return false;
554 }
555 unsigned int nNext = nHDChangeNext + 1;
556 if (!CWalletDB().WriteHDChangeNext(nNext))
557 {
558 strErrorRet = "could not advance the change derivation counter";
559 return false;
560 }
561 nHDChangeNext = nNext;
562 }
563 else
564 {
565 if (!DeriveHDKey(nHDNext, key, strErrorRet))
566 return false;
567 if (!AddKeyIfMissing(key))
568 {
569 strErrorRet = "could not write the derived change key to wallet.dat";
570 return false;
571 }
572 unsigned int nNext = nHDNext + 1;
573 if (!CWalletDB().WriteHDNext(nNext))
574 {
575 strErrorRet = "could not advance the derivation counter";
576 return false;
577 }
578 nHDNext = nNext;
579 }
580 vchPubKeyRet = key.GetPubKey();
581 }
582 return true;
583}
584
585vector<unsigned char> GenerateNewKey()
586{
587 CKey key;
588 key.MakeNewKey();
589 if (!AddKey(key))
590 throw runtime_error("GenerateNewKey() : AddKey failed\n");
591 return key.GetPubKey();
592}
593
594CCriticalSection cs_keyPool;
595map<int64, vector<unsigned char> > mapKeyPool;
596
597vector<unsigned char> vchHDMaster;
598vector<unsigned char> vchHDChainCode;
599unsigned int nHDNext = 0;
600int nHDKeySchema = HD_SCHEMA_NONE;
601unsigned int nHDReceiveNext = 0;
602unsigned int nHDChangeNext = 0;
603unsigned int nHDCoinType = HD_BIP44_COIN_TYPE_BITFLASH_PROVISIONAL;
604
605string HDKeySchemaName(int nSchema)
606{
607 if (nSchema == HD_SCHEMA_LEGACY)
608 return "legacy-hd";
609 if (nSchema == HD_SCHEMA_BIP44)
610 return "bip44";
611 return "none";
612}
613
614std::vector<unsigned int> HDLegacyPath(unsigned int nIndex)
615{
616 std::vector<unsigned int> path;
617 path.push_back(nIndex | bitflash::BIP32_HARDENED);
618 return path;
619}
620
621std::vector<unsigned int> HDBIP44Path(unsigned int nCoinType,
622 unsigned int nAccount,
623 unsigned int nChain,
624 unsigned int nIndex)
625{
626 std::vector<unsigned int> path;
627 path.push_back(HD_BIP44_PURPOSE | bitflash::BIP32_HARDENED);
628 path.push_back(nCoinType | bitflash::BIP32_HARDENED);
629 path.push_back(nAccount | bitflash::BIP32_HARDENED);
630 path.push_back(nChain);
631 path.push_back(nIndex);
632 return path;
633}
634
635static bool ClearKeyPoolRecords(string& strErrorRet)
636{
637 CWalletDB walletdb;
638 for (map<int64, vector<unsigned char> >::const_iterator mi = mapKeyPool.begin();
639 mi != mapKeyPool.end(); ++mi)
640 {
641 if (!walletdb.ErasePool(mi->first))
642 {
643 strErrorRet = strprintf("could not clear old key-pool entry %lld",
644 (long long)mi->first);
645 return false;
646 }
647 }
648 mapKeyPool.clear();
649 return true;
650}
651
652bool DeriveHDKey(unsigned int nIndex, CKey& keyRet, string& strErrorRet)
653{
654 if (!HaveHDSeed())
655 {
656 strErrorRet = "no seed";
657 return false;
658 }
659 if (nIndex >= bitflash::BIP32_HARDENED)
660 {
661 strErrorRet = "child index must be non-hardened; hardening is applied here";
662 return false;
663 }
664
665 bitflash::BIP32PrivateNode parent;
666 parent.privateKey = vchHDMaster;
667 parent.chainCode = vchHDChainCode;
668
669 bitflash::BIP32PrivateNode child;
670 std::vector<unsigned int> path = nHDKeySchema == HD_SCHEMA_BIP44
671 ? HDBIP44Path(nHDCoinType, HD_BIP44_ACCOUNT, HD_BIP44_CHAIN_RECEIVE, nIndex)
672 : HDLegacyPath(nIndex);
673 if (!bitflash::BIP32DerivePath(parent, path, child, strErrorRet))
674 return false;
675
676 if (!keyRet.SetSecret(child.privateKey))
677 {
678 strErrorRet = "derived scalar is not a usable key";
679 return false;
680 }
681 return true;
682}
683
684bool DeriveHDChangeKey(unsigned int nIndex, CKey& keyRet, string& strErrorRet)
685{
686 if (!HaveHDSeed())
687 {
688 strErrorRet = "no seed";
689 return false;
690 }
691 if (nIndex >= bitflash::BIP32_HARDENED)
692 {
693 strErrorRet = "child index must be non-hardened; hardening is applied here";
694 return false;
695 }
696
697 if (nHDKeySchema != HD_SCHEMA_BIP44)
698 return DeriveHDKey(nIndex, keyRet, strErrorRet);
699
700 bitflash::BIP32PrivateNode parent;
701 parent.privateKey = vchHDMaster;
702 parent.chainCode = vchHDChainCode;
703
704 bitflash::BIP32PrivateNode child;
705 if (!bitflash::BIP32DerivePath(parent,
706 HDBIP44Path(nHDCoinType,
707 HD_BIP44_ACCOUNT,
708 HD_BIP44_CHAIN_CHANGE,
709 nIndex),
710 child,
711 strErrorRet))
712 return false;
713
714 if (!keyRet.SetSecret(child.privateKey))
715 {
716 strErrorRet = "derived scalar is not a usable key";
717 return false;
718 }
719 return true;
720}
721
722bool SetHDSeedFromMnemonic(const string& strMnemonic, string& strErrorRet)
723{
724 string strNormalized;
725 if (!bitflash::BIP39ValidateMnemonic(strMnemonic, strNormalized, strErrorRet))
726 return false;
727
728 vector<unsigned char> vchSeed;
729 if (!bitflash::BIP39MnemonicToSeed(strNormalized, "", vchSeed, strErrorRet))
730 return false;
731
732 bitflash::BIP32PrivateNode master;
733 if (!bitflash::BIP32MasterFromSeed(vchSeed, master, strErrorRet))
734 return false;
735
736 CRITICAL_BLOCK(cs_keyPool)
737 {
738 // The pool is cleared before the seed is written, and the order is the
739 // safe one of the two. Old private keys stay in wallet.dat either way;
740 // what is at stake is which half-finished state a failure can leave.
741 //
742 // clear, then write -- a failed write leaves the old seed and an
743 // empty pool. TopUpKeyPool refills it, and nothing was promised to
744 // anybody.
745 //
746 // write, then clear -- a failed clear leaves a seed installed and the
747 // old random pool intact. The user has just been shown twelve words
748 // and the wallet goes on handing out addresses those words cannot
749 // reproduce. That is the bug this function exists to prevent.
750 //
751 // An earlier comment here said the seed was written first so a failure
752 // left the wallet untouched. That was true of the seed alone and stops
753 // being true once the pool has to move with it.
754 if (!ClearKeyPoolRecords(strErrorRet))
755 return false;
756
757 if (!CWalletDB().WriteHDMaster(master.privateKey, master.chainCode) ||
758 !CWalletDB().WriteHDSchema(HD_SCHEMA_BIP44) ||
759 !CWalletDB().WriteHDCoinType(HD_BIP44_COIN_TYPE_BITFLASH_PROVISIONAL) ||
760 !CWalletDB().WriteHDNext(0) ||
761 !CWalletDB().WriteHDReceiveNext(1) ||
762 !CWalletDB().WriteHDChangeNext(0))
763 {
764 strErrorRet = "could not write the seed metadata to wallet.dat";
765 return false;
766 }
767 vchHDMaster = master.privateKey;
768 vchHDChainCode = master.chainCode;
769 nHDKeySchema = HD_SCHEMA_BIP44;
770 nHDReceiveNext = 1;
771 nHDChangeNext = 0;
772 nHDCoinType = HD_BIP44_COIN_TYPE_BITFLASH_PROVISIONAL;
773
774 // Index 0 is spoken for before it is derived, so a failure below cannot
775 // leave the pool free to hand it out as an ordinary key. The cost of
776 // the counter being ahead of the derivation is one unused index; the
777 // cost of the reverse is the default address and a pool key sharing a
778 // derivation path.
779 nHDNext = 0;
780
781 // Remember which address stops being the default, so it can be named
782 // for what it is. Two entries reading "Your Address" -- one covered by
783 // the phrase and one not -- is the wrong thing to find at the moment a
784 // person has just written twelve words down.
785 vector<unsigned char> vchOldDefault = keyUser.GetPubKey();
786
787 CKey key;
788 if (!DeriveHDKey(0, key, strErrorRet))
789 return false;
790 if (!AddKeyIfMissing(key))
791 {
792 strErrorRet = "could not write the default derived key to wallet.dat";
793 return false;
794 }
795 vector<unsigned char> vchPubKey = key.GetPubKey();
796 if (!CWalletDB().WriteDefaultKey(vchPubKey) ||
797 !SetAddressBookName(PubKeyToAddress(vchPubKey), "Your Address"))
798 {
799 strErrorRet = "could not set the default derived receiving key";
800 return false;
801 }
802 if (!vchOldDefault.empty() && vchOldDefault != vchPubKey)
803 SetAddressBookName(PubKeyToAddress(vchOldDefault),
804 "Your Address (created before the recovery phrase)");
805 keyUser = key;
806 }
807 return true;
808}
809
810void TopUpKeyPool()
811{
812 if (IsWalletLocked())
813 {
814 printf("TopUpKeyPool() : wallet is encrypted and locked\n");
815 return;
816 }
817
818 CRITICAL_BLOCK(cs_keyPool)
819 {
820 while ((int)mapKeyPool.size() < KEYPOOL_SIZE)
821 {
822 // Indices only ever go up. Reusing one would mean two pool records
823 // racing for the same slot after an erase.
824 int64 nIndex = 1;
825 if (!mapKeyPool.empty())
826 nIndex = (--mapKeyPool.end())->first + 1;
827
828 CKey key;
829 if (HaveHDSeed())
830 {
831 // Derived, so a recovery phrase can reproduce this exact key.
832 // A derivation that fails is not a reason to stop filling the
833 // pool -- fall back to a random key, which is what a wallet
834 // without a seed uses anyway. It will not come back from the
835 // phrase, and that is better than a node that cannot mine.
836 string strError;
837 vector<unsigned char> vchPubKey;
838 if (DeriveNextHDReceiveKey(vchPubKey, strError))
839 {
840 if (!CWalletDB().WritePool(nIndex, vchPubKey))
841 return;
842 mapKeyPool[nIndex] = vchPubKey;
843 continue;
844 }
845 else
846 {
847 printf("TopUpKeyPool() : receive derivation failed (%s), "
848 "falling back to a random key\n", strError.c_str());
849 key.MakeNewKey();
850 }
851 }
852 else
853 {
854 key.MakeNewKey();
855 }
856 // AddKey writes the private key. Order matters: the key is in
857 // wallet.dat before anything can point at it, so a crash between
858 // the two writes costs an unused key, never a usable one.
859 if (!AddKeyIfMissing(key))
860 return;
861 vector<unsigned char> vchPubKey = key.GetPubKey();
862 if (!CWalletDB().WritePool(nIndex, vchPubKey))
863 return;
864 mapKeyPool[nIndex] = vchPubKey;
865 }
866 }
867}
868
869vector<unsigned char> GetKeyFromPool()
870{
871 if (IsWalletLocked())
872 {
873 printf("GetKeyFromPool() : wallet is encrypted and locked\n");
874 return vector<unsigned char>();
875 }
876
877 CRITICAL_BLOCK(cs_keyPool)
878 {
879 TopUpKeyPool();
880 if (!mapKeyPool.empty())
881 {
882 map<int64, vector<unsigned char> >::iterator mi = mapKeyPool.begin();
883 int64 nIndex = mi->first;
884 vector<unsigned char> vchPubKey = mi->second;
885 mapKeyPool.erase(mi);
886 CWalletDB().ErasePool(nIndex);
887 // Leave the wallet with a full backup window after each draw too,
888 // not only immediately before a draw. If topping up fails, the key
889 // already chosen is still safe to use -- its private half was
890 // written before it entered the pool.
891 TopUpKeyPool();
892 return vchPubKey;
893 }
894 }
895 // Nothing in the pool and nothing could be added -- disk full, wallet
896 // locked open elsewhere. Generating on demand is what this code did for
897 // its whole life, so fall back to it rather than refuse to mine.
898 printf("GetKeyFromPool() : pool empty, generating a key on demand\n");
899 try
900 {
901 return GenerateNewKey();
902 }
903 catch (const std::exception& e)
904 {
905 printf("GetKeyFromPool() : failed to generate a key: %s\n", e.what());
906 return vector<unsigned char>();
907 }
908}
909
910
911
912
913//////////////////////////////////////////////////////////////////////////////
914//
915// mapWallet
916//
917
918bool AddToWallet(const CWalletTx& wtxIn)
919{
920 uint256 hash = wtxIn.GetHash();
921 CRITICAL_BLOCK(cs_mapWallet)
922 {
923 // Inserts only if not already there, returns tx inserted or tx found
924 pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
925 CWalletTx& wtx = (*ret.first).second;
926 bool fInsertedNew = ret.second;
927 if (fInsertedNew)
928 wtx.nTimeReceived = GetAdjustedTime();
929
930 //// debug print
931 if (LogAcceptsCategory("net")) printf("AddToWallet %s %s\n", wtxIn.GetHash().ToString().substr(0,6).c_str(), fInsertedNew ? "new" : "update");
932
933 if (!fInsertedNew)
934 {
935 // Merge
936 bool fUpdated = false;
937 if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
938 {
939 wtx.hashBlock = wtxIn.hashBlock;
940 fUpdated = true;
941 }
942 if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
943 {
944 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
945 wtx.nIndex = wtxIn.nIndex;
946 fUpdated = true;
947 }
948 if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
949 {
950 wtx.fFromMe = wtxIn.fFromMe;
951 fUpdated = true;
952 }
953 if (wtxIn.fSpent && wtxIn.fSpent != wtx.fSpent)
954 {
955 wtx.fSpent = wtxIn.fSpent;
956 fUpdated = true;
957 }
958 if (!fUpdated)
959 return true;
960 }
961
962 // Write to disk
963 if (!wtx.WriteToDisk())
964 return false;
965
966 // Notify UI
967 vWalletUpdated.push_back(make_pair(hash, fInsertedNew));
968 }
969
970 // Refresh UI
971 MainFrameRepaint();
972 return true;
973}
974
975bool AddToWalletIfMine(const CTransaction& tx, const CBlock* pblock)
976{
977 if (tx.IsMine() || mapWallet.count(tx.GetHash()))
978 {
979 CWalletTx wtx(tx);
980 // Get merkle branch if transaction was found in a block
981 if (pblock)
982 wtx.SetMerkleBranch(pblock);
983 return AddToWallet(wtx);
984 }
985 return true;
986}
987
988bool CanScanWalletTransactions(string& strErrorRet)
989{
990 strErrorRet.clear();
991
992 if (pindexGenesisBlock == NULL || pindexBest == NULL || hashBestChain == 0 || nBestHeight < 0)
993 {
994 strErrorRet = "The block index is not loaded, so the wallet scan cannot "
995 "prove whether imported or restored keys own coins.";
996 return false;
997 }
998
999 if (nBestHeight == 0)
1000 {
1001 strErrorRet = "The local chain is only at height 0. A wallet scan would "
1002 "inspect only the genesis block and could incorrectly "
1003 "report zero transactions. Start the node and let it sync "
1004 "before scanning. If this happened after copying a data "
1005 "directory, keep wallet.dat safe and rebuild or re-download "
1006 "the block data instead of trusting the copied database/ "
1007 "environment.";
1008 return false;
1009 }
1010
1011 return true;
1012}
1013
1014int ScanForWalletTransactions(CBlockIndex* pindexStart)
1015{
1016 // Walk the chain looking for transactions that belong to keys this wallet
1017 // holds now, whatever it held when those blocks arrived.
1018 //
1019 // Nothing in this tree could do that. A key added after the fact -- from
1020 // /importwallet, or from a backup restored onto a node that had since
1021 // moved on -- was simply invisible: the coins were on the chain, the
1022 // private key was in wallet.dat, and the balance did not show them,
1023 // because a transaction only ever entered the wallet at the moment its
1024 // block arrived over the network.
1025 //
1026 // Bitcoin grew the same function for the same reason. It is also what any
1027 // recovery-phrase feature has to stand on: deriving the keys is the easy
1028 // half, and without this the other half does not exist.
1029 int nFound = 0;
1030 int nScanned = 0;
1031 CBlockIndex* pindex = pindexStart;
1032 CRITICAL_BLOCK(cs_main)
1033 {
1034 while (pindex)
1035 {
1036 CBlock block;
1037 if (block.ReadFromDisk(pindex, true))
1038 {
1039 foreach(CTransaction& tx, block.vtx)
1040 {
1041 // Ask before handing it over: AddToWalletIfMine returns
1042 // true for a transaction that is none of our business, so
1043 // its return value cannot be counted.
1044 if (tx.IsMine())
1045 {
1046 if (AddToWalletIfMine(tx, &block))
1047 nFound++;
1048 }
1049 }
1050 }
1051 nScanned++;
1052 if ((nScanned % 500) == 0)
1053 printf("ScanForWalletTransactions() : %d blocks scanned, %d transaction(s) found\n",
1054 nScanned, nFound);
1055 pindex = pindex->pnext;
1056 }
1057 }
1058 printf("ScanForWalletTransactions() : %d block(s) scanned, %d transaction(s) added or updated\n",
1059 nScanned, nFound);
1060 return nFound;
1061}
1062
1063bool EraseFromWallet(uint256 hash)
1064{
1065 CRITICAL_BLOCK(cs_mapWallet)
1066 {
1067 if (mapWallet.erase(hash))
1068 CWalletDB().EraseTx(hash);
1069 }
1070 return true;
1071}
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081//////////////////////////////////////////////////////////////////////////////
1082//
1083// mapOrphanTransactions
1084//
1085
1086void AddOrphanTx(const CDataStream& vMsg)
1087{
1088 CTransaction tx;
1089 CDataStream(vMsg) >> tx;
1090 uint256 hash = tx.GetHash();
1091 if (mapOrphanTransactions.count(hash))
1092 return;
1093
1094 // Do not allow an orphan to have an unbounded number of inputs.
1095 // 10,000 inputs is enough for massive legitimate sweeps, but bounds the total
1096 // memory in mapOrphanTransactionsByPrev to ~10,000 * MAX_ORPHAN_TRANSACTIONS.
1097 if (tx.vin.size() > 10000)
1098 {
1099 if (LogAcceptsCategory("net")) printf("AddOrphanTx() : orphan with %d inputs rejected\n", (int)tx.vin.size());
1100 return;
1101 }
1102
1103 CDataStream* pvMsg = mapOrphanTransactions[hash] = new CDataStream(vMsg);
1104 foreach(const CTxIn& txin, tx.vin)
1105 mapOrphanTransactionsByPrev.insert(make_pair(txin.prevout.hash, pvMsg));
1106 LimitOrphanTx(MAX_ORPHAN_TRANSACTIONS);
1107}
1108
1109// Orphans cost nothing to create -- a transaction naming a parent that does
1110// not exist is never validated, just held -- so without a ceiling any peer can
1111// grow this map until the node runs out of memory. Evict at random rather than
1112// in map order, so an attacker cannot keep its own orphans resident by
1113// choosing hashes that sort low.
1114// Drop orphan blocks at random until we are back under the ceiling.
1115//
1116// Random rather than oldest-first, matching LimitOrphanTx below: there is no
1117// arrival order recorded, and an attacker who knew the eviction rule could aim
1118// at it. Dropping one costs nothing that matters -- if its parent ever shows
1119// up, the block is requested again like any other.
1120//
1121// Both maps have to be kept in step, and the CBlock itself has to be deleted:
1122// mapOrphanBlocks owns it.
1123void LimitOrphanBlocks(unsigned int nMaxOrphans)
1124{
1125 while (mapOrphanBlocks.size() > nMaxOrphans)
1126 {
1127 uint256 randomhash;
1128 for (int i = 0; i < 4; i++)
1129 ((uint64*)&randomhash)[i] = GetRand(_UI64_MAX);
1130 map<uint256, CBlock*>::iterator it = mapOrphanBlocks.lower_bound(randomhash);
1131 if (it == mapOrphanBlocks.end())
1132 it = mapOrphanBlocks.begin();
1133
1134 CBlock* pblock = it->second;
1135 uint256 hashPrev = pblock->hashPrevBlock;
1136
1137 for (multimap<uint256, CBlock*>::iterator mi = mapOrphanBlocksByPrev.lower_bound(hashPrev);
1138 mi != mapOrphanBlocksByPrev.upper_bound(hashPrev);)
1139 {
1140 if (mi->second == pblock)
1141 mapOrphanBlocksByPrev.erase(mi++);
1142 else
1143 ++mi;
1144 }
1145
1146 mapOrphanBlocks.erase(it);
1147 delete pblock;
1148 }
1149}
1150
1151void LimitOrphanTx(unsigned int nMaxOrphans)
1152{
1153 while (mapOrphanTransactions.size() > nMaxOrphans)
1154 {
1155 uint256 randomhash;
1156 for (int i = 0; i < 4; i++)
1157 ((uint64*)&randomhash)[i] = GetRand(_UI64_MAX);
1158 map<uint256, CDataStream*>::iterator it = mapOrphanTransactions.lower_bound(randomhash);
1159 if (it == mapOrphanTransactions.end())
1160 it = mapOrphanTransactions.begin();
1161 EraseOrphanTx(it->first);
1162 }
1163}
1164
1165void EraseOrphanTx(uint256 hash)
1166{
1167 if (!mapOrphanTransactions.count(hash))
1168 return;
1169 const CDataStream* pvMsg = mapOrphanTransactions[hash];
1170 CTransaction tx;
1171 CDataStream(*pvMsg) >> tx;
1172 foreach(const CTxIn& txin, tx.vin)
1173 {
1174 for (multimap<uint256, CDataStream*>::iterator mi = mapOrphanTransactionsByPrev.lower_bound(txin.prevout.hash);
1175 mi != mapOrphanTransactionsByPrev.upper_bound(txin.prevout.hash);)
1176 {
1177 if ((*mi).second == pvMsg)
1178 mapOrphanTransactionsByPrev.erase(mi++);
1179 else
1180 mi++;
1181 }
1182 }
1183 delete pvMsg;
1184 mapOrphanTransactions.erase(hash);
1185}
1186
1187
1188
1189
1190
1191
1192
1193
1194//////////////////////////////////////////////////////////////////////////////
1195//
1196// CTransaction
1197//
1198
1199bool CTxIn::IsMine() const
1200{
1201 CRITICAL_BLOCK(cs_mapWallet)
1202 {
1203 map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
1204 if (mi != mapWallet.end())
1205 {
1206 const CWalletTx& prev = (*mi).second;
1207 if (prevout.n < prev.vout.size())
1208 if (prev.vout[prevout.n].IsMine())
1209 return true;
1210 }
1211 }
1212 return false;
1213}
1214
1215int64 CTxIn::GetDebit() const
1216{
1217 CRITICAL_BLOCK(cs_mapWallet)
1218 {
1219 map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
1220 if (mi != mapWallet.end())
1221 {
1222 const CWalletTx& prev = (*mi).second;
1223 if (prevout.n < prev.vout.size())
1224 if (prev.vout[prevout.n].IsMine())
1225 return prev.vout[prevout.n].nValue;
1226 }
1227 }
1228 return 0;
1229}
1230
1231int64 CWalletTx::GetTxTime() const
1232{
1233 if (!fTimeReceivedIsTxTime && hashBlock != 0)
1234 {
1235 // If we did not receive the transaction directly, we rely on the block's
1236 // time to figure out when it happened. We use the median over a range
1237 // of blocks to try to filter out inaccurate block times.
1238 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
1239 if (mi != mapBlockIndex.end())
1240 {
1241 CBlockIndex* pindex = (*mi).second;
1242 if (pindex)
1243 return pindex->GetMedianTime();
1244 }
1245 }
1246 return nTimeReceived;
1247}
1248
1249
1250
1251
1252
1253
1254int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
1255{
1256 if (fClient)
1257 {
1258 if (hashBlock == 0)
1259 return 0;
1260 }
1261 else
1262 {
1263 CBlock blockTmp;
1264 if (pblock == NULL)
1265 {
1266 // Load the block this tx is in
1267 CTxIndex txindex;
1268 if (!CTxDB("r").ReadTxIndex(GetHash(), txindex))
1269 return 0;
1270 if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, true))
1271 return 0;
1272 pblock = &blockTmp;
1273 }
1274
1275 // Update the tx's hashBlock
1276 hashBlock = pblock->GetHash();
1277
1278 // Locate the transaction
1279 for (nIndex = 0; nIndex < pblock->vtx.size(); nIndex++)
1280 if (pblock->vtx[nIndex] == *(CTransaction*)this)
1281 break;
1282 if (nIndex == pblock->vtx.size())
1283 {
1284 vMerkleBranch.clear();
1285 nIndex = -1;
1286 if (LogAcceptsCategory("net")) printf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
1287 return 0;
1288 }
1289
1290 // Fill in merkle branch
1291 vMerkleBranch = pblock->GetMerkleBranch(nIndex);
1292 }
1293
1294 // Is the tx in a block that's in the main chain
1295 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
1296 if (mi == mapBlockIndex.end())
1297 return 0;
1298 CBlockIndex* pindex = (*mi).second;
1299 if (!pindex || !pindex->IsInMainChain())
1300 return 0;
1301
1302 return pindexBest->nHeight - pindex->nHeight + 1;
1303}
1304
1305
1306
1307void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
1308{
1309 vtxPrev.clear();
1310
1311 const int COPY_DEPTH = 3;
1312 if (SetMerkleBranch() < COPY_DEPTH)
1313 {
1314 vector<uint256> vWorkQueue;
1315 foreach(const CTxIn& txin, vin)
1316 vWorkQueue.push_back(txin.prevout.hash);
1317
1318 // This critsect is OK because txdb is already open
1319 CRITICAL_BLOCK(cs_mapWallet)
1320 {
1321 map<uint256, const CMerkleTx*> mapWalletPrev;
1322 set<uint256> setAlreadyDone;
1323 for (int i = 0; i < vWorkQueue.size(); i++)
1324 {
1325 uint256 hash = vWorkQueue[i];
1326 if (setAlreadyDone.count(hash))
1327 continue;
1328 setAlreadyDone.insert(hash);
1329
1330 CMerkleTx tx;
1331 if (mapWallet.count(hash))
1332 {
1333 tx = mapWallet[hash];
1334 foreach(const CMerkleTx& txWalletPrev, mapWallet[hash].vtxPrev)
1335 mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
1336 }
1337 else if (mapWalletPrev.count(hash))
1338 {
1339 tx = *mapWalletPrev[hash];
1340 }
1341 else if (!fClient && txdb.ReadDiskTx(hash, tx))
1342 {
1343 ;
1344 }
1345 else
1346 {
1347 if (LogAcceptsCategory("net")) printf("ERROR: AddSupportingTransactions() : unsupported transaction\n");
1348 continue;
1349 }
1350
1351 int nDepth = tx.SetMerkleBranch();
1352 vtxPrev.push_back(tx);
1353
1354 if (nDepth < COPY_DEPTH)
1355 foreach(const CTxIn& txin, tx.vin)
1356 vWorkQueue.push_back(txin.prevout.hash);
1357 }
1358 }
1359 }
1360
1361 reverse(vtxPrev.begin(), vtxPrev.end());
1362}
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs)
1375{
1376 if (pfMissingInputs)
1377 *pfMissingInputs = false;
1378
1379 // Coinbase is only valid in a block, not as a loose transaction
1380 if (IsCoinBase())
1381 return error("AcceptTransaction() : coinbase as individual tx");
1382
1383 if (!CheckTransaction())
1384 return error("AcceptTransaction() : CheckTransaction failed");
1385
1386 // Do we already have it?
1387 uint256 hash = GetHash();
1388 CRITICAL_BLOCK(cs_mapTransactions)
1389 if (mapTransactions.count(hash))
1390 return false;
1391 if (fCheckInputs)
1392 if (txdb.ContainsTx(hash))
1393 return false;
1394
1395 // Check for conflicts with in-memory transactions
1396 CTransaction* ptxOld = NULL;
1397 for (int i = 0; i < vin.size(); i++)
1398 {
1399 COutPoint outpoint = vin[i].prevout;
1400 if (mapNextTx.count(outpoint))
1401 {
1402 // Allow replacing with a newer version of the same transaction
1403 if (i != 0)
1404 return false;
1405 ptxOld = mapNextTx[outpoint].ptx;
1406 if (!IsNewerThan(*ptxOld))
1407 return false;
1408 for (int i = 0; i < vin.size(); i++)
1409 {
1410 COutPoint outpoint = vin[i].prevout;
1411 if (!mapNextTx.count(outpoint) || mapNextTx[outpoint].ptx != ptxOld)
1412 return false;
1413 }
1414 break;
1415 }
1416 }
1417
1418 // Check against previous transactions
1419 map<uint256, CTxIndex> mapUnused;
1420 int64 nFees = 0;
1421 if (fCheckInputs && !ConnectInputs(txdb, mapUnused, CDiskTxPos(1,1,1), 0, nFees, false, false))
1422 {
1423 if (pfMissingInputs)
1424 *pfMissingInputs = true;
1425 return error("AcceptTransaction() : ConnectInputs failed %s", hash.ToString().substr(0,6).c_str());
1426 }
1427
1428 // Store transaction in memory
1429 CRITICAL_BLOCK(cs_mapTransactions)
1430 {
1431 if (ptxOld)
1432 {
1433 if (LogAcceptsCategory("net")) printf("mapTransaction.erase(%s) replacing with new version\n", ptxOld->GetHash().ToString().c_str());
1434 mapTransactions.erase(ptxOld->GetHash());
1435 }
1436 AddToMemoryPool();
1437 }
1438
1439 ///// are we sure this is ok when loading transactions or restoring block txes
1440 // If updated, erase old tx from wallet
1441 if (ptxOld)
1442 EraseFromWallet(ptxOld->GetHash());
1443
1444 if (LogAcceptsCategory("net")) printf("AcceptTransaction(): accepted %s\n", hash.ToString().substr(0,6).c_str());
1445 return true;
1446}
1447
1448
1449bool CTransaction::AddToMemoryPool()
1450{
1451 // Add to memory pool without checking anything. Don't call this directly,
1452 // call AcceptTransaction to properly check the transaction first.
1453 CRITICAL_BLOCK(cs_mapTransactions)
1454 {
1455 uint256 hash = GetHash();
1456 mapTransactions[hash] = *this;
1457 for (int i = 0; i < vin.size(); i++)
1458 mapNextTx[vin[i].prevout] = CInPoint(&mapTransactions[hash], i);
1459 nTransactionsUpdated++;
1460 }
1461 return true;
1462}
1463
1464
1465bool CTransaction::RemoveFromMemoryPool()
1466{
1467 // Remove transaction from memory pool
1468 CRITICAL_BLOCK(cs_mapTransactions)
1469 {
1470 foreach(const CTxIn& txin, vin)
1471 mapNextTx.erase(txin.prevout);
1472 mapTransactions.erase(GetHash());
1473 nTransactionsUpdated++;
1474 }
1475 return true;
1476}
1477
1478
1479
1480
1481
1482
1483int CMerkleTx::GetDepthInMainChain() const
1484{
1485 if (hashBlock == 0 || nIndex == -1)
1486 return 0;
1487
1488 // Find the block it claims to be in
1489 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
1490 if (mi == mapBlockIndex.end())
1491 return 0;
1492 CBlockIndex* pindex = (*mi).second;
1493 if (!pindex || !pindex->IsInMainChain())
1494 return 0;
1495
1496 // Make sure the merkle branch connects to this block
1497 if (!fMerkleVerified)
1498 {
1499 if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
1500 return 0;
1501 fMerkleVerified = true;
1502 }
1503
1504 return pindexBest->nHeight - pindex->nHeight + 1;
1505}
1506
1507
1508int CMerkleTx::GetBlocksToMaturity() const
1509{
1510 if (!IsCoinBase())
1511 return 0;
1512 return max(0, (COINBASE_MATURITY+20) - GetDepthInMainChain());
1513}
1514
1515
1516bool CMerkleTx::AcceptTransaction(CTxDB& txdb, bool fCheckInputs)
1517{
1518 if (fClient)
1519 {
1520 if (!IsInMainChain() && !ClientConnectInputs())
1521 return false;
1522 return CTransaction::AcceptTransaction(txdb, false);
1523 }
1524 else
1525 {
1526 return CTransaction::AcceptTransaction(txdb, fCheckInputs);
1527 }
1528}
1529
1530
1531
1532bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
1533{
1534 CRITICAL_BLOCK(cs_mapTransactions)
1535 {
1536 foreach(CMerkleTx& tx, vtxPrev)
1537 {
1538 if (!tx.IsCoinBase())
1539 {
1540 uint256 hash = tx.GetHash();
1541 if (!mapTransactions.count(hash) && !txdb.ContainsTx(hash))
1542 tx.AcceptTransaction(txdb, fCheckInputs);
1543 }
1544 }
1545 if (!IsCoinBase())
1546 return AcceptTransaction(txdb, fCheckInputs);
1547 }
1548 return true;
1549}
1550
1551int RescanSpentFlags()
1552{
1553 // Believe the chain, not the wallet, about what has already been spent.
1554 //
1555 // fSpent lives in wallet.dat and is written when this node spends
1556 // something. A wallet.dat that was restored from backup, or copied and
1557 // used on another machine, carries whatever that flag was at the moment
1558 // the copy was taken -- so it can say "unspent" about coins the chain
1559 // shows as gone. The balance then reads high, and the error only surfaces
1560 // when a send is attempted against coins that no longer exist.
1561 //
1562 // Issue #47 is about this shape of problem and #40 reports living through
1563 // it. Bitcoin fixed the same thing in 53d508072.
1564 //
1565 // One direction only. Marking spent when the chain says spent is safe;
1566 // clearing the flag because the chain has not caught up yet would offer
1567 // up coins that are already on their way out.
1568 CTxDB txdb("r");
1569 int nCorrected = 0;
1570 int nExamined = 0;
1571 int nAlreadySpent = 0, nNotIndexed = 0;
1572 CRITICAL_BLOCK(cs_mapWallet)
1573 {
1574 foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
1575 {
1576 CWalletTx& wtx = item.second;
1577 nExamined++;
1578 if (wtx.fSpent)
1579 { nAlreadySpent++; continue; }
1580
1581 CTxIndex txindex;
1582 if (!txdb.ReadTxIndex(wtx.GetHash(), txindex))
1583 { nNotIndexed++; continue; }
1584
1585 // fSpent is one flag for the whole transaction, not one per
1586 // output -- CommitTransactionSpent already marks the entire
1587 // previous transaction when it spends any part of it, so matching
1588 // that here keeps the two consistent.
1589 bool fSeenSpent = false;
1590 for (int i = 0; i < (int)txindex.vSpent.size() && i < (int)wtx.vout.size(); i++)
1591 if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine())
1592 fSeenSpent = true;
1593
1594 if (fSeenSpent)
1595 {
1596 wtx.fSpent = true;
1597 wtx.WriteToDisk();
1598 nCorrected++;
1599 printf("RescanSpentFlags() : %s was spent on chain but the wallet did not know\n",
1600 wtx.GetHash().ToString().substr(0,10).c_str());
1601 }
1602 }
1603 }
1604 // Always say it ran. A check that reports only when it finds something is
1605 // indistinguishable from a check that never executed, and this codebase has
1606 // paid for that confusion more than once.
1607 printf("RescanSpentFlags() : examined %d, already-spent %d, not-indexed %d, corrected %d\n",
1608 nExamined, nAlreadySpent, nNotIndexed, nCorrected);
1609 if (nCorrected)
1610 printf("RescanSpentFlags() : this wallet was behind the chain about what it had already spent, "
1611 "which is what a restored backup looks like\n");
1612 return nCorrected;
1613}
1614
1615
1616void ReacceptWalletTransactions()
1617{
1618 // Reaccept any txes of ours that aren't already in a block
1619 CTxDB txdb("r");
1620 CRITICAL_BLOCK(cs_mapWallet)
1621 {
1622 foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
1623 {
1624 CWalletTx& wtx = item.second;
1625 if (!wtx.IsCoinBase() && !txdb.ContainsTx(wtx.GetHash()))
1626 wtx.AcceptWalletTransaction(txdb, false);
1627 }
1628 }
1629}
1630
1631
1632void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
1633{
1634 foreach(const CMerkleTx& tx, vtxPrev)
1635 {
1636 if (!tx.IsCoinBase())
1637 {
1638 uint256 hash = tx.GetHash();
1639 if (!txdb.ContainsTx(hash))
1640 RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
1641 }
1642 }
1643 if (!IsCoinBase())
1644 {
1645 uint256 hash = GetHash();
1646 if (!txdb.ContainsTx(hash))
1647 {
1648 if (LogAcceptsCategory("net")) printf("Relaying wtx %s\n", hash.ToString().substr(0,6).c_str());
1649 RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
1650 }
1651 }
1652}
1653
1654void RelayWalletTransactions()
1655{
1656 static int64 nLastTime;
1657 if (GetTime() - nLastTime < 10 * 60)
1658 return;
1659 nLastTime = GetTime();
1660
1661 // Rebroadcast any of our txes that aren't in a block yet
1662 if (LogAcceptsCategory("net")) printf("RelayWalletTransactions()\n");
1663 CTxDB txdb("r");
1664 CRITICAL_BLOCK(cs_mapWallet)
1665 {
1666 // Sort them in chronological order
1667 multimap<unsigned int, CWalletTx*> mapSorted;
1668 foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
1669 {
1670 CWalletTx& wtx = item.second;
1671 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
1672 }
1673 foreach(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
1674 {
1675 CWalletTx& wtx = *item.second;
1676 wtx.RelayWalletTransaction(txdb);
1677 }
1678 }
1679}
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690//////////////////////////////////////////////////////////////////////////////
1691//
1692// CBlock and CBlockIndex
1693//
1694
1695bool CBlock::ReadFromDisk(const CBlockIndex* pblockindex, bool fReadTransactions)
1696{
1697 return ReadFromDisk(pblockindex->nFile, pblockindex->nBlockPos, fReadTransactions);
1698}
1699
1700uint256 GetOrphanRoot(const CBlock* pblock)
1701{
1702 // Work back to the first block in the orphan chain
1703 while (mapOrphanBlocks.count(pblock->hashPrevBlock))
1704 pblock = mapOrphanBlocks[pblock->hashPrevBlock];
1705 return pblock->GetHash();
1706}
1707
1708int64 CBlock::GetBlockValue(int nHeight, int64 nFees) const
1709{
1710 int64 nSubsidy = 50 * COIN;
1711
1712 // Halve on the height of this block, never on nBestHeight. The subsidy a
1713 // block is allowed to pay is a property of that block; deriving it from
1714 // the validating node's own tip makes the answer depend on how far that
1715 // node happens to have synced, so two nodes at different heights would
1716 // disagree about the same block across a halving boundary.
1717 nSubsidy >>= (nHeight / 210000);
1718
1719 return nSubsidy + nFees;
1720}
1721
1722unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast)
1723{
1724 // Bitflash: 2-minute target block time with a fast retarget (every 30
1725 // blocks, ~1h) so difficulty tracks the small, volatile CPU hashrate and
1726 // brief disconnections no longer spawn divergent forks.
1727 const unsigned int nTargetSpacing = 2 * 60; // 2 minutes
1728 const unsigned int nInterval = 30; // retarget window
1729 const unsigned int nTargetTimespan = nInterval * nTargetSpacing; // 3600s
1730
1731 // Genesis block
1732 if (pindexLast == NULL)
1733 return bnProofOfWorkLimit.GetCompact();
1734
1735 // Only change once per interval
1736 if ((pindexLast->nHeight+1) % nInterval != 0)
1737 return pindexLast->nBits;
1738
1739 // Go back by what we want to be 14 days worth of blocks
1740 const CBlockIndex* pindexFirst = pindexLast;
1741 for (int i = 0; pindexFirst && i < nInterval-1; i++)
1742 pindexFirst = pindexFirst->pprev;
1743 assert(pindexFirst);
1744
1745 // Limit adjustment step
1746 unsigned int nActualTimespan = pindexLast->nTime - pindexFirst->nTime;
1747 if (LogAcceptsCategory("net")) printf(" nActualTimespan = %d before bounds\n", nActualTimespan);
1748 if (nActualTimespan < nTargetTimespan/4)
1749 nActualTimespan = nTargetTimespan/4;
1750 if (nActualTimespan > nTargetTimespan*4)
1751 nActualTimespan = nTargetTimespan*4;
1752
1753 // Retarget
1754 CBigNum bnNew;
1755 bnNew.SetCompact(pindexLast->nBits);
1756 bnNew *= nActualTimespan;
1757 bnNew /= nTargetTimespan;
1758
1759 if (bnNew > bnProofOfWorkLimit)
1760 bnNew = bnProofOfWorkLimit;
1761
1762 /// debug print
1763 if (LogAcceptsCategory("net")) { printf("\n\n\nGetNextWorkRequired RETARGET *****\n"); printf("nTargetTimespan = %d nActualTimespan = %d\n", nTargetTimespan, nActualTimespan); printf("Before: %08x %s\n", pindexLast->nBits, CBigNum().SetCompact(pindexLast->nBits).getuint256().ToString().c_str()); printf("After: %08x %s\n", bnNew.GetCompact(), bnNew.getuint256().ToString().c_str()); }
1764
1765 return bnNew.GetCompact();
1766}
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776bool CTransaction::DisconnectInputs(CTxDB& txdb)
1777{
1778 // Relinquish previous transactions' spent pointers
1779 if (!IsCoinBase())
1780 {
1781 foreach(const CTxIn& txin, vin)
1782 {
1783 COutPoint prevout = txin.prevout;
1784
1785 // Get prev txindex from disk
1786 CTxIndex txindex;
1787 if (!txdb.ReadTxIndex(prevout.hash, txindex))
1788 return error("DisconnectInputs() : ReadTxIndex failed");
1789
1790 if (prevout.n >= txindex.vSpent.size())
1791 return error("DisconnectInputs() : prevout.n out of range");
1792
1793 // Mark outpoint as not spent
1794 txindex.vSpent[prevout.n].SetNull();
1795
1796 // Write back
1797 txdb.UpdateTxIndex(prevout.hash, txindex);
1798 }
1799 }
1800
1801 // Remove transaction from index
1802 if (!txdb.EraseTxIndex(*this))
1803 return error("DisconnectInputs() : EraseTxPos failed");
1804
1805 return true;
1806}
1807
1808
1809bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx, int nHeight, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee)
1810{
1811 // Take over previous transactions' spent pointers
1812 if (!IsCoinBase())
1813 {
1814 int64 nValueIn = 0;
1815 for (int i = 0; i < vin.size(); i++)
1816 {
1817 COutPoint prevout = vin[i].prevout;
1818
1819 // Read txindex
1820 CTxIndex txindex;
1821 bool fFound = true;
1822 if (fMiner && mapTestPool.count(prevout.hash))
1823 {
1824 // Get txindex from current proposed changes
1825 txindex = mapTestPool[prevout.hash];
1826 }
1827 else
1828 {
1829 // Read txindex from txdb
1830 fFound = txdb.ReadTxIndex(prevout.hash, txindex);
1831 }
1832 if (!fFound && (fBlock || fMiner))
1833 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());
1834
1835 // Read txPrev
1836 CTransaction txPrev;
1837 if (!fFound || txindex.pos == CDiskTxPos(1,1,1))
1838 {
1839 // Get prev tx from single transactions in memory
1840 CRITICAL_BLOCK(cs_mapTransactions)
1841 {
1842 if (!mapTransactions.count(prevout.hash))
1843 return error("ConnectInputs() : %s mapTransactions prev not found %s", GetHash().ToString().substr(0,6).c_str(), prevout.hash.ToString().substr(0,6).c_str());
1844 txPrev = mapTransactions[prevout.hash];
1845 }
1846 if (!fFound)
1847 txindex.vSpent.resize(txPrev.vout.size());
1848 }
1849 else
1850 {
1851 // Get prev tx from disk
1852 if (!txPrev.ReadFromDisk(txindex.pos))
1853 return error("ConnectInputs() : %s ReadFromDisk prev tx %s failed", GetHash().ToString().substr(0,6).c_str(), prevout.hash.ToString().substr(0,6).c_str());
1854 }
1855
1856 if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size())
1857 return error("ConnectInputs() : %s prevout.n out of range %d %d %d", GetHash().ToString().substr(0,6).c_str(), prevout.n, (int)txPrev.vout.size(), (int)txindex.vSpent.size());
1858
1859 // If prev is coinbase, check that it's matured
1860 if (txPrev.IsCoinBase())
1861 for (CBlockIndex* pindex = pindexBest; pindex && nBestHeight - pindex->nHeight < COINBASE_MATURITY-1; pindex = pindex->pprev)
1862 if (pindex->nBlockPos == txindex.pos.nBlockPos && pindex->nFile == txindex.pos.nFile)
1863 return error("ConnectInputs() : tried to spend coinbase at depth %d", nBestHeight - pindex->nHeight);
1864
1865 // Verify signature
1866 if (!VerifySignature(txPrev, *this, i))
1867 return error("ConnectInputs() : %s VerifySignature failed", GetHash().ToString().substr(0,6).c_str());
1868
1869 // Check for conflicts
1870 if (!txindex.vSpent[prevout.n].IsNull())
1871 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());
1872
1873 // Mark outpoints as spent
1874 txindex.vSpent[prevout.n] = posThisTx;
1875
1876 // Write back
1877 if (fBlock)
1878 txdb.UpdateTxIndex(prevout.hash, txindex);
1879 else if (fMiner)
1880 mapTestPool[prevout.hash] = txindex;
1881
1882 nValueIn += txPrev.vout[prevout.n].nValue;
1883 if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
1884 return error("ConnectInputs() : txin values out of range");
1885 }
1886
1887 // Tally transaction fees
1888 int64 nTxFee = nValueIn - GetValueOut();
1889 if (nTxFee < 0)
1890 return error("ConnectInputs() : %s nTxFee < 0", GetHash().ToString().substr(0,6).c_str());
1891 if (nTxFee < nMinFee)
1892 return false;
1893 nFees += nTxFee;
1894 if (!MoneyRange(nFees))
1895 return error("ConnectInputs() : nFees out of range");
1896 }
1897
1898 if (fBlock)
1899 {
1900 // Add transaction to disk index
1901 if (!txdb.AddTxIndex(*this, posThisTx, nHeight))
1902 return error("ConnectInputs() : AddTxPos failed");
1903 }
1904 else if (fMiner)
1905 {
1906 // Add transaction to test pool
1907 mapTestPool[GetHash()] = CTxIndex(CDiskTxPos(1,1,1), vout.size());
1908 }
1909
1910 return true;
1911}
1912
1913
1914bool CTransaction::ClientConnectInputs()
1915{
1916 if (IsCoinBase())
1917 return false;
1918
1919 // Take over previous transactions' spent pointers
1920 CRITICAL_BLOCK(cs_mapTransactions)
1921 {
1922 int64 nValueIn = 0;
1923 for (int i = 0; i < vin.size(); i++)
1924 {
1925 // Get prev tx from single transactions in memory
1926 COutPoint prevout = vin[i].prevout;
1927 if (!mapTransactions.count(prevout.hash))
1928 return false;
1929 CTransaction& txPrev = mapTransactions[prevout.hash];
1930
1931 if (prevout.n >= txPrev.vout.size())
1932 return false;
1933
1934 // Verify signature
1935 if (!VerifySignature(txPrev, *this, i))
1936 return error("ConnectInputs() : VerifySignature failed");
1937
1938 ///// this is redundant with the mapNextTx stuff, not sure which I want to get rid of
1939 ///// this has to go away now that posNext is gone
1940 // // Check for conflicts
1941 // if (!txPrev.vout[prevout.n].posNext.IsNull())
1942 // return error("ConnectInputs() : prev tx already used");
1943 //
1944 // // Flag outpoints as used
1945 // txPrev.vout[prevout.n].posNext = posThisTx;
1946
1947 nValueIn += txPrev.vout[prevout.n].nValue;
1948 }
1949 if (GetValueOut() > nValueIn)
1950 return false;
1951 }
1952
1953 return true;
1954}
1955
1956
1957
1958
1959bool CBlock::DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex)
1960{
1961 // Disconnect in reverse order
1962 for (int i = vtx.size()-1; i >= 0; i--)
1963 if (!vtx[i].DisconnectInputs(txdb))
1964 return false;
1965
1966 // Update block index on disk without changing it in memory.
1967 // The memory index structure will be changed after the db commits.
1968 if (pindex->pprev)
1969 {
1970 CDiskBlockIndex blockindexPrev(pindex->pprev);
1971 blockindexPrev.hashNext = 0;
1972 txdb.WriteBlockIndex(blockindexPrev);
1973 }
1974
1975 return true;
1976}
1977
1978bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
1979{
1980 //// issue here: it doesn't know the version
1981 unsigned int nTxPos = pindex->nBlockPos + ::GetSerializeSize(CBlock(), SER_DISK) - 1 + GetSizeOfCompactSize(vtx.size());
1982
1983 map<uint256, CTxIndex> mapUnused;
1984 int64 nFees = 0;
1985 foreach(CTransaction& tx, vtx)
1986 {
1987 CDiskTxPos posThisTx(pindex->nFile, pindex->nBlockPos, nTxPos);
1988 nTxPos += ::GetSerializeSize(tx, SER_DISK);
1989
1990 if (!tx.ConnectInputs(txdb, mapUnused, posThisTx, pindex->nHeight, nFees, true, false))
1991 return false;
1992 }
1993
1994 if (vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees))
1995 return false;
1996
1997 // Update block index on disk without changing it in memory.
1998 // The memory index structure will be changed after the db commits.
1999 if (pindex->pprev)
2000 {
2001 CDiskBlockIndex blockindexPrev(pindex->pprev);
2002 blockindexPrev.hashNext = pindex->GetBlockHash();
2003 txdb.WriteBlockIndex(blockindexPrev);
2004 }
2005
2006 // Watch for transactions paying to me
2007 foreach(CTransaction& tx, vtx)
2008 AddToWalletIfMine(tx, this);
2009
2010 return true;
2011}
2012
2013
2014
2015bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
2016{
2017 LogPrint("net", "*** REORGANIZE ***\n");
2018
2019 // Find the fork
2020 CBlockIndex* pfork = pindexBest;
2021 CBlockIndex* plonger = pindexNew;
2022 while (pfork != plonger)
2023 {
2024 if (!(pfork = pfork->pprev))
2025 return error("Reorganize() : pfork->pprev is null");
2026 while (plonger->nHeight > pfork->nHeight)
2027 if (!(plonger = plonger->pprev))
2028 return error("Reorganize() : plonger->pprev is null");
2029 }
2030
2031 // List of what to disconnect
2032 vector<CBlockIndex*> vDisconnect;
2033 for (CBlockIndex* pindex = pindexBest; pindex != pfork; pindex = pindex->pprev)
2034 vDisconnect.push_back(pindex);
2035
2036 // List of what to connect
2037 vector<CBlockIndex*> vConnect;
2038 for (CBlockIndex* pindex = pindexNew; pindex != pfork; pindex = pindex->pprev)
2039 vConnect.push_back(pindex);
2040 reverse(vConnect.begin(), vConnect.end());
2041
2042 // Disconnect shorter branch
2043 vector<CTransaction> vResurrect;
2044 foreach(CBlockIndex* pindex, vDisconnect)
2045 {
2046 CBlock block;
2047 if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos, true))
2048 return error("Reorganize() : ReadFromDisk for disconnect failed");
2049 if (!block.DisconnectBlock(txdb, pindex))
2050 return error("Reorganize() : DisconnectBlock failed");
2051
2052 // Queue memory transactions to resurrect
2053 foreach(const CTransaction& tx, block.vtx)
2054 if (!tx.IsCoinBase())
2055 vResurrect.push_back(tx);
2056 }
2057
2058 // Connect longer branch
2059 vector<CTransaction> vDelete;
2060 for (int i = 0; i < vConnect.size(); i++)
2061 {
2062 CBlockIndex* pindex = vConnect[i];
2063 CBlock block;
2064 if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos, true))
2065 return error("Reorganize() : ReadFromDisk for connect failed");
2066 if (!block.ConnectBlock(txdb, pindex))
2067 {
2068 // Invalid block, delete the rest of this branch
2069 txdb.TxnAbort();
2070 for (int j = i; j < vConnect.size(); j++)
2071 {
2072 CBlockIndex* pindex = vConnect[j];
2073 pindex->EraseBlockFromDisk();
2074 txdb.EraseBlockIndex(pindex->GetBlockHash());
2075 mapBlockIndex.erase(pindex->GetBlockHash());
2076 delete pindex;
2077 }
2078 return error("Reorganize() : ConnectBlock failed");
2079 }
2080
2081 // Queue memory transactions to delete
2082 foreach(const CTransaction& tx, block.vtx)
2083 vDelete.push_back(tx);
2084 }
2085 if (!txdb.WriteHashBestChain(pindexNew->GetBlockHash()))
2086 return error("Reorganize() : WriteHashBestChain failed");
2087
2088 // Commit now because resurrecting could take some time
2089 txdb.TxnCommit();
2090
2091 // Disconnect shorter branch
2092 foreach(CBlockIndex* pindex, vDisconnect)
2093 if (pindex->pprev)
2094 pindex->pprev->pnext = NULL;
2095
2096 // Connect longer branch
2097 foreach(CBlockIndex* pindex, vConnect)
2098 if (pindex->pprev)
2099 pindex->pprev->pnext = pindex;
2100
2101 // Resurrect memory transactions that were in the disconnected branch
2102 foreach(CTransaction& tx, vResurrect)
2103 tx.AcceptTransaction(txdb, false);
2104
2105 // Delete redundant memory transactions that are in the connected branch
2106 foreach(CTransaction& tx, vDelete)
2107 tx.RemoveFromMemoryPool();
2108
2109 return true;
2110}
2111
2112
2113bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
2114{
2115 // Check for duplicate
2116 uint256 hash = GetHash();
2117 if (mapBlockIndex.count(hash))
2118 return error("AddToBlockIndex() : %s already exists", hash.ToString().substr(0,14).c_str());
2119
2120 // Construct new block index object
2121 CBlockIndex* pindexNew = new CBlockIndex(nFile, nBlockPos, *this);
2122 if (!pindexNew)
2123 return error("AddToBlockIndex() : new CBlockIndex failed");
2124 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
2125 pindexNew->phashBlock = &((*mi).first);
2126 map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(hashPrevBlock);
2127 if (miPrev != mapBlockIndex.end())
2128 {
2129 pindexNew->pprev = (*miPrev).second;
2130 pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
2131 }
2132
2133 CTxDB txdb;
2134 txdb.TxnBegin();
2135 txdb.WriteBlockIndex(CDiskBlockIndex(pindexNew));
2136
2137 // New best
2138 if (pindexNew->nHeight > nBestHeight)
2139 {
2140 if (pindexGenesisBlock == NULL && hash == hashGenesisBlock)
2141 {
2142 pindexGenesisBlock = pindexNew;
2143 txdb.WriteHashBestChain(hash);
2144 }
2145 else if (hashPrevBlock == hashBestChain)
2146 {
2147 // Adding to current best branch
2148 if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash))
2149 {
2150 txdb.TxnAbort();
2151 pindexNew->EraseBlockFromDisk();
2152 mapBlockIndex.erase(pindexNew->GetBlockHash());
2153 delete pindexNew;
2154 return error("AddToBlockIndex() : ConnectBlock failed");
2155 }
2156 txdb.TxnCommit();
2157 pindexNew->pprev->pnext = pindexNew;
2158
2159 // Delete redundant memory transactions
2160 foreach(CTransaction& tx, vtx)
2161 tx.RemoveFromMemoryPool();
2162 }
2163 else
2164 {
2165 // New best branch
2166 if (!Reorganize(txdb, pindexNew))
2167 {
2168 txdb.TxnAbort();
2169 return error("AddToBlockIndex() : Reorganize failed");
2170 }
2171 }
2172
2173 // New best link
2174 hashBestChain = hash;
2175 pindexBest = pindexNew;
2176 nBestHeight = pindexBest->nHeight;
2177 nTransactionsUpdated++;
2178 printf("AddToBlockIndex: new best=%s height=%d\n", hashBestChain.ToString().substr(0,14).c_str(), nBestHeight);
2179 }
2180
2181 txdb.TxnCommit();
2182 txdb.Close();
2183
2184 // Relay wallet transactions that haven't gotten in yet
2185 if (pindexNew == pindexBest)
2186 RelayWalletTransactions();
2187
2188 MainFrameRepaint();
2189 return true;
2190}
2191
2192
2193
2194
2195bool CBlock::CheckBlock() const
2196{
2197 // These are checks that are independent of context
2198 // that can be verified before saving an orphan block.
2199
2200 // Size limits
2201 if (!CheckSizeLimits())
2202 return error("CheckBlock() : size limits failed");
2203
2204 // Check timestamp
2205 if (nTime > GetAdjustedTime() + 2 * 60 * 60)
2206 return error("CheckBlock() : block timestamp too far in the future");
2207
2208 // First transaction must be coinbase, the rest must not be
2209 if (vtx.empty() || !vtx[0].IsCoinBase())
2210 return error("CheckBlock() : first tx is not coinbase");
2211 for (int i = 1; i < vtx.size(); i++)
2212 if (vtx[i].IsCoinBase())
2213 return error("CheckBlock() : more than one coinbase");
2214
2215 // Check transactions
2216 foreach(const CTransaction& tx, vtx)
2217 if (!tx.CheckTransaction())
2218 return error("CheckBlock() : CheckTransaction failed");
2219
2220 // Cap the work a block can demand. MAX_SIZE bounds the bytes, not the cost:
2221 // every signature operation is an elliptic-curve verification, and at this
2222 // chain's difficulty a block packed with them is affordable to mine and
2223 // expensive for everyone else to reject.
2224 unsigned int nSigOps = 0;
2225 foreach(const CTransaction& tx, vtx)
2226 nSigOps += tx.GetSigOpCount();
2227 if (nSigOps > MAX_BLOCK_SIGOPS)
2228 return error("CheckBlock() : out-of-bounds signature operation count");
2229
2230 // Reject blocks carrying the same transaction twice (CVE-2012-2459).
2231 //
2232 // BuildMerkleTree duplicates the last hash when a level has an odd width,
2233 // so appending a copy of the trailing transaction(s) yields a block with
2234 // an identical merkle root -- and therefore an identical block hash -- to
2235 // a legitimate one. The forgery fails validation, the hash gets recorded
2236 // as bad, and the real block is then refused because it hashes the same.
2237 set<uint256> setTxHashes;
2238 foreach(const CTransaction& tx, vtx)
2239 {
2240 uint256 hashTx = tx.GetHash();
2241 if (setTxHashes.count(hashTx))
2242 return error("CheckBlock() : duplicate transaction in block");
2243 setTxHashes.insert(hashTx);
2244 }
2245
2246 // Check proof of work matches claimed amount (memory-hard RandomX PoW)
2247 if (CBigNum().SetCompact(nBits) > bnProofOfWorkLimit)
2248 return error("CheckBlock() : nBits below minimum work");
2249 if (GetPoWHash() > CBigNum().SetCompact(nBits).getuint256())
2250 return error("CheckBlock() : RandomX proof-of-work does not match nBits");
2251
2252 // Check merkleroot
2253 if (hashMerkleRoot != BuildMerkleTree())
2254 return error("CheckBlock() : hashMerkleRoot mismatch");
2255
2256 return true;
2257}
2258
2259bool CBlock::AcceptBlock()
2260{
2261 // Check for duplicate
2262 uint256 hash = GetHash();
2263 if (mapBlockIndex.count(hash))
2264 return error("AcceptBlock() : block already in mapBlockIndex");
2265
2266 // Get prev block index
2267 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashPrevBlock);
2268 if (mi == mapBlockIndex.end())
2269 return error("AcceptBlock() : prev block not found");
2270 CBlockIndex* pindexPrev = (*mi).second;
2271
2272 // Check timestamp against prev
2273 if (nTime <= pindexPrev->GetMedianTimePast())
2274 return error("AcceptBlock() : block's timestamp is too early");
2275
2276 // Check proof of work
2277 if (nBits != GetNextWorkRequired(pindexPrev))
2278 return error("AcceptBlock() : incorrect proof of work");
2279
2280 // Write block to history file
2281 unsigned int nFile;
2282 unsigned int nBlockPos;
2283 if (!WriteToDisk(!fClient, nFile, nBlockPos))
2284 return error("AcceptBlock() : WriteToDisk failed");
2285 if (!AddToBlockIndex(nFile, nBlockPos))
2286 return error("AcceptBlock() : AddToBlockIndex failed");
2287
2288 if (hashBestChain == hash)
2289 RelayInventory(CInv(MSG_BLOCK, hash));
2290
2291 // // Add atoms to user reviews for coins created
2292 // vector<unsigned char> vchPubKey;
2293 // if (ExtractPubKey(vtx[0].vout[0].scriptPubKey, false, vchPubKey))
2294 // {
2295 // unsigned short nAtom = GetRand(USHRT_MAX - 100) + 100;
2296 // vector<unsigned short> vAtoms(1, nAtom);
2297 // AddAtomsAndPropagate(Hash(vchPubKey.begin(), vchPubKey.end()), vAtoms, true);
2298 // }
2299
2300 return true;
2301}
2302
2303bool ProcessBlock(CNode* pfrom, CBlock* pblock)
2304{
2305 // Counted before any check, so the ratio below is against everything that
2306 // arrived rather than everything that was any good.
2307 if (pfrom)
2308 nBlocksReceived++;
2309
2310 // Check for duplicate
2311 uint256 hash = pblock->GetHash();
2312 if (mapBlockIndex.count(hash))
2313 return error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString().substr(0,14).c_str());
2314 if (mapOrphanBlocks.count(hash))
2315 return error("ProcessBlock() : already have block (orphan) %s", hash.ToString().substr(0,14).c_str());
2316
2317 // Preliminary checks
2318 if (!pblock->CheckBlock())
2319 {
2320 delete pblock;
2321 return error("ProcessBlock() : CheckBlock FAILED");
2322 }
2323
2324 // If don't already have its previous block, shunt it off to holding area until we get it
2325 if (!mapBlockIndex.count(pblock->hashPrevBlock))
2326 {
2327 printf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString().substr(0,14).c_str());
2328 if (pfrom)
2329 nBlocksWithoutParent++;
2330 mapOrphanBlocks.insert(make_pair(hash, pblock));
2331 mapOrphanBlocksByPrev.insert(make_pair(pblock->hashPrevBlock, pblock));
2332
2333 // Read what we need out of pblock before trimming: eviction picks at
2334 // random and is perfectly entitled to pick the block just inserted,
2335 // which would leave the GetOrphanRoot call below reading freed memory.
2336 uint256 hashOrphanRoot = GetOrphanRoot(pblock);
2337
2338 LimitOrphanBlocks(MAX_ORPHAN_BLOCKS);
2339
2340 // Ask this guy to fill in what we're missing
2341 if (pfrom)
2342 pfrom->PushGetBlocks(pindexBest, hashOrphanRoot);
2343 return true;
2344 }
2345
2346 // Store to disk
2347 if (!pblock->AcceptBlock())
2348 {
2349 delete pblock;
2350 return error("ProcessBlock() : AcceptBlock FAILED");
2351 }
2352 delete pblock;
2353
2354 // Recursively process any orphan blocks that depended on this one
2355 vector<uint256> vWorkQueue;
2356 vWorkQueue.push_back(hash);
2357 for (int i = 0; i < vWorkQueue.size(); i++)
2358 {
2359 uint256 hashPrev = vWorkQueue[i];
2360 for (multimap<uint256, CBlock*>::iterator mi = mapOrphanBlocksByPrev.lower_bound(hashPrev);
2361 mi != mapOrphanBlocksByPrev.upper_bound(hashPrev);
2362 ++mi)
2363 {
2364 CBlock* pblockOrphan = (*mi).second;
2365 if (pblockOrphan->AcceptBlock())
2366 vWorkQueue.push_back(pblockOrphan->GetHash());
2367 mapOrphanBlocks.erase(pblockOrphan->GetHash());
2368 delete pblockOrphan;
2369 }
2370 mapOrphanBlocksByPrev.erase(hashPrev);
2371 }
2372
2373 printf("ProcessBlock: ACCEPTED\n");
2374 return true;
2375}
2376
2377
2378
2379
2380
2381
2382
2383
2384template<typename Stream>
2385bool ScanMessageStart(Stream& s)
2386{
2387 // Scan ahead to the next pchMessageStart, which should normally be immediately
2388 // at the file pointer. Leaves file pointer at end of pchMessageStart.
2389 s.clear(0);
2390 short prevmask = s.exceptions(0);
2391 const char* p = BEGIN(pchMessageStart);
2392 try
2393 {
2394 loop
2395 {
2396 char c;
2397 s.read(&c, 1);
2398 if (s.fail())
2399 {
2400 s.clear(0);
2401 s.exceptions(prevmask);
2402 return false;
2403 }
2404 if (*p != c)
2405 p = BEGIN(pchMessageStart);
2406 if (*p == c)
2407 {
2408 if (++p == END(pchMessageStart))
2409 {
2410 s.clear(0);
2411 s.exceptions(prevmask);
2412 return true;
2413 }
2414 }
2415 }
2416 }
2417 catch (...)
2418 {
2419 s.clear(0);
2420 s.exceptions(prevmask);
2421 return false;
2422 }
2423}
2424
2425string GetAppDir()
2426{
2427 string strDir;
2428 if (!strSetDataDir.empty())
2429 {
2430 strDir = strSetDataDir;
2431 }
2432#ifdef _WIN32
2433 else if (getenv("APPDATA"))
2434 {
2435 strDir = strprintf("%s\\Bitflash", getenv("APPDATA"));
2436 }
2437 else if (getenv("USERPROFILE"))
2438 {
2439 string strAppData = strprintf("%s\\Application Data", getenv("USERPROFILE"));
2440 static bool fMkdirDone;
2441 if (!fMkdirDone)
2442 {
2443 fMkdirDone = true;
2444 _mkdir(strAppData.c_str());
2445 }
2446 strDir = strprintf("%s\\Bitflash", strAppData.c_str());
2447 }
2448#else
2449 else if (getenv("HOME"))
2450 {
2451 strDir = strprintf("%s/.bitflash", getenv("HOME"));
2452 }
2453#endif
2454 else
2455 {
2456 return ".";
2457 }
2458 static bool fMkdirDone;
2459 if (!fMkdirDone)
2460 {
2461 fMkdirDone = true;
2462 _mkdir(strDir.c_str());
2463 }
2464 return strDir;
2465}
2466
2467FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode)
2468{
2469 if (nFile == -1)
2470 return NULL;
2471 FILE* file = fopen(strprintf("%s/blk%04d.dat", GetAppDir().c_str(), nFile).c_str(), pszMode);
2472 if (!file)
2473 return NULL;
2474 if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w'))
2475 {
2476 if (fseek(file, nBlockPos, SEEK_SET) != 0)
2477 {
2478 fclose(file);
2479 return NULL;
2480 }
2481 }
2482 return file;
2483}
2484
2485static unsigned int nCurrentBlockFile = 1;
2486
2487FILE* AppendBlockFile(unsigned int& nFileRet)
2488{
2489 nFileRet = 0;
2490 loop
2491 {
2492 FILE* file = OpenBlockFile(nCurrentBlockFile, 0, "ab");
2493 if (!file)
2494 return NULL;
2495 if (fseek(file, 0, SEEK_END) != 0)
2496 return NULL;
2497 // FAT32 filesize max 4GB, fseek and ftell max 2GB, so we must stay under 2GB
2498 if (ftell(file) < 0x7F000000 - MAX_SIZE)
2499 {
2500 nFileRet = nCurrentBlockFile;
2501 return file;
2502 }
2503 fclose(file);
2504 nCurrentBlockFile++;
2505 }
2506}
2507
2508bool LoadBlockIndex(bool fAllowNew)
2509{
2510 // Initialize the RandomX PoW before touching any block (both the genesis
2511 // and verification depend on it).
2512 if (!RandomXInit())
2513 return error("LoadBlockIndex() : RandomXInit failed");
2514
2515 //
2516 // Load block index
2517 //
2518 CTxDB txdb("cr");
2519 if (!txdb.LoadBlockIndex())
2520 return false;
2521 txdb.Close();
2522
2523 // Repair a bad tip found during verification.
2524 //
2525 // This has to happen after the handle above is closed. CTxDB::LoadBlockIndex
2526 // walks the index with a cursor it never closes, so it is still holding read
2527 // locks -- a write transaction opened alongside it waits on them forever.
2528 // Measured, not guessed: the node came up, printed the diagnosis, and hung
2529 // there with nothing in any log.
2530 if (pindexBadChainFork)
2531 {
2532 CBlockIndex* pindexFork = pindexBadChainFork;
2533 pindexBadChainFork = NULL;
2534
2535 printf("LoadBlockIndex() : *** moving best chain back to height %d, discarding %d block(s)\n",
2536 pindexFork->nHeight, nBestHeight - pindexFork->nHeight);
2537
2538 vector<CBlockIndex*> vDisconnect;
2539 for (CBlockIndex* pindex = pindexBest; pindex && pindex != pindexFork; pindex = pindex->pprev)
2540 vDisconnect.push_back(pindex);
2541
2542 bool fRolledBack = false;
2543 try
2544 {
2545 CTxDB txdbWrite;
2546 txdbWrite.TxnBegin();
2547 foreach(CBlockIndex* pindex, vDisconnect)
2548 {
2549 CBlock block;
2550 if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos, true))
2551 throw runtime_error("ReadFromDisk for disconnect failed");
2552 if (!block.DisconnectBlock(txdbWrite, pindex))
2553 throw runtime_error("DisconnectBlock failed");
2554 }
2555 if (!txdbWrite.WriteHashBestChain(pindexFork->GetBlockHash()))
2556 throw runtime_error("WriteHashBestChain failed");
2557 txdbWrite.TxnCommit();
2558 txdbWrite.Close();
2559 fRolledBack = true;
2560 }
2561 catch (const std::exception& e)
2562 {
2563 printf("LoadBlockIndex() : rollback failed: %s\n", e.what());
2564 }
2565 catch (...)
2566 {
2567 printf("LoadBlockIndex() : rollback failed\n");
2568 }
2569
2570 if (fRolledBack)
2571 {
2572 foreach(CBlockIndex* pindex, vDisconnect)
2573 if (pindex->pprev)
2574 pindex->pprev->pnext = NULL;
2575
2576 pindexBest = pindexFork;
2577 hashBestChain = pindexBest->GetBlockHash();
2578 nBestHeight = pindexBest->nHeight;
2579 printf("LoadBlockIndex() : now at height %d, will re-download from peers\n", nBestHeight);
2580 }
2581 else
2582 {
2583 // Start anyway. The operator needs a running node to read this from.
2584 printf("LoadBlockIndex() : *** still on the bad chain at height %d -- back up the data directory and report this\n",
2585 nBestHeight);
2586 }
2587 }
2588
2589 //
2590 // Init with genesis block
2591 //
2592 if (mapBlockIndex.empty())
2593 {
2594 if (!fAllowNew)
2595 return false;
2596
2597
2598 // Genesis Block:
2599 // GetHash() = 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
2600 // hashMerkleRoot = 0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
2601 // txNew.vin[0].scriptSig = 486604799 4 0x736B6E616220726F662074756F6C69616220646E6F63657320666F206B6E697262206E6F20726F6C6C65636E61684320393030322F6E614A2F33302073656D695420656854
2602 // txNew.vout[0].nValue = 5000000000
2603 // txNew.vout[0].scriptPubKey = 0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704 OP_CHECKSIG
2604 // block.nVersion = 1
2605 // block.nTime = 1231006505
2606 // block.nBits = 0x1d00ffff
2607 // block.nNonce = 2083236893
2608 // CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
2609 // CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
2610 // CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
2611 // CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
2612 // vMerkleTree: 4a5e1e
2613
2614 // Bitflash genesis block -- own header (fair launch, 2026 stable relaunch)
2615 char* pszTimestamp = "Bitflash 24/Jul/2026 Fair launch: one CPU one vote, no premine";
2616 CTransaction txNew;
2617 txNew.vin.resize(1);
2618 txNew.vout.resize(1);
2619 txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((unsigned char*)pszTimestamp, (unsigned char*)pszTimestamp + strlen(pszTimestamp));
2620 txNew.vout[0].nValue = 50 * COIN;
2621 txNew.vout[0].scriptPubKey = CScript() << CBigNum("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704") << OP_CHECKSIG;
2622 CBlock block;
2623 block.vtx.push_back(txNew);
2624 block.hashPrevBlock = 0;
2625 block.hashMerkleRoot = block.BuildMerkleTree();
2626 block.nVersion = 1;
2627 block.nTime = 1753315200; // 2026-07-24 00:00:00 UTC (stable relaunch)
2628 block.nBits = 0x1f0fffff; // = bnProofOfWorkLimit (Bitflash RandomX floor)
2629 block.nNonce = GENESIS_NONCE;
2630
2631 // If the nonce has not been found yet, mine the genesis once (RandomX)
2632 // and print the values to be hardcoded in the constants above.
2633 if (block.GetHash() != hashGenesisBlock)
2634 {
2635 printf("Mining Bitflash genesis block (RandomX)...\n");
2636 uint256 hashTarget = CBigNum().SetCompact(block.nBits).getuint256();
2637 while (block.GetPoWHash() > hashTarget)
2638 {
2639 if ((block.nNonce & 0x3ff) == 0)
2640 printf("nonce %u\r", block.nNonce);
2641 block.nNonce++;
2642 if (block.nNonce == 0)
2643 {
2644 printf("nonce overflow, incrementing nTime\n");
2645 block.nTime++;
2646 }
2647 }
2648 printf("\n=== BITFLASH GENESIS (RandomX) FOUND ===\n");
2649 printf("nTime = %u\n", block.nTime);
2650 printf("nNonce = %u (0x%08x)\n", block.nNonce, block.nNonce);
2651 printf("powhash = %s\n", block.GetPoWHash().ToString().c_str());
2652 printf("hash = %s\n", block.GetHash().ToString().c_str());
2653 printf("merkle = %s\n", block.hashMerkleRoot.ToString().c_str());
2654 printf("========================================\n");
2655 }
2656
2657 // Asserts only apply once the genesis values are hardcoded
2658 if (hashGenesisBlock != uint256(0))
2659 {
2660 assert(block.hashMerkleRoot == hashGenesisMerkleRoot);
2661 assert(block.GetHash() == hashGenesisBlock);
2662 }
2663
2664 // Start new block file
2665 unsigned int nFile;
2666 unsigned int nBlockPos;
2667 if (!block.WriteToDisk(!fClient, nFile, nBlockPos))
2668 return error("LoadBlockIndex() : writing genesis block to disk failed");
2669 if (!block.AddToBlockIndex(nFile, nBlockPos))
2670 return error("LoadBlockIndex() : genesis block not accepted");
2671 }
2672
2673 return true;
2674}
2675
2676
2677
2678void PrintBlockTree()
2679{
2680 // precompute tree structure
2681 map<CBlockIndex*, vector<CBlockIndex*> > mapNext;
2682 for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
2683 {
2684 CBlockIndex* pindex = (*mi).second;
2685 mapNext[pindex->pprev].push_back(pindex);
2686 // test
2687 //while (rand() % 3 == 0)
2688 // mapNext[pindex->pprev].push_back(pindex);
2689 }
2690
2691 vector<pair<int, CBlockIndex*> > vStack;
2692 vStack.push_back(make_pair(0, pindexGenesisBlock));
2693
2694 int nPrevCol = 0;
2695 while (!vStack.empty())
2696 {
2697 int nCol = vStack.back().first;
2698 CBlockIndex* pindex = vStack.back().second;
2699 vStack.pop_back();
2700
2701 // print split or gap
2702 if (nCol > nPrevCol)
2703 {
2704 for (int i = 0; i < nCol-1; i++)
2705 printf("| ");
2706 printf("|\\\n");
2707 }
2708 else if (nCol < nPrevCol)
2709 {
2710 for (int i = 0; i < nCol; i++)
2711 printf("| ");
2712 printf("|\n");
2713 }
2714 nPrevCol = nCol;
2715
2716 // print columns
2717 for (int i = 0; i < nCol; i++)
2718 printf("| ");
2719
2720 // print item
2721 CBlock block;
2722 block.ReadFromDisk(pindex, true);
2723 printf("%d (%u,%u) %s %s tx %d",
2724 pindex->nHeight,
2725 pindex->nFile,
2726 pindex->nBlockPos,
2727 block.GetHash().ToString().substr(0,14).c_str(),
2728 DateTimeStr(block.nTime).c_str(),
2729 (int)block.vtx.size());
2730
2731 CRITICAL_BLOCK(cs_mapWallet)
2732 {
2733 if (mapWallet.count(block.vtx[0].GetHash()))
2734 {
2735 CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
2736 printf(" mine: %d %d %lld", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
2737 }
2738 }
2739 printf("\n");
2740
2741
2742 // put the main timechain first
2743 vector<CBlockIndex*>& vNext = mapNext[pindex];
2744 for (int i = 0; i < vNext.size(); i++)
2745 {
2746 if (vNext[i]->pnext)
2747 {
2748 swap(vNext[0], vNext[i]);
2749 break;
2750 }
2751 }
2752
2753 // iterate children
2754 for (int i = 0; i < vNext.size(); i++)
2755 vStack.push_back(make_pair(nCol+i, vNext[i]));
2756 }
2757}
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768//////////////////////////////////////////////////////////////////////////////
2769//
2770// Messages
2771//
2772
2773
2774bool AlreadyHave(CTxDB& txdb, const CInv& inv)
2775{
2776 switch (inv.type)
2777 {
2778 case MSG_TX: return mapTransactions.count(inv.hash) || txdb.ContainsTx(inv.hash);
2779 case MSG_BLOCK: return mapBlockIndex.count(inv.hash) || mapOrphanBlocks.count(inv.hash);
2780 case MSG_REVIEW: return true;
2781 case MSG_PRODUCT: return mapProducts.count(inv.hash);
2782 }
2783 // Don't know what it is, just say we already got one
2784 return true;
2785}
2786
2787
2788
2789
2790
2791
2792
2793bool ProcessMessages(CNode* pfrom)
2794{
2795 CDataStream& vRecv = pfrom->vRecv;
2796 if (vRecv.empty())
2797 return true;
2798 LogPrint("net", "ProcessMessages(%d bytes)\n", (int)vRecv.size());
2799
2800 //
2801 // Message format
2802 // (4) message start
2803 // (12) command
2804 // (4) size
2805 // (x) data
2806 //
2807
2808 loop
2809 {
2810 // Scan for message start
2811 CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(pchMessageStart), END(pchMessageStart));
2812 if (vRecv.end() - pstart < sizeof(CMessageHeader))
2813 {
2814 if (vRecv.size() > sizeof(CMessageHeader))
2815 {
2816 if (LogAcceptsCategory("net")) printf("\n\nPROCESSMESSAGE MESSAGESTART NOT FOUND\n\n");
2817 vRecv.erase(vRecv.begin(), vRecv.end() - sizeof(CMessageHeader));
2818 }
2819 break;
2820 }
2821 if (pstart - vRecv.begin() > 0)
2822 if (LogAcceptsCategory("net")) printf("\n\nPROCESSMESSAGE SKIPPED %d BYTES\n\n", (int)(pstart - vRecv.begin()));
2823 vRecv.erase(vRecv.begin(), pstart);
2824
2825 // Read the header from a copy first. The old path consumed the header,
2826 // noticed the payload was incomplete, inserted the header back at the
2827 // front of the receive buffer, then slept inside the shared message
2828 // thread. A peer could announce a large payload and drip bytes forever,
2829 // making every pass pay for an O(n) insert and a 100 ms stall.
2830 CMessageHeader hdr;
2831 CDataStream vHeader(vRecv.begin(), vRecv.begin() + sizeof(CMessageHeader),
2832 vRecv.nType, vRecv.nVersion);
2833 vHeader >> hdr;
2834 if (!hdr.IsValid())
2835 {
2836 if (LogAcceptsCategory("net")) printf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", hdr.GetCommand().c_str());
2837 if (hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_SIZE)
2838 pfrom->fDisconnect = true;
2839 pfrom->nIncompleteMessageStart = 0;
2840 vRecv.ignore(sizeof(CMessageHeader));
2841 continue;
2842 }
2843 string strCommand = hdr.GetCommand();
2844
2845 // Message size
2846 unsigned int nMessageSize = hdr.nMessageSize;
2847 unsigned int nPayloadAvailable = vRecv.size() - sizeof(CMessageHeader);
2848 if (nMessageSize > nPayloadAvailable)
2849 {
2850 if (pfrom->nIncompleteMessageStart == 0 ||
2851 pfrom->nIncompleteMessageSize != nMessageSize ||
2852 pfrom->strIncompleteMessageCommand != strCommand)
2853 {
2854 pfrom->nIncompleteMessageStart = GetTime();
2855 pfrom->nIncompleteMessageSize = nMessageSize;
2856 pfrom->strIncompleteMessageCommand = strCommand;
2857 }
2858 else if (GetTime() - pfrom->nIncompleteMessageStart >
2859 BTF_INCOMPLETE_MESSAGE_TIMEOUT_SECS)
2860 {
2861 LogPrint("net",
2862 "disconnecting %s: incomplete %s message, %u of %u bytes after %d seconds\n",
2863 pfrom->addr.ToString().c_str(), strCommand.c_str(),
2864 nPayloadAvailable, nMessageSize,
2865 BTF_INCOMPLETE_MESSAGE_TIMEOUT_SECS);
2866 pfrom->fDisconnect = true;
2867 }
2868 break;
2869 }
2870 pfrom->nIncompleteMessageStart = 0;
2871 pfrom->nIncompleteMessageSize = 0;
2872 pfrom->strIncompleteMessageCommand.clear();
2873 vRecv.ignore(sizeof(CMessageHeader));
2874
2875 // Copy message to its own buffer
2876 CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);
2877 vRecv.ignore(nMessageSize);
2878
2879 // Process message
2880 bool fRet = false;
2881 try
2882 {
2883 CheckForShutdown(2);
2884 CRITICAL_BLOCK(cs_main)
2885 fRet = ProcessMessage(pfrom, strCommand, vMsg);
2886 CheckForShutdown(2);
2887 }
2888 CATCH_PRINT_EXCEPTION("ProcessMessage()")
2889 if (!fRet)
2890 if (LogAcceptsCategory("net")) printf("ProcessMessage(%s, %d bytes) from %s to %s FAILED\n", strCommand.c_str(), nMessageSize, pfrom->addr.ToString().c_str(), addrLocalHost.ToString().c_str());
2891 }
2892
2893 vRecv.Compact();
2894 return true;
2895}
2896
2897
2898
2899
2900bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
2901{
2902 static map<unsigned int, vector<unsigned char> > mapReuseKey;
2903 if (LogAcceptsCategory("net")) { printf("received: %-12s (%d bytes) ", strCommand.c_str(), (int)vRecv.size()); for (int i = 0; i < min(vRecv.size(), (unsigned int)25); i++) printf("%02x ", vRecv[i] & 0xff); printf("\n"); }
2904 if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0)
2905 {
2906 if (LogAcceptsCategory("net")) printf("dropmessages DROPPING RECV MESSAGE\n");
2907 return true;
2908 }
2909
2910
2911
2912 if (strCommand == "version")
2913 {
2914 // Can only do this once
2915 if (pfrom->nVersion != 0)
2916 return false;
2917
2918 int64 nTime;
2919 CAddress addrMe;
2920 vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;
2921 if (pfrom->nVersion == 0)
2922 return false;
2923
2924 // Optional: peers older than this field simply end the message here,
2925 // and nStartingHeight stays -1 for them. Never make this a requirement
2926 // -- every node released so far sends the short form.
2927 if (!vRecv.empty())
2928 vRecv >> pfrom->nStartingHeight;
2929
2930 pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION));
2931 pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));
2932
2933 pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);
2934 if (pfrom->fClient)
2935 {
2936 pfrom->vSend.nType |= SER_BLOCKHEADERONLY;
2937 pfrom->vRecv.nType |= SER_BLOCKHEADERONLY;
2938 }
2939
2940 AddTimeData(pfrom->addr.ip, nTime);
2941
2942 // Ask the first connected node for block updates
2943 static bool fAskedForBlocks;
2944 if (!fAskedForBlocks && !pfrom->fClient)
2945 {
2946 fAskedForBlocks = true;
2947 pfrom->PushGetBlocks(pindexBest, uint256(0));
2948 }
2949
2950 // Introduce ourselves and hand over the .btf peers that answered us.
2951 // Everything in here is self-certifying, so this is safe to send to a
2952 // node we know nothing about, and safe for it to act on.
2953 vector<string> vPexOut;
2954 BtfPexCollect(vPexOut);
2955 if (!vPexOut.empty())
2956 pfrom->PushMessage("btfpeers", vPexOut);
2957
2958 if (LogAcceptsCategory("net")) printf("version addrMe = %s, peer height = %d\n", addrMe.ToString().c_str(), pfrom->nStartingHeight);
2959 }
2960
2961
2962 else if (pfrom->nVersion == 0)
2963 {
2964 // Must have a version message before anything else
2965 return false;
2966 }
2967
2968
2969 else if (strCommand == "btfpeers")
2970 {
2971 // Peer exchange. Nothing here is taken on trust: BtfPexAccept checks
2972 // every descriptor's signature against the key its .btf address
2973 // decodes to, and drops the rest.
2974 int64 nNow = GetTime();
2975 if (nNow - pfrom->nLastPexRecv < PEX_MIN_INTERVAL)
2976 {
2977 if (LogAcceptsCategory("net"))
2978 printf("btfpeers: ignoring, %s is sending them too fast\n",
2979 pfrom->addr.ToString().c_str());
2980 return true;
2981 }
2982 pfrom->nLastPexRecv = nNow;
2983
2984 vector<string> vDesc;
2985 vRecv >> vDesc;
2986 int nKept = BtfPexAccept(vDesc);
2987 LogPrint("net", "btfpeers: kept %d of %zu descriptor(s) from %s\n",
2988 nKept, vDesc.size(), pfrom->addr.ToString().c_str());
2989 }
2990
2991
2992 else if (strCommand == "inv")
2993 {
2994 vector<CInv> vInv;
2995 vRecv >> vInv;
2996
2997 CTxDB txdb("r");
2998 foreach(const CInv& inv, vInv)
2999 {
3000 if (fShutdown)
3001 return true;
3002 pfrom->AddInventoryKnown(inv);
3003
3004 bool fAlreadyHave = AlreadyHave(txdb, inv);
3005 if (LogAcceptsCategory("net")) printf(" got inventory: %s %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new");
3006
3007 if (!fAlreadyHave)
3008 pfrom->AskFor(inv);
3009 else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
3010 pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
3011 }
3012 }
3013
3014
3015 else if (strCommand == "getdata")
3016 {
3017 vector<CInv> vInv;
3018 vRecv >> vInv;
3019
3020 foreach(const CInv& inv, vInv)
3021 {
3022 if (fShutdown)
3023 return true;
3024 if (LogAcceptsCategory("net")) printf("received getdata for: %s\n", inv.ToString().c_str());
3025
3026 if (inv.type == MSG_BLOCK)
3027 {
3028 // Send block from disk
3029 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(inv.hash);
3030 if (mi != mapBlockIndex.end())
3031 {
3032 //// could optimize this to send header straight from blockindex for client
3033 CBlock block;
3034 block.ReadFromDisk((*mi).second, !pfrom->fClient);
3035 pfrom->PushMessage("block", block);
3036 }
3037 }
3038 else if (inv.IsKnownType())
3039 {
3040 // Send stream from relay memory
3041 CRITICAL_BLOCK(cs_mapRelay)
3042 {
3043 map<CInv, CDataStream>::iterator mi = mapRelay.find(inv);
3044 if (mi != mapRelay.end())
3045 pfrom->PushMessage(inv.GetCommand(), (*mi).second);
3046 }
3047 }
3048 }
3049 }
3050
3051
3052 else if (strCommand == "getblocks")
3053 {
3054 CBlockLocator locator;
3055 uint256 hashStop;
3056 vRecv >> locator >> hashStop;
3057
3058 // Find the first block the caller has in the main chain
3059 CBlockIndex* pindex = locator.GetBlockIndex();
3060
3061 // Send the rest of the chain
3062 if (pindex)
3063 pindex = pindex->pnext;
3064 if (LogAcceptsCategory("net")) printf("getblocks %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,14).c_str());
3065 for (; pindex; pindex = pindex->pnext)
3066 {
3067 if (pindex->GetBlockHash() == hashStop)
3068 {
3069 if (LogAcceptsCategory("net")) printf(" getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,14).c_str());
3070 break;
3071 }
3072
3073 // Bypass setInventoryKnown in case an inventory message got lost
3074 CRITICAL_BLOCK(pfrom->cs_inventory)
3075 {
3076 CInv inv(MSG_BLOCK, pindex->GetBlockHash());
3077 // returns true if wasn't already contained in the set
3078 if (pfrom->setInventoryKnown2.insert(inv).second)
3079 {
3080 pfrom->setInventoryKnown.erase(inv);
3081 pfrom->vInventoryToSend.push_back(inv);
3082 }
3083 }
3084 }
3085 }
3086
3087
3088 else if (strCommand == "tx")
3089 {
3090 vector<uint256> vWorkQueue;
3091 CDataStream vMsg(vRecv);
3092 CTransaction tx;
3093 vRecv >> tx;
3094
3095 CInv inv(MSG_TX, tx.GetHash());
3096 pfrom->AddInventoryKnown(inv);
3097
3098 bool fMissingInputs = false;
3099 if (tx.AcceptTransaction(true, &fMissingInputs))
3100 {
3101 AddToWalletIfMine(tx, NULL);
3102 RelayMessage(inv, vMsg);
3103 mapAlreadyAskedFor.erase(inv);
3104 vWorkQueue.push_back(inv.hash);
3105
3106 // Recursively process any orphan transactions that depended on this one
3107 for (int i = 0; i < vWorkQueue.size(); i++)
3108 {
3109 uint256 hashPrev = vWorkQueue[i];
3110 for (multimap<uint256, CDataStream*>::iterator mi = mapOrphanTransactionsByPrev.lower_bound(hashPrev);
3111 mi != mapOrphanTransactionsByPrev.upper_bound(hashPrev);
3112 ++mi)
3113 {
3114 const CDataStream& vMsg = *((*mi).second);
3115 CTransaction tx;
3116 CDataStream(vMsg) >> tx;
3117 CInv inv(MSG_TX, tx.GetHash());
3118
3119 if (tx.AcceptTransaction(true))
3120 {
3121 if (LogAcceptsCategory("net")) printf(" accepted orphan tx %s\n", inv.hash.ToString().substr(0,6).c_str());
3122 AddToWalletIfMine(tx, NULL);
3123 RelayMessage(inv, vMsg);
3124 mapAlreadyAskedFor.erase(inv);
3125 vWorkQueue.push_back(inv.hash);
3126 }
3127 }
3128 }
3129
3130 foreach(uint256 hash, vWorkQueue)
3131 EraseOrphanTx(hash);
3132 }
3133 else if (fMissingInputs)
3134 {
3135 if (LogAcceptsCategory("net")) printf("storing orphan tx %s\n", inv.hash.ToString().substr(0,6).c_str());
3136 AddOrphanTx(vMsg);
3137 }
3138 }
3139
3140
3141 else if (strCommand == "review")
3142 {
3143 CDataStream vMsg(vRecv);
3144 CReview review;
3145 vRecv >> review;
3146
3147 CInv inv(MSG_REVIEW, review.GetHash());
3148 pfrom->AddInventoryKnown(inv);
3149
3150 if (review.AcceptReview())
3151 {
3152 // Relay the original message as-is in case it's a higher version than we know how to parse
3153 RelayMessage(inv, vMsg);
3154 mapAlreadyAskedFor.erase(inv);
3155 }
3156 }
3157
3158
3159 else if (strCommand == "block")
3160 {
3161 auto_ptr<CBlock> pblock(new CBlock);
3162 vRecv >> *pblock;
3163
3164 //// debug print
3165 if (LogAcceptsCategory("net")) { printf("received block:\n"); pblock->print(); }
3166
3167 CInv inv(MSG_BLOCK, pblock->GetHash());
3168 pfrom->AddInventoryKnown(inv);
3169
3170 if (ProcessBlock(pfrom, pblock.release()))
3171 mapAlreadyAskedFor.erase(inv);
3172 }
3173
3174
3175 else if (strCommand == "checkorder")
3176 {
3177 uint256 hashReply;
3178 CWalletTx order;
3179 vRecv >> hashReply >> order;
3180
3181 /// we have a chance to check the order here
3182
3183 // Keep giving the same key to the same ip until they use it
3184 if (!mapReuseKey.count(pfrom->addr.ip))
3185 mapReuseKey[pfrom->addr.ip] = GenerateNewKey();
3186
3187 // Send back approval of order and pubkey to use
3188 CScript scriptPubKey;
3189 scriptPubKey << mapReuseKey[pfrom->addr.ip] << OP_CHECKSIG;
3190 pfrom->PushMessage("reply", hashReply, (int)0, scriptPubKey);
3191 }
3192
3193
3194 else if (strCommand == "submitorder")
3195 {
3196 uint256 hashReply;
3197 CWalletTx wtxNew;
3198 vRecv >> hashReply >> wtxNew;
3199
3200 // Broadcast
3201 if (!wtxNew.AcceptWalletTransaction())
3202 {
3203 pfrom->PushMessage("reply", hashReply, (int)1);
3204 return error("submitorder AcceptWalletTransaction() failed, returning error 1");
3205 }
3206 wtxNew.fTimeReceivedIsTxTime = true;
3207 AddToWallet(wtxNew);
3208 wtxNew.RelayWalletTransaction();
3209 mapReuseKey.erase(pfrom->addr.ip);
3210
3211 // Send back confirmation
3212 pfrom->PushMessage("reply", hashReply, (int)0);
3213 }
3214
3215
3216 else if (strCommand == "reply")
3217 {
3218 uint256 hashReply;
3219 vRecv >> hashReply;
3220
3221 CRequestTracker tracker;
3222 CRITICAL_BLOCK(pfrom->cs_mapRequests)
3223 {
3224 map<uint256, CRequestTracker>::iterator mi = pfrom->mapRequests.find(hashReply);
3225 if (mi != pfrom->mapRequests.end())
3226 {
3227 tracker = (*mi).second;
3228 pfrom->mapRequests.erase(mi);
3229 }
3230 }
3231 if (!tracker.IsNull())
3232 tracker.fn(tracker.param1, vRecv);
3233 }
3234
3235
3236 else if (strCommand == "ping")
3237 {
3238 // Nothing to do and nothing to answer. Arriving at all is the entire
3239 // content of the message: the receive path has already stamped
3240 // nLastRecv, which is what the sender wanted us to notice.
3241 //
3242 // Deliberately no reply. A node old enough not to know "ping" ignores
3243 // it as an unknown command and would never answer one, so a scheme
3244 // that required an answer would read every such peer as dead.
3245 }
3246
3247
3248 else
3249 {
3250 // Ignore unknown commands for extensibility
3251 if (LogAcceptsCategory("net")) printf("ProcessMessage(%s) : Ignored unknown message\n", strCommand.c_str());
3252 }
3253
3254
3255 if (!vRecv.empty())
3256 if (LogAcceptsCategory("net")) printf("ProcessMessage(%s) : %d extra bytes\n", strCommand.c_str(), (int)vRecv.size());
3257
3258 return true;
3259}
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269bool SendMessages(CNode* pto)
3270{
3271 CheckForShutdown(2);
3272 CRITICAL_BLOCK(cs_main)
3273 {
3274 // Don't send anything until we get their version message
3275 if (pto->nVersion == 0)
3276 return true;
3277
3278
3279 //
3280 // Message: keep-alive ping
3281 //
3282 // Only when we have nothing else queued -- any real message serves the
3283 // same purpose. A peer with nothing to relay is otherwise silent, and
3284 // silence is exactly what the inactivity check disconnects on.
3285 //
3286 if (pto->nLastSend && GetTime() - pto->nLastSend > BTF_PING_INTERVAL_SECS && pto->vSend.empty())
3287 pto->PushMessage("ping");
3288
3289
3290 //
3291 // Message: inventory
3292 //
3293 vector<CInv> vInventoryToSend;
3294 CRITICAL_BLOCK(pto->cs_inventory)
3295 {
3296 vInventoryToSend.reserve(pto->vInventoryToSend.size());
3297 foreach(const CInv& inv, pto->vInventoryToSend)
3298 {
3299 // returns true if wasn't already contained in the set
3300 if (pto->setInventoryKnown.insert(inv).second)
3301 vInventoryToSend.push_back(inv);
3302 }
3303 pto->vInventoryToSend.clear();
3304 pto->setInventoryKnown2.clear();
3305 }
3306 if (!vInventoryToSend.empty())
3307 pto->PushMessage("inv", vInventoryToSend);
3308
3309
3310 //
3311 // Message: getdata
3312 //
3313 vector<CInv> vAskFor;
3314 int64 nNow = GetTime() * 1000000;
3315 CTxDB txdb("r");
3316 while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow)
3317 {
3318 const CInv& inv = (*pto->mapAskFor.begin()).second;
3319 if (LogAcceptsCategory("net")) printf("sending getdata: %s\n", inv.ToString().c_str());
3320 if (!AlreadyHave(txdb, inv))
3321 vAskFor.push_back(inv);
3322 pto->mapAskFor.erase(pto->mapAskFor.begin());
3323 }
3324 if (!vAskFor.empty())
3325 pto->PushMessage("getdata", vAskFor);
3326
3327 }
3328 return true;
3329}
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344//////////////////////////////////////////////////////////////////////////////
3345//
3346// BitcoinMiner
3347//
3348
3349int FormatHashBlocks(void* pbuffer, unsigned int len)
3350{
3351 unsigned char* pdata = (unsigned char*)pbuffer;
3352 unsigned int blocks = 1 + ((len + 8) / 64);
3353 unsigned char* pend = pdata + 64 * blocks;
3354 memset(pdata + len, 0, 64 * blocks - len);
3355 pdata[len] = 0x80;
3356 unsigned int bits = len * 8;
3357 pend[-1] = (bits >> 0) & 0xff;
3358 pend[-2] = (bits >> 8) & 0xff;
3359 pend[-3] = (bits >> 16) & 0xff;
3360 pend[-4] = (bits >> 24) & 0xff;
3361 return blocks;
3362}
3363
3364using CryptoPP::ByteReverse;
3365static int detectlittleendian = 1;
3366
3367void BlockSHA256(const void* pin, unsigned int nBlocks, void* pout)
3368{
3369 unsigned int* pinput = (unsigned int*)pin;
3370 unsigned int* pstate = (unsigned int*)pout;
3371
3372 CryptoPP::SHA256::InitState(pstate);
3373
3374 if (*(char*)&detectlittleendian != 0)
3375 {
3376 for (int n = 0; n < nBlocks; n++)
3377 {
3378 unsigned int pbuf[16];
3379 for (int i = 0; i < 16; i++)
3380 pbuf[i] = ByteReverse(pinput[n * 16 + i]);
3381 CryptoPP::SHA256::Transform(pstate, pbuf);
3382 }
3383 for (int i = 0; i < 8; i++)
3384 pstate[i] = ByteReverse(pstate[i]);
3385 }
3386 else
3387 {
3388 for (int n = 0; n < nBlocks; n++)
3389 CryptoPP::SHA256::Transform(pstate, pinput + n * 16);
3390 }
3391}
3392
3393
3394// ---------------------------------------------------------------------------
3395// Participant pool miner -- connects to an external Stratum server, receives
3396// RandomX jobs, hashes with the local CPU, and submits shares.
3397// Called from BitcoinMiner() when nMineMode == MINE_PARTICIPANT.
3398// ---------------------------------------------------------------------------
3399
3400using json = nlohmann::json;
3401
3402
3403// ---------------------------------------------------------------------------
3404// Participant miner -- connects to a pool over a .btf tunnel, runs Stratum,
3405// hashes with RandomX, submits shares. Called from BitcoinMiner().
3406// ---------------------------------------------------------------------------
3407
3408using json = nlohmann::json;
3409
3410static std::string ToHexStr(const void* p, size_t n)
3411{
3412 const unsigned char* b = (const unsigned char*)p;
3413 std::string s; s.reserve(n*2);
3414 static const char* H = "0123456789abcdef";
3415 for (size_t i = 0; i < n; i++) { s += H[b[i]>>4]; s += H[b[i]&0xf]; }
3416 return s;
3417}
3418
3419static std::vector<unsigned char> FromHexStr(const std::string& s)
3420{
3421 std::vector<unsigned char> v;
3422 for (size_t i = 0; i+1 < s.size(); i += 2) {
3423 auto h = [](char c)->int{
3424 if(c>='0'&&c<='9') return c-'0';
3425 if(c>='a'&&c<='f') return c-'a'+10;
3426 if(c>='A'&&c<='F') return c-'A'+10;
3427 return 0;
3428 };
3429 v.push_back((unsigned char)((h(s[i])<<4)|h(s[i+1])));
3430 }
3431 return v;
3432}
3433
3434static void UpdateParticipantHashRate(uint64 hashesSinceSample, int64 sampleStart)
3435{
3436 int64 elapsed = GetTime() - sampleStart;
3437 if (elapsed <= 0) elapsed = 1;
3438 gParticipantHashRateX1000.store(
3439 (uint64)((double)hashesSinceSample / (double)elapsed * 1000.0));
3440}
3441
3442// Blocking send of a JSON line to the pool.
3443static bool StratumSendLine(SOCKET s, const json& j)
3444{
3445 std::string line = j.dump() + "\n";
3446 int sent = 0, total = (int)line.size();
3447 while (sent < total) {
3448 int r = send(s, line.c_str()+sent, total-sent, 0);
3449 if (r <= 0) return false;
3450 sent += r;
3451 }
3452 return true;
3453}
3454
3455// Non-blocking recv into carry buffer. Returns true + fills line when a
3456// complete newline-terminated message is ready. Returns false in two cases:
3457// disconnected=true -- socket closed by peer; caller must stop
3458// disconnected=false -- no complete line yet; caller should select() and retry
3459static bool StratumRecvLine(SOCKET s, std::string& buf,
3460 std::string& line, bool& disconnected)
3461{
3462 disconnected = false;
3463 char tmp[4096];
3464#ifdef _WIN32
3465 u_long avail = 0;
3466 ioctlsocket(s, FIONREAD, &avail);
3467 if (avail > 0) {
3468 int r = recv(s, tmp, (int)std::min((u_long)(sizeof(tmp)-1), avail), 0);
3469 if (r > 0) { tmp[r] = 0; buf += tmp; }
3470 else if (r == 0) { disconnected = true; return false; }
3471 }
3472#else
3473 {
3474 int r = recv(s, tmp, sizeof(tmp)-1, MSG_DONTWAIT);
3475 if (r > 0) { tmp[r] = 0; buf += tmp; }
3476 else if (r == 0) { disconnected = true; return false; }
3477 // r < 0: EAGAIN -- no data right now
3478 }
3479#endif
3480 size_t pos = buf.find('\n');
3481 if (pos == std::string::npos) return false;
3482 line = buf.substr(0, pos);
3483 if (!line.empty() && line.back() == '\r') line.pop_back();
3484 buf = buf.substr(pos + 1);
3485 return true;
3486}
3487
3488// How long to wait for a mining.notify after authorize before giving up
3489static const int64 STUCK_NO_JOB_TIMEOUT_SECS = 120;
3490
3491static bool PoolParticipantMiner()
3492{
3493 // ------------------------------------------------------------------
3494 // Step 1: resolve .btf address -> meeting node
3495 // ------------------------------------------------------------------
3496 if (strParticipantPool.empty()) {
3497 LogPrint("worker", "[worker] no pool selected\n");
3498 SetParticipantMiningStatus("no pool selected");
3499 return false;
3500 }
3501
3502 LogPrint("worker", "[worker] connecting to pool %s\n", strParticipantPool.c_str());
3503 SetParticipantMiningStatus("resolving pool address");
3504
3505 unsigned char target_pubkey[32];
3506 if (!btf::ParseAddress(strParticipantPool, target_pubkey)) {
3507 LogPrint("worker", "[worker] invalid .btf address: %s\n", strParticipantPool.c_str());
3508 SetParticipantMiningStatus("invalid pool address");
3509 return false;
3510 }
3511
3512 std::string meetingHostPort;
3513 unsigned char service_enc_pub[32];
3514 if (!BtfResolve(strParticipantPool, meetingHostPort, service_enc_pub)) {
3515 LogPrint("worker", "[worker] failed to resolve pool %s"
3516 " (no Nostr descriptor found -- pool may be offline or relays down)\n",
3517 strParticipantPool.c_str());
3518 SetParticipantMiningStatus("failed to resolve pool");
3519 return false;
3520 }
3521 LogPrint("worker", "[worker] pool resolved to meeting node %s\n", meetingHostPort.c_str());
3522
3523 size_t colon = meetingHostPort.rfind(':');
3524 if (colon == std::string::npos) {
3525 LogPrint("worker", "[worker] bad meeting node format '%s'\n", meetingHostPort.c_str());
3526 SetParticipantMiningStatus("bad pool endpoint");
3527 return false;
3528 }
3529 std::string host = meetingHostPort.substr(0, colon);
3530 int port = atoi(meetingHostPort.substr(colon + 1).c_str());
3531 if (port <= 0 || port > 65535) {
3532 LogPrint("worker", "[worker] bad meeting port %d in '%s'\n",
3533 port, meetingHostPort.c_str());
3534 SetParticipantMiningStatus("bad pool port");
3535 return false;
3536 }
3537
3538 // ------------------------------------------------------------------
3539 // Step 2: open encrypted tunnel to pool
3540 // ------------------------------------------------------------------
3541 SetParticipantMiningStatus("opening tunnel");
3542 btf_socket_t s = btf::BtfClientTunnel(host.c_str(), (unsigned short)port,
3543 target_pubkey, service_enc_pub);
3544 if (s == INVALID_SOCKET) {
3545 LogPrint("worker", "[worker] tunnel connect FAILED via %s"
3546 " (relay unreachable or pool not listening)\n",
3547 meetingHostPort.c_str());
3548 SetParticipantMiningStatus("tunnel connect failed");
3549 return false;
3550 }
3551 LogPrint("worker", "[worker] tunnel open via %s\n", meetingHostPort.c_str());
3552 SetParticipantMiningStatus("tunnel open");
3553
3554 // ------------------------------------------------------------------
3555 // Step 3: determine our payout address (mining username)
3556 // ------------------------------------------------------------------
3557 std::string username;
3558 {
3559 std::vector<unsigned char> vchPubKey;
3560 if (CWalletDB("r").ReadDefaultKey(vchPubKey))
3561 username = PubKeyToAddress(vchPubKey);
3562 }
3563 if (username.empty()) username = BtfLocalAddress();
3564 if (username.empty()) {
3565 LogPrint("worker", "[worker] WARNING: could not determine wallet address"
3566 " -- shares will not pay out\n");
3567 username = "unknown";
3568 }
3569 LogPrint("worker", "[worker] payout address: %s\n", username.c_str());
3570
3571 // ------------------------------------------------------------------
3572 // Step 4: build the fast (~2 GB dataset) RandomX mode if not already
3573 // built, then start our VM. Without this, RandomXCreateMinerVM() falls
3574 // back to "light" mode (cache only) forever, which is dramatically
3575 // slower per hash than fast mode -- it recomputes dataset items on the
3576 // fly for every single hash instead of a direct memory lookup. That
3577 // alone can turn a "few seconds per share" pool into "many minutes per
3578 // share" regardless of how easy the share target is.
3579 //
3580 // This MUST happen before we send mining.subscribe/authorize, not
3581 // after: it's a synchronous, single-threaded-per-call build that can
3582 // take anywhere from several seconds to a couple of minutes depending
3583 // on core count. If it runs after the handshake messages are sent,
3584 // the pool's replies (subscribe ack, authorize ack, set_difficulty,
3585 // and the first job) all land in the OS socket buffer while we're
3586 // not reading -- nothing is lost, but we sit there looking (and
3587 // logging) like we're "stuck waiting for pool response" for the
3588 // entire build duration, when really we're just not listening yet.
3589 // Building the dataset first means that by the time we say
3590 // "subscribing", we're genuinely ready to read the reply the instant
3591 // it arrives.
3592 // ------------------------------------------------------------------
3593 if (!RandomXFastReady()) {
3594 SetParticipantMiningStatus("building RandomX dataset (~2GB, one-time)");
3595 unsigned int nThreads = std::thread::hardware_concurrency();
3596 RandomXInitDataset(nThreads > 0 ? (int)nThreads : 1);
3597 }
3598 void* rxvm = RandomXCreateMinerVM();
3599 if (!rxvm) {
3600 LogPrint("worker", "[worker] failed to create RandomX VM\n");
3601 SetParticipantMiningStatus("RandomX init failed");
3602 closesocket(s); return false;
3603 }
3604 LogPrint("worker", "[worker] RandomX VM ready (%s)\n",
3605 RandomXFastReady() ? "fast 2GB" : "light 256MB");
3606
3607 // ------------------------------------------------------------------
3608 // Step 5: Stratum subscribe + authorize. The socket is read from
3609 // immediately after this, in the main loop below, so nothing sits
3610 // unread behind a blocking dataset build anymore.
3611 // ------------------------------------------------------------------
3612 std::string buf;
3613 int msgId = 1;
3614 std::set<int> pendingSubmitIds;
3615
3616 SetParticipantMiningStatus("subscribing");
3617 LogPrint("worker", "[worker->pool] sending mining.subscribe\n");
3618 if (!StratumSendLine(s, json{{"id",msgId++},{"method","mining.subscribe"},
3619 {"params",json::array()}})) {
3620 LogPrint("worker", "[worker] subscribe send FAILED -- pool dropped connection\n");
3621 SetParticipantMiningStatus("subscribe send failed");
3622 RandomXDestroyMinerVM(rxvm);
3623 closesocket(s); return false;
3624 }
3625
3626 SetParticipantMiningStatus("authorizing");
3627 LogPrint("worker", "[worker->pool] sending mining.authorize as %s\n", username.c_str());
3628 if (!StratumSendLine(s, json{{"id",msgId++},{"method","mining.authorize"},
3629 {"params",json::array({username,"x"})}})) {
3630 LogPrint("worker", "[worker] authorize send FAILED -- pool dropped connection\n");
3631 SetParticipantMiningStatus("authorize send failed");
3632 RandomXDestroyMinerVM(rxvm);
3633 closesocket(s); return false;
3634 }
3635
3636 // ------------------------------------------------------------------
3637 // Step 6: main loop -- receive messages, hash, submit shares
3638 // ------------------------------------------------------------------
3639 std::string jobId;
3640 unsigned char header[80] = {};
3641 uint256 target;
3642 double currentDifficulty = 1.0; // updated by mining.set_difficulty from pool
3643 bool haveJob = false;
3644 bool gotSubscribeAck = false;
3645 bool gotAuthorizeAck = false;
3646 int64 authWaitStart = 0;
3647 int64 lastStuckLog = 0;
3648 unsigned int nNonce = 1;
3649 uint64 hashesSinceSample = 0;
3650 uint64 sessionSharesSent = 0; // this connection only
3651 uint64 sessionSharesAccepted = 0;
3652 int64 sampleStart = GetTime();
3653
3654 SetParticipantMiningStatus("waiting for pool response");
3655
3656 while (fGenerateBitcoins && nMineMode == MINE_PARTICIPANT && !fShutdown)
3657 {
3658 // -- Receive: check buffer first, then select --
3659 {
3660 bool haveBuffered = buf.find('\n') != std::string::npos;
3661 bool readable = false;
3662 if (!haveBuffered) {
3663 fd_set fds; FD_ZERO(&fds); FD_SET(s, &fds);
3664 struct timeval tv = {0, 50000}; // 50ms
3665 readable = select((int)s+1, &fds, NULL, NULL, &tv) > 0;
3666 }
3667
3668 if (haveBuffered || readable) {
3669 std::string line;
3670 bool disc = false;
3671 while (StratumRecvLine(s, buf, line, disc)) {
3672 json msg;
3673 try { msg = json::parse(line); } catch (...) {
3674 LogPrint("worker", "[pool->worker] JSON parse error: %.80s\n",
3675 line.c_str());
3676 continue;
3677 }
3678
3679 // -- Response to our subscribe (id=1) --
3680 if (msg.contains("id") && msg["id"].is_number_integer()
3681 && msg["id"].get<int>() == 1
3682 && msg.contains("result") && !msg["result"].is_null()) {
3683 gotSubscribeAck = true;
3684 LogPrint("worker", "[pool->worker] subscribe ack received\n");
3685 SetParticipantMiningStatus("subscribed; waiting for authorize ack");
3686 }
3687
3688 // -- Response to our authorize (id=2) --
3689 else if (msg.contains("id") && msg["id"].is_number_integer()
3690 && msg["id"].get<int>() == 2
3691 && msg.contains("result")) {
3692 bool ok = msg["result"].is_boolean() && msg["result"].get<bool>();
3693 authWaitStart = GetTime();
3694 if (ok) {
3695 gotAuthorizeAck = true;
3696 LogPrint("worker", "[pool->worker] authorize OK -- waiting for job\n");
3697 SetParticipantMiningStatus("authorized; waiting for job");
3698 } else {
3699 std::string reason = msg.value("error", json("unspecified")).is_string()
3700 ? msg["error"].get<std::string>() : "unspecified";
3701 LogPrint("worker", "[pool->worker] authorize REJECTED: %s\n",
3702 reason.c_str());
3703 SetParticipantMiningStatus("authorization rejected");
3704 // Don't break -- pool might still send a job (some pools
3705 // reject bad addresses but still send work)
3706 }
3707 }
3708
3709 // -- Share submission response --
3710 else if (msg.contains("id") && msg["id"].is_number_integer()) {
3711 int rid = msg["id"].get<int>();
3712 if (pendingSubmitIds.erase(rid) > 0) {
3713 bool accepted = msg.contains("result")
3714 && msg["result"].is_boolean()
3715 && msg["result"].get<bool>();
3716 if (accepted) {
3717 gParticipantSharesAccepted.fetch_add(1);
3718 sessionSharesAccepted++;
3719 LogPrint("worker", "[pool->worker] share id=%d ACCEPTED\n", rid);
3720 SetParticipantMiningStatus("share accepted");
3721 } else {
3722 std::string reason = (msg.contains("error")
3723 && msg["error"].is_string())
3724 ? msg["error"].get<std::string>() : "unspecified";
3725 LogPrint("worker", "[pool->worker] share id=%d REJECTED: %s\n",
3726 rid, reason.c_str());
3727 SetParticipantMiningStatus("share rejected: " + reason);
3728 }
3729 }
3730 }
3731
3732 // -- Server notification --
3733 else {
3734 std::string method = msg.value("method", "");
3735
3736 if (method == "mining.notify") {
3737 auto& p = msg["params"];
3738 if (!p.is_array() || p.size() < 4) {
3739 LogPrint("worker", "[pool->worker] malformed mining.notify"
3740 " (params size=%zu)\n", p.is_array() ? p.size() : 0);
3741 } else {
3742 std::string newJobId = p[0].get<std::string>();
3743 auto hdrBytes = FromHexStr(p[1].get<std::string>());
3744 auto tgtBytes = FromHexStr(p[3].get<std::string>());
3745
3746 if (hdrBytes.size() < 80) {
3747 LogPrint("worker", "[pool->worker] mining.notify:"
3748 " header too short (%zu bytes)\n",
3749 hdrBytes.size());
3750 } else if (tgtBytes.size() < 32) {
3751 LogPrint("worker", "[pool->worker] mining.notify:"
3752 " target too short (%zu bytes)\n",
3753 tgtBytes.size());
3754 } else {
3755 jobId = newJobId;
3756 memcpy(header, hdrBytes.data(), 80);
3757 memcpy(&target, tgtBytes.data(), 32);
3758 haveJob = true;
3759 nNonce = 1;
3760 LogPrint("worker", "[pool->worker] new job %s received\n",
3761 jobId.c_str());
3762 SetParticipantMiningStatus("hashing job " + jobId);
3763 }
3764 }
3765 } else if (method == "mining.set_difficulty") {
3766 // Pool adjusts our share difficulty via vardiff.
3767 // Apply it immediately so we start hashing at the new target.
3768 if (msg.contains("params") && msg["params"].is_array()
3769 && msg["params"].size() > 0
3770 && msg["params"][0].is_number()) {
3771 double newDiff = msg["params"][0].get<double>();
3772 if (newDiff > 0.0) {
3773 bool changed = (newDiff != currentDifficulty);
3774 currentDifficulty = newDiff;
3775 LogPrint("worker", "[pool->worker] set_difficulty %.6f%s\n",
3776 newDiff, changed ? " (updated)" : " (initial)");
3777 }
3778 } else {
3779 LogPrint("worker", "[pool->worker] set_difficulty"
3780 " received (no valid params)\n");
3781 }
3782 } else if (!method.empty()) {
3783 LogPrint("worker", "[pool->worker] unknown server method: %s\n",
3784 method.c_str());
3785 }
3786 }
3787 }
3788
3789 if (disc) {
3790 LogPrint("worker", "[worker] pool closed the connection"
3791 " (gotSubscribeAck=%d gotAuthorizeAck=%d haveJob=%d)\n",
3792 gotSubscribeAck, gotAuthorizeAck, haveJob);
3793 break;
3794 }
3795 }
3796 }
3797
3798 // -- Stuck watchdog: authorized but no job arriving --
3799 if (gotAuthorizeAck && !haveJob && authWaitStart > 0) {
3800 int64 waited = GetTime() - authWaitStart;
3801 if (waited > 10 && GetTime() - lastStuckLog >= 15) {
3802 LogPrint("worker", "[worker] authorized but no job after %llds"
3803 " -- pool tunnel is live, waiting on mining.notify\n",
3804 (long long)waited);
3805 lastStuckLog = GetTime();
3806 }
3807 if (waited > STUCK_NO_JOB_TIMEOUT_SECS) {
3808 LogPrint("worker", "[worker] no job received after %llds -- disconnecting"
3809 " and reconnecting\n", (long long)STUCK_NO_JOB_TIMEOUT_SECS);
3810 SetParticipantMiningStatus("timeout waiting for job; reconnecting");
3811 break;
3812 }
3813 }
3814
3815 if (!haveJob) { Sleep(100); continue; }
3816
3817 // -- Hash one nonce --
3818 memcpy(header+76, &nNonce, 4);
3819 uint256 hash = RandomXHashWithVM(rxvm, header, 80);
3820 hashesSinceSample++;
3821 gParticipantHashes.fetch_add(1);
3822 if ((hashesSinceSample & 0x3ff) == 0)
3823 UpdateParticipantHashRate(hashesSinceSample, sampleStart);
3824
3825 if (hash <= target) {
3826 LogPrint("worker", "[worker] share found! nonce=%u job=%s difficulty=%.4f\n",
3827 nNonce, jobId.c_str(), currentDifficulty);
3828 SetParticipantMiningStatus("share found; submitting");
3829 int submitId = msgId++;
3830 pendingSubmitIds.insert(submitId);
3831 gParticipantSharesSent.fetch_add(1);
3832 sessionSharesSent++;
3833 json submit = {{"id",submitId},{"method","mining.submit"},
3834 {"params",json::array({username, jobId, ToHexStr(&nNonce,4)})}};
3835 if (!StratumSendLine(s, submit)) {
3836 LogPrint("worker", "[worker] share submit send FAILED"
3837 " -- pool connection lost\n");
3838 break;
3839 }
3840 }
3841
3842 nNonce++;
3843 if (nNonce == 0) {
3844 LogPrint("worker", "[worker] nonce space exhausted for job %s"
3845 " -- waiting for new job\n", jobId.c_str());
3846 haveJob = false;
3847 }
3848 }
3849
3850 // ------------------------------------------------------------------
3851 // Cleanup
3852 // ------------------------------------------------------------------
3853 RandomXDestroyMinerVM(rxvm);
3854 closesocket(s);
3855 UpdateParticipantHashRate(hashesSinceSample, sampleStart);
3856 SetParticipantMiningStatus("disconnected");
3857 LogPrint("worker", "[worker] disconnected from pool"
3858 " (hashes this session: %llu, shares sent: %llu, accepted: %llu)\n",
3859 (unsigned long long)hashesSinceSample,
3860 (unsigned long long)sessionSharesSent,
3861 (unsigned long long)sessionSharesAccepted);
3862 return true;
3863}
3864
3865bool BitcoinMiner(int nThreadId)
3866{
3867 // Relay mode: never mines, just relays/syncs. (Shouldn't normally get here
3868 // since the GUI hides Start Mining for Relay, but guard it regardless.)
3869 if (nMineMode == MINE_RELAY)
3870 return true;
3871
3872 // Participant mode: connect to external pool instead of mining solo/operator
3873 if (nMineMode == MINE_PARTICIPANT)
3874 {
3875 while (fGenerateBitcoins && nMineMode == MINE_PARTICIPANT && !fShutdown) {
3876 PoolParticipantMiner();
3877 if (fGenerateBitcoins && nMineMode == MINE_PARTICIPANT && !fShutdown) {
3878 LogPrint("worker", "PoolParticipantMiner: reconnecting in 10s\n");
3879 for (int i = 0; i < 10 && !fShutdown; i++) Sleep(1000);
3880 }
3881 }
3882 return true;
3883 }
3884
3885 // Operator mode only serves the pool; it does not mine solo.
3886 if (nMineMode == MINE_OPERATOR)
3887 return true;
3888
3889 LogPrint("net", "BitcoinMiner started\n");
3890 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
3891
3892 // Build the fast (~2 GB dataset) RandomX mode once, up front, so we're
3893 // not stuck mining in the much slower light/cache-only mode forever.
3894 if (!RandomXFastReady()) {
3895 unsigned int nThreads = std::thread::hardware_concurrency();
3896 RandomXInitDataset(nThreads > 0 ? (int)nThreads : 1);
3897 }
3898
3899 // Drawn from the pool, so it is already in wallet.dat before a single hash
3900 // is computed. The old code generated a key here and only saved it if this
3901 // thread happened to win a block, which meant a backup taken while mining
3902 // could not spend what the very next block paid.
3903 vector<unsigned char> vchPubKey = GetKeyFromPool();
3904 if (vchPubKey.empty())
3905 {
3906 printf("BitcoinMiner: no wallet key available for coinbase; mining stopped\n");
3907 return false;
3908 }
3909 CBigNum bnExtraNonce = 0;
3910 while (fGenerateBitcoins)
3911 {
3912 Sleep(50);
3913 // Return instead of _endthread()ing. With more than one miner thread the
3914 // bookkeeping in ThreadBitcoinMiner has to run on the way out, and
3915 // _endthread() does not unwind on Windows, so a normal return is the
3916 // only exit that works the same on both platforms.
3917 if (fShutdown)
3918 return true;
3919 while (vNodes.empty() && !fSoloMineTest)
3920 {
3921 Sleep(1000);
3922 if (fShutdown)
3923 return true;
3924 }
3925
3926 unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
3927 CBlockIndex* pindexPrev = pindexBest;
3928 unsigned int nBits = GetNextWorkRequired(pindexPrev);
3929
3930
3931 //
3932 // Create coinbase tx
3933 //
3934 CTransaction txNew;
3935 txNew.vin.resize(1);
3936 txNew.vin[0].prevout.SetNull();
3937 // The height comes first and is what makes this transaction unique.
3938 //
3939 // Without it nothing in the coinbase belongs to the block: it is a
3940 // function of the difficulty, a counter, and the payout key. nBits
3941 // holds still for long stretches and bnExtraNonce is a local that
3942 // restarts at zero whenever the miner does, so the same combination
3943 // comes round again and produces a byte-identical transaction with the
3944 // same txid. Two blocks then name the same transaction and the index
3945 // keeps whichever arrived last, which silently destroys the outputs of
3946 // the first. It has already happened twice on this chain, at heights
3947 // 859 and 860 (#58).
3948 //
3949 // Two coinbases at different heights can now never be identical, no
3950 // matter what the counter or the key do.
3951 //
3952 // Nothing validates coinbase content, so this changes only what we
3953 // produce -- nodes that do not upgrade accept these blocks unchanged.
3954 // Requiring the height is a separate, coordinated step.
3955 txNew.vin[0].scriptSig << (pindexPrev ? pindexPrev->nHeight + 1 : 0) << nBits << ++bnExtraNonce;
3956 txNew.vout.resize(1);
3957 // Always pay coinbase to own wallet key. In operator mode, the pool
3958 // server distributes shares to miners via SendMoney() after each block.
3959 txNew.vout[0].scriptPubKey << vchPubKey << OP_CHECKSIG;
3960
3961
3962 //
3963 // Create new block
3964 //
3965 auto_ptr<CBlock> pblock(new CBlock());
3966 if (!pblock.get())
3967 return false;
3968
3969 // Add our coinbase tx as first transaction
3970 pblock->vtx.push_back(txNew);
3971
3972 // Collect the latest transactions into the block
3973 int64 nFees = 0;
3974 CRITICAL_BLOCK(cs_main)
3975 CRITICAL_BLOCK(cs_mapTransactions)
3976 {
3977 CTxDB txdb("r");
3978 map<uint256, CTxIndex> mapTestPool;
3979 vector<char> vfAlreadyAdded(mapTransactions.size());
3980 bool fFoundSomething = true;
3981 unsigned int nBlockSize = 0;
3982 while (fFoundSomething && nBlockSize < MAX_SIZE/2)
3983 {
3984 fFoundSomething = false;
3985 unsigned int n = 0;
3986 for (map<uint256, CTransaction>::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi, ++n)
3987 {
3988 if (vfAlreadyAdded[n])
3989 continue;
3990 CTransaction& tx = (*mi).second;
3991 if (tx.IsCoinBase() || !tx.IsFinal())
3992 continue;
3993
3994 // Transaction fee requirements, mainly only needed for flood control
3995 // Under 10K (about 80 inputs) is free for first 100 transactions
3996 // Base rate is 0.01 per KB
3997 int64 nMinFee = tx.GetMinFee(pblock->vtx.size() < 100);
3998
3999 map<uint256, CTxIndex> mapTestPoolTmp(mapTestPool);
4000 if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), 0, nFees, false, true, nMinFee))
4001 continue;
4002 swap(mapTestPool, mapTestPoolTmp);
4003
4004 pblock->vtx.push_back(tx);
4005 nBlockSize += ::GetSerializeSize(tx, SER_NETWORK);
4006 vfAlreadyAdded[n] = true;
4007 fFoundSomething = true;
4008 }
4009 }
4010 }
4011 pblock->nBits = nBits;
4012 pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(nBestHeight + 1, nFees);
4013 if (LogAcceptsCategory("net")) printf("\n\nRunning BitcoinMiner with %d transactions in block\n", (int)pblock->vtx.size());
4014
4015
4016 //
4017 // Prepare the block header
4018 //
4019 pblock->hashPrevBlock = (pindexPrev ? pindexPrev->GetBlockHash() : 0);
4020 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
4021 pblock->nTime = max((pindexPrev ? pindexPrev->GetMedianTimePast()+1 : 0), GetAdjustedTime());
4022 pblock->nBits = nBits;
4023 pblock->nNonce = 1;
4024
4025
4026 //
4027 // Search (memory-hard RandomX PoW) -- each thread uses its own VM
4028 //
4029 void* rxvm = RandomXCreateMinerVM();
4030 if (!rxvm)
4031 {
4032 LogPrint("net", "BitcoinMiner: failed to create RandomX VM\n");
4033 Sleep(1000);
4034 continue;
4035 }
4036 // The thread number is in the line on purpose: every miner would
4037 // otherwise print the same text, and the dedup filter would fold them
4038 // into one, leaving no way to tell four threads from one.
4039 LogPrint("net", "BitcoinMiner: thread %d hashing with RandomX (%s)\n",
4040 nThreadId, RandomXFastReady() ? "fast 2GB" : "light 256MB");
4041
4042 unsigned int nStart = GetTime();
4043 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
4044 loop
4045 {
4046 uint256 hash = RandomXHashWithVM(rxvm, (const void*)BEGIN(pblock->nVersion),
4047 END(pblock->nNonce) - BEGIN(pblock->nVersion));
4048
4049 if (hash <= hashTarget)
4050 {
4051 //// debug print
4052 if (LogAcceptsCategory("net")) printf("BitcoinMiner:\n");
4053 if (LogAcceptsCategory("net")) printf("RandomX proof-of-work found \n powhash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
4054 if (LogAcceptsCategory("net")) pblock->print();
4055
4056 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
4057 CRITICAL_BLOCK(cs_main)
4058 {
4059 // Is the parent we solved for still the tip?
4060 //
4061 // The loop only tests this every 256 hashes, and never
4062 // again once a solution turns up. So a thread that found
4063 // one just after somebody else extended the chain would
4064 // submit a block built on a parent that is no longer the
4065 // tip -- a block born orphaned, at a height already taken.
4066 //
4067 // Every miner thread on this machine works from the same
4068 // pindexPrev, so the moment one of them wins, all the
4069 // others are hashing a doomed template until their next
4070 // checkpoint. On a 32-core box that is thirty threads with
4071 // a standing chance of producing a guaranteed orphan, and
4072 // it is why a healthy miner's wallet filled up with them.
4073 if (pindexPrev != pindexBest)
4074 {
4075 LogPrint("net", "BitcoinMiner: thread %d solved for a parent that is no longer the tip, discarding\n",
4076 nThreadId);
4077 }
4078 else
4079 {
4080 // The key that just got paid was written to wallet.dat
4081 // when it left the pool, so there is nothing to save
4082 // here -- only a fresh one to take for the next block.
4083 // Two threads never draw the same key: the pool hands
4084 // them out one at a time under cs_keyPool, which is
4085 // what keeps concurrent coinbases distinct (#58).
4086 vchPubKey = GetKeyFromPool();
4087 if (vchPubKey.empty())
4088 {
4089 printf("BitcoinMiner: no replacement wallet key available; mining stopped\n");
4090 fGenerateBitcoins = false;
4091 }
4092
4093 // Process this block the same as if we had received it from another node
4094 if (!ProcessBlock(NULL, pblock.release()))
4095 LogPrint("net", "ERROR in BitcoinMiner, ProcessBlock, block not accepted\n");
4096 }
4097 }
4098 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
4099
4100 Sleep(500);
4101 break;
4102 }
4103
4104 // Check stop conditions periodically (RandomX is slow, so every
4105 // ~256 hashes is already plenty of time)
4106 if ((++pblock->nNonce & 0xff) == 0)
4107 {
4108 if (fShutdown)
4109 break; // falls through to RandomXDestroyMinerVM below
4110 if (pblock->nNonce == 0)
4111 break;
4112 if (pindexPrev != pindexBest)
4113 break;
4114 if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)
4115 break;
4116 if (!fGenerateBitcoins)
4117 break;
4118 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
4119 }
4120 }
4121 RandomXDestroyMinerVM(rxvm);
4122 if (fShutdown)
4123 break;
4124 }
4125
4126 return true;
4127}
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146//////////////////////////////////////////////////////////////////////////////
4147//
4148// Actions
4149//
4150
4151
4152WalletRecoveryAudit GetWalletRecoveryAudit()
4153{
4154 WalletRecoveryAudit audit;
4155 set<vector<unsigned char> > setDerivedPubKeys;
4156
4157 CRITICAL_BLOCK(cs_keyPool)
4158 {
4159 audit.fHaveSeed = HaveHDSeed();
4160 audit.nSchema = nHDKeySchema;
4161 audit.nDerivedKnown = nHDNext;
4162 audit.nReceiveNext = nHDReceiveNext;
4163 audit.nChangeNext = nHDChangeNext;
4164 audit.nCoinType = nHDCoinType;
4165 if (nHDKeySchema == HD_SCHEMA_BIP44)
4166 audit.nDerivedKnown = nHDReceiveNext + nHDChangeNext + nHDNext;
4167 if (audit.fHaveSeed)
4168 {
4169 string strError;
4170 unsigned int nReceiveDepth = nHDKeySchema == HD_SCHEMA_BIP44
4171 ? nHDReceiveNext
4172 : nHDNext;
4173 for (unsigned int i = 0; i < nReceiveDepth; i++)
4174 {
4175 CKey key;
4176 if (!DeriveHDKey(i, key, strError))
4177 {
4178 audit.fDeriveComplete = false;
4179 audit.strDeriveError = strprintf("derivation failed at index %u: %s",
4180 i, strError.c_str());
4181 break;
4182 }
4183 setDerivedPubKeys.insert(key.GetPubKey());
4184 }
4185 if (nHDKeySchema == HD_SCHEMA_BIP44)
4186 {
4187 int nSavedSchema = nHDKeySchema;
4188 for (unsigned int i = 0; i < nHDChangeNext; i++)
4189 {
4190 CKey key;
4191 if (!DeriveHDChangeKey(i, key, strError))
4192 {
4193 audit.fDeriveComplete = false;
4194 audit.strDeriveError = strprintf("change derivation failed at index %u: %s",
4195 i, strError.c_str());
4196 break;
4197 }
4198 setDerivedPubKeys.insert(key.GetPubKey());
4199 }
4200 nHDKeySchema = HD_SCHEMA_LEGACY;
4201 for (unsigned int i = 0; i < nHDNext; i++)
4202 {
4203 CKey key;
4204 if (!DeriveHDKey(i, key, strError))
4205 {
4206 audit.fDeriveComplete = false;
4207 audit.strDeriveError = strprintf("legacy compatibility derivation failed at index %u: %s",
4208 i, strError.c_str());
4209 break;
4210 }
4211 setDerivedPubKeys.insert(key.GetPubKey());
4212 }
4213 nHDKeySchema = nSavedSchema;
4214 }
4215 }
4216 }
4217
4218 CRITICAL_BLOCK(cs_mapWallet)
4219 {
4220 for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4221 {
4222 CWalletTx& wtx = (*it).second;
4223 if (!wtx.IsFinal() || wtx.fSpent)
4224 continue;
4225 bool fImmature = wtx.IsCoinBase() && wtx.GetBlocksToMaturity() > 0;
4226
4227 bool fTxRecoverable = false;
4228 bool fTxLegacy = false;
4229 for (int i = 0; i < (int)wtx.vout.size(); i++)
4230 {
4231 const CTxOut& txout = wtx.vout[i];
4232 if (!txout.IsMine())
4233 continue;
4234
4235 vector<unsigned char> vchPubKey;
4236 bool fRecoverable = false;
4237 if (audit.fHaveSeed && ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
4238 fRecoverable = setDerivedPubKeys.count(vchPubKey) > 0;
4239
4240 if (fRecoverable)
4241 {
4242 if (fImmature)
4243 audit.nRecoverableImmatureCredit += txout.nValue;
4244 else
4245 audit.nRecoverableCredit += txout.nValue;
4246 fTxRecoverable = true;
4247 }
4248 else
4249 {
4250 if (fImmature)
4251 audit.nLegacyImmatureCredit += txout.nValue;
4252 else
4253 audit.nLegacyCredit += txout.nValue;
4254 fTxLegacy = true;
4255 }
4256 }
4257
4258 if (fTxRecoverable)
4259 {
4260 if (fImmature)
4261 audit.nRecoverableImmatureTx++;
4262 else
4263 audit.nRecoverableTx++;
4264 }
4265 if (fTxLegacy)
4266 {
4267 if (fImmature)
4268 audit.nLegacyImmatureTx++;
4269 else
4270 audit.nLegacyTx++;
4271 }
4272 }
4273 }
4274
4275 return audit;
4276}
4277
4278int64 GetBalance()
4279{
4280 int64 nStart, nEnd;
4281 QueryPerformanceCounter((LARGE_INTEGER*)&nStart);
4282
4283 int64 nTotal = 0;
4284 CRITICAL_BLOCK(cs_mapWallet)
4285 {
4286 for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4287 {
4288 CWalletTx* pcoin = &(*it).second;
4289 if (!pcoin->IsFinal() || pcoin->fSpent)
4290 continue;
4291 nTotal += pcoin->GetCredit();
4292 }
4293 }
4294
4295 QueryPerformanceCounter((LARGE_INTEGER*)&nEnd);
4296 ///printf(" GetBalance() time = %16lld\n", nEnd - nStart);
4297 return nTotal;
4298}
4299
4300
4301
4302bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
4303{
4304 setCoinsRet.clear();
4305
4306 // List of values less than target
4307 int64 nLowestLarger = _I64_MAX;
4308 CWalletTx* pcoinLowestLarger = NULL;
4309 vector<pair<int64, CWalletTx*> > vValue;
4310 int64 nTotalLower = 0;
4311
4312 CRITICAL_BLOCK(cs_mapWallet)
4313 {
4314 for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4315 {
4316 CWalletTx* pcoin = &(*it).second;
4317 if (!pcoin->IsFinal() || pcoin->fSpent)
4318 continue;
4319 int64 n = pcoin->GetCredit();
4320 if (n <= 0)
4321 continue;
4322 if (n < nTargetValue)
4323 {
4324 vValue.push_back(make_pair(n, pcoin));
4325 nTotalLower += n;
4326 }
4327 else if (n == nTargetValue)
4328 {
4329 setCoinsRet.insert(pcoin);
4330 return true;
4331 }
4332 else if (n < nLowestLarger)
4333 {
4334 nLowestLarger = n;
4335 pcoinLowestLarger = pcoin;
4336 }
4337 }
4338 }
4339
4340 if (nTotalLower < nTargetValue)
4341 {
4342 if (pcoinLowestLarger == NULL)
4343 return false;
4344 setCoinsRet.insert(pcoinLowestLarger);
4345 return true;
4346 }
4347
4348 // Solve subset sum by stochastic approximation
4349 sort(vValue.rbegin(), vValue.rend());
4350 vector<char> vfIncluded;
4351 vector<char> vfBest(vValue.size(), true);
4352 int64 nBest = nTotalLower;
4353
4354 for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)
4355 {
4356 vfIncluded.assign(vValue.size(), false);
4357 int64 nTotal = 0;
4358 bool fReachedTarget = false;
4359 for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
4360 {
4361 for (int i = 0; i < vValue.size(); i++)
4362 {
4363 if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
4364 {
4365 nTotal += vValue[i].first;
4366 vfIncluded[i] = true;
4367 if (nTotal >= nTargetValue)
4368 {
4369 fReachedTarget = true;
4370 if (nTotal < nBest)
4371 {
4372 nBest = nTotal;
4373 vfBest = vfIncluded;
4374 }
4375 nTotal -= vValue[i].first;
4376 vfIncluded[i] = false;
4377 }
4378 }
4379 }
4380 }
4381 }
4382
4383 // If the next larger is still closer, return it
4384 if (pcoinLowestLarger && nLowestLarger - nTargetValue <= nBest - nTargetValue)
4385 setCoinsRet.insert(pcoinLowestLarger);
4386 else
4387 {
4388 for (int i = 0; i < vValue.size(); i++)
4389 if (vfBest[i])
4390 setCoinsRet.insert(vValue[i].second);
4391
4392 //// debug print
4393 if (LogAcceptsCategory("net")) printf("SelectCoins() best subset: ");
4394 for (int i = 0; i < vValue.size(); i++)
4395 if (vfBest[i])
4396 if (LogAcceptsCategory("net")) printf("%s ", FormatMoney(vValue[i].first).c_str());
4397 if (LogAcceptsCategory("net")) printf("total %s\n", FormatMoney(nBest).c_str());
4398 }
4399
4400 return true;
4401}
4402
4403
4404
4405
4406bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, int64& nFeeRequiredRet)
4407{
4408 nFeeRequiredRet = 0;
4409 CRITICAL_BLOCK(cs_main)
4410 {
4411 // txdb must be opened before the mapWallet lock
4412 CTxDB txdb("r");
4413 CRITICAL_BLOCK(cs_mapWallet)
4414 {
4415 int64 nFee = nTransactionFee;
4416 loop
4417 {
4418 wtxNew.vin.clear();
4419 wtxNew.vout.clear();
4420 if (nValue < 0)
4421 return false;
4422
4423 // nValue is the amount the payee asked for and must stay that.
4424 //
4425 // This used to read "nValueOut = nValue; nValue += nFee;", and
4426 // both lines are inside the retry loop. The first pass was
4427 // fine. But when the fee turned out to be too low the loop
4428 // starts over, and on the second pass nValueOut is read from
4429 // an nValue that already had the fee added -- so the payee is
4430 // sent the amount plus the fee, and it compounds on every
4431 // further retry, with the sender covering it.
4432 //
4433 // The retry fires whenever GetMinFee exceeds the fee we
4434 // guessed, which for this fee schedule means any transaction
4435 // over 10 KB: a wallet paying from many small inputs. Bitcoin
4436 // fixed this in 107d9e288.
4437 int64 nTotalValue = nValue + nFee;
4438
4439 // Choose coins to use
4440 set<CWalletTx*> setCoins;
4441 if (!SelectCoins(nTotalValue, setCoins))
4442 return false;
4443 int64 nValueIn = 0;
4444 foreach(CWalletTx* pcoin, setCoins)
4445 nValueIn += pcoin->GetCredit();
4446
4447 // Fill vout[0] to the payee
4448 wtxNew.vout.push_back(CTxOut(nValue, scriptPubKey));
4449
4450 // Fill vout[1] back to self with any change
4451 if (nValueIn > nTotalValue)
4452 {
4453 vector<unsigned char> vchPubKey;
4454 if (HaveHDSeed())
4455 {
4456 string strError;
4457 if (!DeriveNextHDChangeKey(vchPubKey, strError))
4458 {
4459 printf("CreateTransaction() : could not derive a phrase-backed change key: %s\n",
4460 strError.c_str());
4461 return false;
4462 }
4463 }
4464 else
4465 {
4466 // Legacy wallets have no deterministic seed. Preserve
4467 // the 0.1.0 behaviour for them: return change to a key
4468 // already proven to belong to this wallet.
4469 CTransaction& txFirst = *(*setCoins.begin());
4470 foreach(const CTxOut& txout, txFirst.vout)
4471 if (txout.IsMine())
4472 if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
4473 break;
4474 }
4475 if (vchPubKey.empty())
4476 return false;
4477
4478 // Fill vout[1] to ourself
4479 CScript scriptPubKey;
4480 scriptPubKey << vchPubKey << OP_CHECKSIG;
4481 wtxNew.vout.push_back(CTxOut(nValueIn - nTotalValue, scriptPubKey));
4482 }
4483
4484 // Fill vin
4485 foreach(CWalletTx* pcoin, setCoins)
4486 for (int nOut = 0; nOut < pcoin->vout.size(); nOut++)
4487 if (pcoin->vout[nOut].IsMine())
4488 wtxNew.vin.push_back(CTxIn(pcoin->GetHash(), nOut));
4489
4490 // Sign
4491 int nIn = 0;
4492 foreach(CWalletTx* pcoin, setCoins)
4493 for (int nOut = 0; nOut < pcoin->vout.size(); nOut++)
4494 if (pcoin->vout[nOut].IsMine())
4495 SignSignature(*pcoin, wtxNew, nIn++);
4496
4497 // Check that enough fee is included
4498 if (nFee < wtxNew.GetMinFee(true))
4499 {
4500 nFee = nFeeRequiredRet = wtxNew.GetMinFee(true);
4501 continue;
4502 }
4503
4504 // Fill vtxPrev by copying from previous transactions vtxPrev
4505 wtxNew.AddSupportingTransactions(txdb);
4506 wtxNew.fTimeReceivedIsTxTime = true;
4507
4508 break;
4509 }
4510 }
4511 }
4512 return true;
4513}
4514
4515// Undo what CommitTransactionSpent did: unmark the inputs it marked spent
4516// and erase the half-committed wallet entry. Used when a transaction is
4517// accepted into the wallet but then rejected by the mempool/chain, so we
4518// don't end up with a wallet that thinks money is spent that never left.
4519void RollbackTransactionSpent(const CWalletTx& wtxNew)
4520{
4521 CRITICAL_BLOCK(cs_main)
4522 CRITICAL_BLOCK(cs_mapWallet)
4523 {
4524 set<CWalletTx*> setCoins;
4525 foreach(const CTxIn& txin, wtxNew.vin)
4526 {
4527 map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
4528 if (mi != mapWallet.end())
4529 setCoins.insert(&mi->second);
4530 }
4531 foreach(CWalletTx* pcoin, setCoins)
4532 {
4533 pcoin->fSpent = false;
4534 pcoin->WriteToDisk();
4535 vWalletUpdated.push_back(make_pair(pcoin->GetHash(), false));
4536 }
4537
4538 EraseFromWallet(wtxNew.GetHash());
4539 }
4540 MainFrameRepaint();
4541}
4542
4543// Call after CreateTransaction unless you want to abort
4544bool CommitTransactionSpent(const CWalletTx& wtxNew)
4545{
4546 CRITICAL_BLOCK(cs_main)
4547 CRITICAL_BLOCK(cs_mapWallet)
4548 {
4549 //// todo: make this transactional, never want to add a transaction
4550 //// without marking spent transactions
4551
4552 // Add tx to wallet, because if it has change it's also ours,
4553 // otherwise just for transaction history.
4554 AddToWallet(wtxNew);
4555
4556 // Mark old coins as spent
4557 set<CWalletTx*> setCoins;
4558 foreach(const CTxIn& txin, wtxNew.vin)
4559 setCoins.insert(&mapWallet[txin.prevout.hash]);
4560 foreach(CWalletTx* pcoin, setCoins)
4561 {
4562 pcoin->fSpent = true;
4563 pcoin->WriteToDisk();
4564 vWalletUpdated.push_back(make_pair(pcoin->GetHash(), false));
4565 }
4566 }
4567 MainFrameRepaint();
4568 return true;
4569}
4570
4571
4572
4573
4574bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
4575{
4576 CRITICAL_BLOCK(cs_main)
4577 {
4578 int64 nFeeRequired;
4579 if (!CreateTransaction(scriptPubKey, nValue, wtxNew, nFeeRequired))
4580 {
4581 string strError;
4582 if (nValue + nFeeRequired > GetBalance())
4583 strError = strprintf("Error: This is an oversized transaction that requires a transaction fee of %s ", FormatMoney(nFeeRequired).c_str());
4584 else
4585 strError = "Error: Transaction creation failed ";
4586 return error("SendMoney() : %s\n", strError.c_str());
4587 }
4588 if (!CommitTransactionSpent(wtxNew))
4589 {
4590 return error("SendMoney() : Error finalizing transaction");
4591 }
4592
4593 if (LogAcceptsCategory("net")) printf("SendMoney: %s\n", wtxNew.GetHash().ToString().substr(0,6).c_str());
4594
4595 // Broadcast
4596 if (!wtxNew.AcceptTransaction())
4597 {
4598 // The transaction was already signed and committed to the wallet
4599 // above, but the chain/mempool just rejected it (e.g. a raced
4600 // input already spent by another transaction). Unwind the
4601 // wallet state we just wrote instead of crashing the app.
4602 RollbackTransactionSpent(wtxNew);
4603 return error("SendMoney() : wtxNew.AcceptTransaction() failed");
4604 }
4605 wtxNew.RelayWalletTransaction();
4606 }
4607 MainFrameRepaint();
4608 return true;
4609}