Bitcoin Forum
September 08, 2024, 07:44:37 AM *
News: Latest Bitcoin Core release: 27.1 [Torrent]
 
  Home Help Search Login Register More  
  Show Posts
Pages: [1]
1  Alternate cryptocurrencies / Altcoin Discussion / You don't have to download the pre-fork blockchain again for each Bitcoin fork! on: January 25, 2018, 04:06:13 AM
If you are annoyed by having to download 150 GB of the blockchain data over and over again for each Bitcoin fork despite the fact that all the pre-fork blocks are naturally identical to each fork as well as to the original Bitcoin blockchain, there might be a solution for you. It might be possible to import the pre-fork blocks from the original Bitcoin block files or even from another fork's block files.

The original idea comes from here (which in turn is basically just a duplicated LoadExternalBlockFile() with a few tweaks), I merely made it universal and added command-line options. Unfortunately since most forks logically didn't use the exactly same revision of the original Bitcoin source code as their starting point there is no way how to make one single universal patch for all of them. From my experience of patching nearly 15 different forks I determined 2 different patch sets that (one or the other) after some little adjusting fit to all forks I have tried so far. If you compare the patches and look at your particular source code you will easily see which patch you should use for your particular fork, but either way it will most probably still need some (very little and very trivial) manual work. I will not help you with that but you can ask for a particular fork patch and if I already patched that fork I will just publish it.

Patchset 1:
Code:
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -361,7 +361,16 @@ std::string HelpMessage(HelpMessageMode mode)
     strUsage += HelpMessageOpt("-dbcache=<n>", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache));
     if (showDebug)
         strUsage += HelpMessageOpt("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER));
-    strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file on startup"));
+    strUsage += HelpMessageOpt("-loadblock=<dir>", _("Imports blocks from external blk000??.dat file(s) from the specified directory on startup"));
+    strUsage += HelpMessageOpt("-loadblockfirst=<n>", _("The number of the first blk000??.dat file to import blocks from (default: 0)"));
+    strUsage += HelpMessageOpt("-loadblocklast=<n>", _("The number of the last blk000??.dat file to import blocks from (default: 0)"));
+    strUsage += HelpMessageOpt("-importblocksbelow=<n>", _("Import only blocks below <n> from external file(s)"));
+    strUsage += HelpMessageOpt("-ignorecheckqueuefailed", _("Ignore 'ConnectBlock(): CheckQueue failed' error; use with extreme caution!"));
+    strUsage += HelpMessageOpt("-messagestart0=<hex>", strprintf("Magic byte 0 for external file(s) import (default: 0xf9)"));
+    strUsage += HelpMessageOpt("-messagestart1=<hex>", strprintf("Magic byte 1 for external file(s) import (default: 0xbe)"));
+    strUsage += HelpMessageOpt("-messagestart2=<hex>", strprintf("Magic byte 2 for external file(s) import (default: 0xb4)"));
+    strUsage += HelpMessageOpt("-messagestart3=<hex>", strprintf("Magic byte 3 for external file(s) import (default: 0xd9)"));
+    strUsage += HelpMessageOpt("-logwriteblockok", _("Log each successful block write"));
     strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS));
     strUsage += HelpMessageOpt("-maxmempool=<n>", strprintf(_("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE));
     strUsage += HelpMessageOpt("-mempoolexpiry=<n>", strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY));
@@ -628,6 +637,7 @@ void CleanupBlockRevFiles()
     }
 }

+extern bool LoadExternalBlockFileX(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp);
 void ThreadImport(std::vector<fs::path> vImportFiles)
 {
     const CChainParams& chainparams = Params();
@@ -672,13 +682,26 @@ void ThreadImport(std::vector<fs::path> vImportFiles)
     }

     // -loadblock=
+    unsigned char btcMagic[4];
+    btcMagic[0] = 0xf9; const std::string magic0 = gArgs.GetArg("-messagestart0", ""); if (IsHexNumber(magic0)) btcMagic[0] = (unsigned char)strtoul(magic0.c_str(), NULL, 16);
+    btcMagic[1] = 0xbe; const std::string magic1 = gArgs.GetArg("-messagestart1", ""); if (IsHexNumber(magic1)) btcMagic[1] = (unsigned char)strtoul(magic1.c_str(), NULL, 16);
+    btcMagic[2] = 0xb4; const std::string magic2 = gArgs.GetArg("-messagestart2", ""); if (IsHexNumber(magic2)) btcMagic[2] = (unsigned char)strtoul(magic2.c_str(), NULL, 16);
+    btcMagic[3] = 0xd9; const std::string magic3 = gArgs.GetArg("-messagestart3", ""); if (IsHexNumber(magic3)) btcMagic[3] = (unsigned char)strtoul(magic3.c_str(), NULL, 16);
     for (const fs::path& path : vImportFiles) {
-        FILE *file = fsbridge::fopen(path, "rb");
-        if (file) {
-            LogPrintf("Importing blocks file %s...\n", path.string());
-            LoadExternalBlockFile(chainparams, file);
-        } else {
-            LogPrintf("Warning: Could not open blocks file %s\n", path.string());
+        int nFile = gArgs.GetArg("-loadblockfirst", 0), nFilelast = gArgs.GetArg("-loadblocklast", 0);
+        while (true) {
+            if (nFile > nFilelast)
+                break;
+            std::string pathstr = strprintf("%s/blk%05u.dat", path.string(), nFile);
+            FILE *file = fsbridge::fopen(pathstr, "rb");
+            if (file) {
+                LogPrintf("Importing magic %#x %#x %#x %#x blocks from file %s...\n", btcMagic[0], btcMagic[1], btcMagic[2], btcMagic[3], pathstr);
+                LoadExternalBlockFileX(chainparams, file, NULL);
+            } else {
+                LogPrintf("Warning: Could not open blocks file %s\n", pathstr);
+            }
+
+            nFile++;
         }
     }

--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1716,6 +1716,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
     assert((pindex->phashBlock == nullptr) ||
            (*pindex->phashBlock == block.GetHash()));
     int64_t nTimeStart = GetTimeMicros();
+    bool ignorecheckqueuefailed = gArgs.GetBoolArg("-ignorecheckqueuefailed", false);

     // Check it again in case a previous version let a bad block in
     if (!CheckBlock(block, state, chainparams.GetConsensus(), !fJustCheck, !fJustCheck))
@@ -1892,8 +1893,12 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
                                block.vtx[0]->GetValueOut(), blockReward),
                                REJECT_INVALID, "bad-cb-amount");

-    if (!control.Wait())
-        return state.DoS(100, error("%s: CheckQueue failed", __func__), REJECT_INVALID, "block-validation-failed");
+    if (!control.Wait()) {
+        if (ignorecheckqueuefailed)
+            LogPrintf("%s: CheckQueue failed\n", __func__);
+        else
+            return state.DoS(100, error("%s: CheckQueue failed", __func__), REJECT_INVALID, "block-validation-failed");
+    }
     int64_t nTime4 = GetTimeMicros(); nTimeVerify += nTime4 - nTime2;
     LogPrint(BCLog::BENCH, "    - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs]\n", nInputs - 1, 0.001 * (nTime4 - nTime2), nInputs <= 1 ? 0 : 0.001 * (nTime4 - nTime2) / (nInputs-1), nTimeVerify * 0.000001);

@@ -3232,6 +3237,7 @@ static bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidation

     CBlockIndex *pindexDummy = nullptr;
     CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
+    bool logwriteblockok = gArgs.GetBoolArg("-logwriteblockok", false);

     if (!AcceptBlockHeader(block, state, chainparams, &pindex))
         return false;
@@ -3293,9 +3299,12 @@ static bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidation
             blockPos = *dbp;
         if (!FindBlockPos(state, blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != nullptr))
             return error("AcceptBlock(): FindBlockPos failed");
-        if (dbp == nullptr)
+        if (dbp == nullptr) {
             if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart()))
                 AbortNode(state, "Failed to write block");
+            else if (logwriteblockok)
+                LogPrintf("Write block ok\n");
+        }
         if (!ReceivedBlockTransactions(block, state, pindex, blockPos, chainparams.GetConsensus()))
             return error("AcceptBlock(): ReceivedBlockTransactions failed");
     } catch (const std::runtime_error& e) {
@@ -4079,6 +4088,127 @@ bool LoadGenesisBlock(const CChainParams& chainparams)
     return true;
 }

+
+bool LoadExternalBlockFileX(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp)
+{
+    // Map of disk positions for blocks with unknown parent (only used for reindex)
+    static std::multimap<uint256, CDiskBlockPos> mapBlocksUnknownParent;
+    int64_t nStart = GetTimeMillis();
+
+    unsigned char btcMagic[4];
+    btcMagic[0] = 0xf9; const std::string magic0 = gArgs.GetArg("-messagestart0", ""); if (IsHexNumber(magic0)) btcMagic[0] = (unsigned char)strtoul(magic0.c_str(), NULL, 16);
+    btcMagic[1] = 0xbe; const std::string magic1 = gArgs.GetArg("-messagestart1", ""); if (IsHexNumber(magic1)) btcMagic[1] = (unsigned char)strtoul(magic1.c_str(), NULL, 16);
+    btcMagic[2] = 0xb4; const std::string magic2 = gArgs.GetArg("-messagestart2", ""); if (IsHexNumber(magic2)) btcMagic[2] = (unsigned char)strtoul(magic2.c_str(), NULL, 16);
+    btcMagic[3] = 0xd9; const std::string magic3 = gArgs.GetArg("-messagestart3", ""); if (IsHexNumber(magic3)) btcMagic[3] = (unsigned char)strtoul(magic3.c_str(), NULL, 16);
+    int nLoaded = 0, blocknheight = 0, importblocksbelow = gArgs.GetArg("-importblocksbelow", 0);
+    try {
+        // This takes over fileIn and calls fclose() on it in the CBufferedFile destructor
+        CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SERIALIZED_SIZE, MAX_BLOCK_SERIALIZED_SIZE+8, SER_DISK, PROTOCOL_VERSION);
+        uint64_t nRewind = blkdat.GetPos();
+        while (!blkdat.eof()) {
+            boost::this_thread::interruption_point();
+
+            blkdat.SetPos(nRewind);
+            nRewind++; // start one byte further next time, in case of failure
+            blkdat.SetLimit(); // remove former limit
+            unsigned int nSize = 0;
+            try {
+                // locate a header
+                unsigned char buf[CMessageHeader::MESSAGE_START_SIZE];
+                blkdat.FindByte(btcMagic[0]);
+                nRewind = blkdat.GetPos()+1;
+                blkdat >> FLATDATA(buf);
+
+                if (memcmp(buf, btcMagic, CMessageHeader::MESSAGE_START_SIZE))
+                    continue;
+
+                // read size
+                blkdat >> nSize;
+                if (nSize < 80 || nSize > MAX_BLOCK_SERIALIZED_SIZE)
+                    continue;
+            } catch (const std::exception&) {
+                // no valid block header found; don't complain
+                LogPrintf("Import exception\n");
+                break;
+            }
+            try {
+                // read block
+                uint64_t nBlockPos = blkdat.GetPos();
+                if (dbp)
+                    dbp->nPos = nBlockPos;
+                blkdat.SetLimit(nBlockPos + nSize);
+                blkdat.SetPos(nBlockPos);
+                std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
+                CBlock& block = *pblock;
+                //block.new_format = false;
+                blkdat >> block;
+                //block >> blkdat;
+                nRewind = blkdat.GetPos();
+
+                LogPrint(BCLog::REINDEX, "version: %d hash: %s prev: %s\n",
+                            block.nVersion,
+                            block.GetHash().ToString(),
+                            block.hashPrevBlock.ToString());
+
+                // detect out of order blocks, and store them for later
+                uint256 hash = block.GetHash();
+                if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex.find(block.hashPrevBlock) == mapBlockIndex.end()) {
+                    LogPrint(BCLog::REINDEX, "%s: Out of order block %s, parent %s not known\n", __func__, hash.ToString(),
+                            block.hashPrevBlock.ToString());
+                    if (dbp)
+                       mapBlocksUnknownParent.insert(std::make_pair(block.hashPrevBlock, *dbp));
+                    continue;
+                }
+
+                if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) {
+                    LOCK(cs_main);
+                    CValidationState state;
+                    LogPrint(BCLog::REINDEX, "Found prev hash in index\n");
+                    BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
+
+                    if (mi !=  mapBlockIndex.end()) {
+                        assert(mi != mapBlockIndex.end());
+                        const CBlockIndex *pindex = mi->second;
+                        LogPrint(BCLog::REINDEX, "prev height %d\n", pindex->nHeight);
+                        blocknheight = pindex->nHeight +1;
+                    }
+
+                    if (importblocksbelow > 0 && blocknheight >= importblocksbelow)
+                        continue;
+                    if (AcceptBlock(pblock, state, chainparams, nullptr, true, dbp, nullptr)) {
+                        LogPrint(BCLog::REINDEX, "BLOCK ACCEPTEED\n");
+                        nLoaded++;
+                    } else
+                        LogPrint(BCLog::REINDEX, "BLOCK REJECTED\n");
+                    if (state.IsError())
+                        break;
+                } else if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex[hash]->nHeight % 1000 == 0) {
+                    LogPrint(BCLog::REINDEX, "Block Import: already had block %s at height %d\n", hash.ToString(), mapBlockIndex[hash]->nHeight);
+                }
+
+                // Activate the genesis block so normal node progress can continue
+                if (hash == chainparams.GetConsensus().hashGenesisBlock) {
+                    LogPrint(BCLog::REINDEX, "Found Genesis Block\n" );
+                    CValidationState state;
+                    if (!ActivateBestChain(state, chainparams)) {
+                        break;
+                    }
+                }
+
+                NotifyHeaderTip();
+
+            } catch (const std::exception& e) {
+                LogPrintf("%s: Deserialize or I/O error - %s\n", __func__, e.what());
+            }
+        }
+    } catch (const std::runtime_error& e) {
+        AbortNode(std::string("System error: ") + e.what());
+    }
+    if (nLoaded > 0)
+        LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, GetTimeMillis() - nStart);
+    return nLoaded > 0;
+}
+
 bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp)
 {
     // Map of disk positions for blocks with unknown parent (only used for reindex)

Patchset 2:
Code:
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -357,9 +357,16 @@ std::string HelpMessage(HelpMessageMode mode) {
             "-feefilter", strprintf("Tell other nodes to filter invs to us by "
                                     "our mempool min fee (default: %d)",
                                     DEFAULT_FEEFILTER));
-    strUsage += HelpMessageOpt(
-        "-loadblock=<file>",
-        _("Imports blocks from external blk000??.dat file on startup"));
+    strUsage += HelpMessageOpt("-loadblock=<dir>", _("Imports blocks from external blk000??.dat file(s) from the specified directory on startup"));
+    strUsage += HelpMessageOpt("-loadblockfirst=<n>", _("The number of the first blk000??.dat file to import blocks from (default: 0)"));
+    strUsage += HelpMessageOpt("-loadblocklast=<n>", _("The number of the last blk000??.dat file to import blocks from (default: 0)"));
+    strUsage += HelpMessageOpt("-importblocksbelow=<n>", _("Import only blocks below <n> from external file(s)"));
+    strUsage += HelpMessageOpt("-ignorecheckqueuefailed", _("Ignore 'ConnectBlock(): CheckQueue failed' error; use with extreme caution!"));
+    strUsage += HelpMessageOpt("-messagestart0=<hex>", strprintf("Magic byte 0 for external file(s) import (default: 0xf9)"));
+    strUsage += HelpMessageOpt("-messagestart1=<hex>", strprintf("Magic byte 1 for external file(s) import (default: 0xbe)"));
+    strUsage += HelpMessageOpt("-messagestart2=<hex>", strprintf("Magic byte 2 for external file(s) import (default: 0xb4)"));
+    strUsage += HelpMessageOpt("-messagestart3=<hex>", strprintf("Magic byte 3 for external file(s) import (default: 0xd9)"));
+    strUsage += HelpMessageOpt("-logwriteblockok", _("Log each successful block write"));
     strUsage += HelpMessageOpt(
         "-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable "
                                         "transactions in memory (default: %u)"),
@@ -971,6 +978,7 @@ void CleanupBlockRevFiles() {
     }
 }

+extern bool LoadExternalBlockFileX(const Config &config, FILE* fileIn, CDiskBlockPos *dbp);
 void ThreadImport(const Config &config,
                   std::vector<boost::filesystem::path> vImportFiles) {
     RenameThread("bitcoin-loadblk");
@@ -1017,14 +1025,26 @@ void ThreadImport(const Config &config,
         }

         // -loadblock=
+        unsigned char btcMagic[4];
+        btcMagic[0] = 0xf9; const std::string magic0 = GetArg("-messagestart0", ""); if (IsHexNumber(magic0)) btcMagic[0] = (unsigned char)strtoul(magic0.c_str(), NULL, 16);
+        btcMagic[1] = 0xbe; const std::string magic1 = GetArg("-messagestart1", ""); if (IsHexNumber(magic1)) btcMagic[1] = (unsigned char)strtoul(magic1.c_str(), NULL, 16);
+        btcMagic[2] = 0xb4; const std::string magic2 = GetArg("-messagestart2", ""); if (IsHexNumber(magic2)) btcMagic[2] = (unsigned char)strtoul(magic2.c_str(), NULL, 16);
+        btcMagic[3] = 0xd9; const std::string magic3 = GetArg("-messagestart3", ""); if (IsHexNumber(magic3)) btcMagic[3] = (unsigned char)strtoul(magic3.c_str(), NULL, 16);
         for (const boost::filesystem::path &path : vImportFiles) {
-            FILE *file = fopen(path.string().c_str(), "rb");
-            if (file) {
-                LogPrintf("Importing blocks file %s...\n", path.string());
-                LoadExternalBlockFile(config, file);
-            } else {
-                LogPrintf("Warning: Could not open blocks file %s\n",
-                          path.string());
+            int nFile = GetArg("-loadblockfirst", 0), nFilelast = GetArg("-loadblocklast", 0);
+            while (true) {
+                if (nFile > nFilelast)
+                    break;
+                std::string pathstr = strprintf("%s/blk%05u.dat", path.string(), nFile);
+                FILE *file = fopen(pathstr.c_str(), "rb");
+                if (file) {
+                    LogPrintf("Importing magic %#x %#x %#x %#x blocks from file %s...\n", btcMagic[0], btcMagic[1], btcMagic[2], btcMagic[3], pathstr);
+                    LoadExternalBlockFileX(config, file, NULL);
+                } else {
+                    LogPrintf("Warning: Could not open blocks file %s\n", pathstr);
+                }
+
+                nFile++;
             }
         }

--- a/src/utilstrencodings.cpp
+++ b/src/utilstrencodings.cpp
@@ -61,6 +61,19 @@ bool IsHex(const std::string &str) {
     return (str.size() > 0) && (str.size() % 2 == 0);
 }

+bool IsHexNumber(const std::string& str)
+{
+    size_t starting_location = 0;
+    if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') {
+        starting_location = 2;
+    }
+    for (auto c : str.substr(starting_location)) {
+        if (HexDigit(c) < 0) return false;
+    }
+    // Return false for empty string or "0x".
+    return (str.size() > starting_location);
+}
+
 std::vector<uint8_t> ParseHex(const char *psz) {
     // convert hex dump to vector
     std::vector<uint8_t> vch;
--- a/src/utilstrencodings.h
+++ b/src/utilstrencodings.h
@@ -41,6 +41,7 @@ std::vector<uint8_t> ParseHex(const char *psz);
 std::vector<uint8_t> ParseHex(const std::string &str);
 signed char HexDigit(char c);
 bool IsHex(const std::string &str);
+bool IsHexNumber(const std::string& str);
 std::vector<uint8_t> DecodeBase64(const char *p, bool *pfInvalid = nullptr);
 std::string DecodeBase64(const std::string &str);
 std::string EncodeBase64(const uint8_t *pch, size_t len);
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1872,6 +1872,7 @@ static bool ConnectBlock(const Config &config, const CBlock &block,
     AssertLockHeld(cs_main);

     int64_t nTimeStart = GetTimeMicros();
+    bool ignorecheckqueuefailed = GetBoolArg("-ignorecheckqueuefailed", false);

     // Check it again in case a previous version let a bad block in
     if (!CheckBlock(config, block, state, !fJustCheck, !fJustCheck)) {
@@ -2118,8 +2119,10 @@ static bool ConnectBlock(const Config &config, const CBlock &block,
     }

     if (!control.Wait()) {
-        return state.DoS(100, false, REJECT_INVALID, "blk-bad-inputs", false,
-                         "parallel script check failed");
+        if (ignorecheckqueuefailed)
+            LogPrintf("%s: CheckQueue failed\n", __func__);
+        else
+            return state.DoS(100, error("%s: CheckQueue failed", __func__), REJECT_INVALID, "block-validation-failed");
     }

     int64_t nTime4 = GetTimeMicros();
@@ -3622,6 +3625,7 @@ static bool AcceptBlock(const Config &config,

     CBlockIndex *pindexDummy = nullptr;
     CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
+    bool logwriteblockok = GetBoolArg("-logwriteblockok", false);

     if (!AcceptBlockHeader(config, block, state, &pindex)) {
         return false;
@@ -3710,9 +3714,10 @@ static bool AcceptBlock(const Config &config,
             return error("AcceptBlock(): FindBlockPos failed");
         }
         if (dbp == nullptr) {
-            if (!WriteBlockToDisk(block, blockPos, chainparams.DiskMagic())) {
+            if (!WriteBlockToDisk(block, blockPos, chainparams.DiskMagic()))
                 AbortNode(state, "Failed to write block");
-            }
+            else if (logwriteblockok)
+                LogPrintf("Write block ok\n");
         }
         if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) {
             return error("AcceptBlock(): ReceivedBlockTransactions failed");
@@ -4454,6 +4459,127 @@ bool InitBlockIndex(const Config &config) {
     return true;
 }

+bool LoadExternalBlockFileX(const Config &config, FILE* fileIn, CDiskBlockPos *dbp)
+{
+    // Map of disk positions for blocks with unknown parent (only used for reindex)
+    static std::multimap<uint256, CDiskBlockPos> mapBlocksUnknownParent;
+    int64_t nStart = GetTimeMillis();
+    const CChainParams &chainparams = config.GetChainParams();
+
+    unsigned char btcMagic[4];
+    btcMagic[0] = 0xf9; const std::string magic0 = GetArg("-messagestart0", ""); if (IsHexNumber(magic0)) btcMagic[0] = (unsigned char)strtoul(magic0.c_str(), NULL, 16);
+    btcMagic[1] = 0xbe; const std::string magic1 = GetArg("-messagestart1", ""); if (IsHexNumber(magic1)) btcMagic[1] = (unsigned char)strtoul(magic1.c_str(), NULL, 16);
+    btcMagic[2] = 0xb4; const std::string magic2 = GetArg("-messagestart2", ""); if (IsHexNumber(magic2)) btcMagic[2] = (unsigned char)strtoul(magic2.c_str(), NULL, 16);
+    btcMagic[3] = 0xd9; const std::string magic3 = GetArg("-messagestart3", ""); if (IsHexNumber(magic3)) btcMagic[3] = (unsigned char)strtoul(magic3.c_str(), NULL, 16);
+    int nLoaded = 0, blocknheight = 0, importblocksbelow = GetArg("-importblocksbelow", 0);
+    try {
+        // This takes over fileIn and calls fclose() on it in the CBufferedFile destructor
+        CBufferedFile blkdat(fileIn, 2*MAX_TX_SIZE, MAX_TX_SIZE+8, SER_DISK, PROTOCOL_VERSION);
+        uint64_t nRewind = blkdat.GetPos();
+        while (!blkdat.eof()) {
+            boost::this_thread::interruption_point();
+
+            blkdat.SetPos(nRewind);
+            nRewind++; // start one byte further next time, in case of failure
+            blkdat.SetLimit(); // remove former limit
+            unsigned int nSize = 0;
+            try {
+                // locate a header
+                unsigned char buf[CMessageHeader::MESSAGE_START_SIZE];
+                blkdat.FindByte(btcMagic[0]);
+                nRewind = blkdat.GetPos()+1;
+                blkdat >> FLATDATA(buf);
+
+                if (memcmp(buf, btcMagic, CMessageHeader::MESSAGE_START_SIZE))
+                    continue;
+
+                // read size
+                blkdat >> nSize;
+                if (nSize < 80 || nSize > MAX_TX_SIZE)
+                    continue;
+            } catch (const std::exception&) {
+                // no valid block header found; don't complain
+                LogPrintf("Import exception\n");
+                break;
+            }
+            try {
+                // read block
+                uint64_t nBlockPos = blkdat.GetPos();
+                if (dbp)
+                    dbp->nPos = nBlockPos;
+                blkdat.SetLimit(nBlockPos + nSize);
+                blkdat.SetPos(nBlockPos);
+                std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
+                CBlock& block = *pblock;
+                //block.new_format = false;
+                blkdat >> block;
+                //block >> blkdat;
+                nRewind = blkdat.GetPos();
+
+                LogPrintf("version: %d hash: %s prev: %s\n",
+                            block.nVersion,
+                            block.GetHash().ToString(),
+                            block.hashPrevBlock.ToString());
+
+                // detect out of order blocks, and store them for later
+                uint256 hash = block.GetHash();
+                if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex.find(block.hashPrevBlock) == mapBlockIndex.end()) {
+                    LogPrintf("%s: Out of order block %s, parent %s not known\n", __func__, hash.ToString(),
+                            block.hashPrevBlock.ToString());
+                    if (dbp)
+                       mapBlocksUnknownParent.insert(std::make_pair(block.hashPrevBlock, *dbp));
+                    continue;
+                }
+
+                if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) {
+                    LOCK(cs_main);
+                    CValidationState state;
+                    LogPrintf("Found prev hash in index\n");
+                    BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
+
+                    if (mi !=  mapBlockIndex.end()) {
+                        assert(mi != mapBlockIndex.end());
+                        const CBlockIndex *pindex = mi->second;
+                        LogPrintf("prev height %d\n", pindex->nHeight);
+                        blocknheight = pindex->nHeight +1;
+                    }
+
+                    if (importblocksbelow > 0 && blocknheight >= importblocksbelow)
+                        continue;
+                    if (AcceptBlock(config, pblock, state, nullptr, true, dbp, nullptr)) {
+                        LogPrintf("BLOCK ACCEPTEED\n");
+                        nLoaded++;
+                    } else
+                        LogPrintf("BLOCK REJECTED\n");
+                    if (state.IsError())
+                        break;
+                } else if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex[hash]->nHeight % 1000 == 0) {
+                    LogPrintf("Block Import: already had block %s at height %d\n", hash.ToString(), mapBlockIndex[hash]->nHeight);
+                }
+
+                // Activate the genesis block so normal node progress can continue
+                if (hash == chainparams.GetConsensus().hashGenesisBlock) {
+                    LogPrintf("Found Genesis Block\n" );
+                    CValidationState state;
+                    if (!ActivateBestChain(config, state)) {
+                        break;
+                    }
+                }
+
+                NotifyHeaderTip();
+
+            } catch (const std::exception& e) {
+                LogPrintf("%s: Deserialize or I/O error - %s\n", __func__, e.what());
+            }
+        }
+    } catch (const std::runtime_error& e) {
+        AbortNode(std::string("System error: ") + e.what());
+    }
+    if (nLoaded > 0)
+        LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, GetTimeMillis() - nStart);
+    return nLoaded > 0;
+}
+
 bool LoadExternalBlockFile(const Config &config, FILE *fileIn,
                            CDiskBlockPos *dbp) {
     // Map of disk positions for blocks with unknown parent (only used for


What this does is basically taking the blocks data from the block files on your harddrive and feeding them to the fork's own AcceptBlock() function. So it's not like the blocks are somehow illegitimately injected bypassing verification or any other test. If a block is accepted this way it's an identical situation as if the block was downloaded from other nodes via the Internet.

New/changed command-line options are as follows:

-loadblock=<dir>
 This option was already there but allowed to import only one single block file and from only the same signature blockchain. Now it has a different meaning - with it you specify the "blocks" directory that contains blocks you want to import, e.g. -loadblock=~/.bitcoin/blocks.

-loadblockfirst=<n>
 The number of the first blk000??.dat file that you want to import from, default is 0. It's ok to repeatedly start from 0 and try to import from files you already imported from, if the block is already in blockchain it will just be ignored.

-loadblocklast=<n>
 The number of the last blk000??.dat file that you want to import from, default is 0. It's ok to specify too high number (but above some 1200 or so will probably be pointless for any current fork), if a file is not found the loop will just continue with the next file.

-importblocksbelow=<n>
 Using this option will ensure that only blocks below given number are imported. This number is typically the fork number.

-ignorecheckqueuefailed
 It happened to me with one fork that I was importing blocks from the original Bitcoin and all of a sudden in the middle I got this strange 'ConnectBlock(): CheckQueue failed' error that prevented the import from continuing. I found out that if I actually ignored this error the block would then get imported successfully. So in my particular case this turned out to be a fake error. Since I knew that the blocks I was trying to import were correct and I wasn't willing to spend hours or days trying to fix somebody else's bug I implemented this option. However you should use it really as the last resort when you are stuck and only if you understand the implications.

-messagestart0=<hex>
-messagestart1=<hex>
-messagestart2=<hex>
-messagestart3=<hex>
 With these options you can specify the signature (magic bytes) of the blockchain from which you are trying to import blocks. This in theory might allow you to import pre-fork blocks from any fork into any fork. The original Bitcoin blockchain signature is 0xf9 0xbe 0xb4 0xd9 which is the default. What signature is used in the particular fork which you want to import from you can find out from the definition of pchMessageStart in src/chainparams.cpp.

-logwriteblockok
 An extra log of each successful WriteBlockToDisk().


Before you start importing the blocks it's advisable to first run the node and let it connect to other (fork's native) nodes and sync the headers. Once it starts downloading the actual blocks you can exit it and try this method. The import is then in two phases - first all the blocks are imported and then they are indexed. It happened to me in one case that not all blocks were imported all in one go and I had to rerun the import again (either set the -loadblockfirst appropriately or just let it go through all the files again, it's quite fast) so you may try that, too.

It's also worth noting that since all pre-fork blockchain data is identical (but not necessarily the actual blocks files are binary identical, though, so you shouldn't just cross-link them) you can very effectively use a deduplication feature of the filesystem that supports it and save nearly all the disk space. Since deduplication is not Bitcoin (forks) specific I will not go into details, I can just confirm that it works very well on both Linux (Ubuntu - zfs) and Windows (8.1 - ntfs).
2  Alternate cryptocurrencies / Altcoin Discussion / My list of 43(+3) reviewed Bitcoin forks on: January 18, 2018, 04:41:09 PM
Here is my list of 43 (mostly) reviewed Bitcoin forks (+3 Bitcoin Cash forks). This list is not comprehensive, I am not adding anymore forks that I newly learned about that very clearly have just a website (and maybe an old source code) and never really took off, it would be just a waste of my time.

Feel free to suggest a bugfix, addition or any other improvement.

The difference between this list and most of the other lists is that I personally compile the source code, run the software, sync or import all the shared pre-fork blockchain data (using the method I described here, if possible - almost always is), sync-up the blockchain, replace wallet.dat with my Bitcoin Core's encrypted wallet.dat, zap/rescan the wallet and verify that my balances are properly present. Since I never import any private key (and so far never made a since transaction on any of these new forks, thus never unencrypted and revealed my keys) even if the software is evil and would like to babble out the private keys it can't. I am only interested in forks with full-node source code based on Bitcoin Core. If all this checks out I deem the fork as "seems to be working". Aferwards I prune the blockchain up to the fork block by starting the daemon with "prune=1" and then issuing an RPC command "pruneblockchain <forkblock>" as the pre-fork blockchain data is not necessary anymore. That way we can see how much the fork's blockchain actually grew since its inception and that (the size of the "blocks" directory) is what the GB amount indicates.

(Last update: February 26th, 2019)


Total number of reviewed Bitcoin forks: 43
 of which
 - seem to be working: 16 (214.59 GB)
 - first worked then stopped (and possibly disappeared): 5 (10.22 GB)
 - seem to have no nodes: 1
 - haven't published full-node source code based on Bitcoin Core: 11
 - seem like a waste of my resources to compile/sync/test (sorry): 3
 - seem abandoned: 2
 - don't seem to exist (anymore): 5

Total number of reviewed Bitcoin Cash forks: 3 (5.89 GB)


Timeline
block 478558: Bitcoin Cash[>], Bitcoin Clashic[>]
block 491407: Bitcoin Gold[>]
block 495866: Bitcoin Diamond[>]
block 498754: Bitcoin CBC[>]
block 498777: UnitedBitcoin[>]
block 498848: Bitcoin Hot[>]
block 498888: SuperBitcoin[>], Bitcoin X[>], Oil Bitcoin[>]
block 498960: Bitcoin ALL[>]
block 499345: Bitcoin Pay[>]
block 499777: Bitcoin World[>]
block 499888: Bitclassic Coin[>]
block 499999: BitcoinStake[>], Bitcoin King[>]
block 500000: Bitcoin Faith[>]
block 500283: BitEthereum[>]
block 501000: Bitcoin New[>]
block 501118: Bitcoin Top[>]
block 501225: Bitcoin God[>], Bitcoin FILE[>], FastBitcoin[>]
block 501407: Bitcoin Cash Plus[>]
block 501451: Segwit2X[>]
December 31st, 2017: Bitcoin Uranium[>], Bitcoin Silver[>]
block 501888: Bitcoin Pizza[>], Bitcoin Nano[>]
block 501949: Bitcoin Ore[>]
block 503888: World Bitcoin[>]
block 505050: Bitcoin Smart[>], Bitvote[>]
block 505083: Bitcoin Interest[>]
block 505888: Bitcoin Atom[>]
January 30th, 2018: Bitcoin LITE[>]
block 507850: Bitcoin 2[>]
block 508000: Bitcoin Flash[>]
block 508888: Big Bitcoin[>]
block 511346: Bitcoin Private[>]
block 516095: ClassicBitcoin[>]
block 518800: bitcoinClean[>]
block 520000: Smart Bitcoin[>]


Bitcoin Cash (BCH)
- fork at 478558
- https://www.bitcoincash.org/
- https://github.com/Bitcoin-ABC/bitcoin-abc
- example nodes: https://bitnodes.earn.com/nodes/?q=NODE_CASH
- status on 2/26/2019: seems to be working, 13.5 GB

Bitcoin Clashic (BCL)
- fork at 478558
- http://bitcoinclashic.org
- "The Bitcoin Clashic mainnet launched on August 1st, 2017 and is still alive. Beware of BCash - a FakeVision, maliciously hard-forked from Clashic on November 13, 2017"
- https://twitter.com/BitcoinClashic
- https://github.com/Bitcoin-Clashic/bitcoin-clashic
- seems like a waste of my resources to compile/sync/test (sorry)

Bitcoin Gold (BTG)
- fork at 491407
- https://bitcoingold.org/
- https://github.com/BTCGPU/BTCGPU
- example nodes: 120.76.25.178:8338, 173.212.207.13:8338, 145.239.0.50:8338, 97.94.224.113:8338
- status on 2/26/2019: seems to be working, 4.26 GB

Bitcoin Diamond (BCD) (1 BTC = 10 BCD)
- fork at 495866
- http://www.btcd.io/
- https://twitter.com/BitcoinDiamond_
- https://github.com/eveybcd/BitcoinDiamond
- example nodes: 104.215.189.251:7117, 138.197.73.98:7117, 47.74.133.129:7117, 47.95.22.84:7117
- status on 2/26/2019: seems to be working, 0.8 GB

Bitcoin CBC (BCBC)
- fork at 498754
- snapshot fork (no shared pre-fork blockchain history)
- "All unspent coinbase generated coins from 50000 first blocks from original Bitcoin blockchain were filtered (1235650 coins)"
- "Two famous addresses deleted from blockchain: 1FeexV6bAHb8ybZjq, 12tkqA9xSoowkzoER (108108 coins)"
- "Each address with positive amount was substracted by 1 COIN, these funds also went to to ExtraReward. (1356958 coins)" [sic]
- https://cleanblockchain.org/ (disappeared)
- https://twitter.com/cleanblockchain (disappeared)
- https://github.com/cleanblockchain/Bitcoin-CBC (disappeared)
- status on 2/26/2019: doesn't seem to be working anymore, 0.04 GB, last synced block 18286 on 7/17/2018

UnitedBitcoin (UBTC)
- fork at 498777
- http://www.ub.com
- https://twitter.com/United_Bitcoin
- https://github.com/UnitedBitcoin/UnitedBitcoin
- example nodes: 101.200.56.23:8333, 39.107.77.167:8333, 212.64.58.109:8333
- Phase1 between Block 494000 and Block 498777, Phase2 between Block 498777 and Block 501878
- status on 2/26/2019: still seems to be working, 2.09 GB

Bitcoin Hot (BTH) (1 BTC = 100 BTH)
- fork at 498848
- https://www.bithot.org/
- https://github.com/BitcoinHot/bitcoinhot
- no source code available

SuperBitcoin (SBTC)
- fork at 498888
- http://superbtc.org/
- https://twitter.com/SuperBTC2
- https://github.com/superbitcoin/SuperBitcoin
- https://bitcointalk.org/index.php?topic=2546577
- example nodes: 47.254.203.200:8334, 118.31.46.190:8334, 120.78.188.194:8334, 47.89.183.127:8334
- status on 2/26/2019: still seems to be working, 0.4 GB

Bitcoin X (BCX) (1 BTC = 10000 BCX)
- fork at 498888
- https://bcx.org/
- https://github.com/bitcoinx-project/bitcoinx
- example nodes: 120.131.5.15:9003, 166.62.117.163:9003, 47.97.8.50:9003, 180.97.80.213:9003
- status on 2/26/2019: still seems to be working, 0.6 GB

Oil Bitcoin (OBTC)
- fork at 498888
- http://www.oilbtc.io/index_en.html (disappeared)
- https://twitter.com/oilbtc
- https://github.com/oilbtc2017/oilbtc
- status on 2/26/2019: doesn't seem to be working anymore, 0.6 GB, last synced block 524001 on 3/7/2018

Bitcoin ALL (BTA)
- fork at 498960
- http://bitcoinall.org/ (only in Chinese)
- no source code available

Bitcoin Pay (BTP) (1 BTC = 10 BTP)
- fork at 499345
- http://www.btceasypay.com/
- no source code available

Bitcoin World (BTW) (1 BTC = 10000 BTW)
- fork at 499777
- http://www.btw.one/
- https://github.com/btwone/btwcore
- status on 2/26/2019: - seems to have no nodes (no DNS seeds)

Bitclassic Coin (BICC)
- fork at 499888
- http://bicc.io/
- https://github.com/bitunity/BitClassicCoin-BICC
- doesn't seem to exist (anymore)


BitcoinStake (BTCS) (1 BTC = 100 BTCS)
- fork at 499999
- http://btcscoin.com (only in Chinese)
- no source code available

Bitcoin King (BCK)
- fork at 499999
- https://btcking.org/
- https://github.com/btcking/btcking
- seems like a waste of my resources to compile/sync/test (sorry)

Bitcoin Faith (BTF)
- fork at 500000
- http://bitcoinfaith.org/
- https://twitter.com/BitcoinFaith
- https://github.com/bitcoinfaith/bitcoinfaith (disappeared)
- example nodes: 51.255.95.53:8346
- status on 2/26/2019: still seems to be working, 0.6 GB

BitEthereum (BITE) (1 BTC = 3.93946357 BITE)
- fork at 500283 - 00:00 on December 21st, 2017 (GMT+8)
- claiming deadline April 2, 2018
- https://www.bitethereum.io/
- no source code available

Bitcoin New (BTN)
- fork at 501000
- http://btn.kim
- https://twitter.com/BTN_top
- no source code available
- doesn't seem to exist (anymore)


Bitcoin Top (BTT)
- fork at 501118
- https://bitcointop.org/
- https://github.com/bitcointop/bitcointop
- example nodes: 47.52.201.220:18888, 61.52.24.7:18888
- status on 2/26/2019: still seems to be working, 0.2 GB

Bitcoin God (GOD)
- fork at 501225
- https://www.bitcoingod.org/
- https://twitter.com/BitcoinGodOrg
- https://twitter.com/ChandlerGuo
- https://github.com/BitcoinGod/BitcoinGod/
- example nodes: 47.98.114.56:8885, 78.126.24.43:8885, 47.75.185.189:8885, 47.106.86.211:8885
- status on 2/26/2019: seems to be working, 0.7 GB

Bitcoin FILE (BIFI) (1 BTC = 1000 BIFI)
- fork at 501225
- https://www.bitcoinfile.org/
- no source code available

FastBitcoin (FBTC)
- fork at 501225
- https://fbtc.pro/index-en.html
- https://github.com/fastbitcoin/fastbitcoin (not based on Bitcoin Core)

Bitcoin Cash Plus (BCP)
- fork at 501407
- http://bitcoincashplus.org/
- https://twitter.com/bitcoincashplus
- https://github.com/bitcoincashplus/bitcoincashplus
- status on 2/26/2019: doesn't seem to be working anymore, 8.88 GB, last synced block 536609 on 6/8/2018

Segwit2X (B2X) (1:1 + "a proportional number of Bitcoins of Satoshi Nakamoto" via "the crypto-exchanges and wallets of our partners gradually")
- fork at 501451
- https://b2x-segwit.io/
- https://bitcointalk.org/index.php?topic=2595620
- https://github.com/SegwitB2X/bitcoin2x
- example nodes: 47.97.117.250:8333, 94.130.27.232:8333
- status on 2/26/2019: still seems to be working, 0.8 GB

Bitcoin Uranium (BUM)
- fork at ?? ("Coming 31th December 2017")
- https://bitcointalk.org/index.php?topic=2316506
- https://github.com/BitcoinUranium/bitcoin
- doesn't seem to exist (anymore)


Bitcoin Silver (BTSI)
- fork at ?? ("COMING 31TH DECEMBER 2017")
- https://bitcointalk.org/index.php?topic=2311582
- no source code available
- doesn't seem to exist (anymore)


Bitcoin Pizza (BPA)
- fork at 501888
- http://p.top/en/
- https://github.com/DAGBPA/BitcoinPizza/
- example nodes: 59.110.7.115:8888
- status on 2/26/2019: still seems to be working, 1.54 GB

Bitcoin Nano (Nano) (1 BTC = 1000 Nano)
- fork at 501888
- snapshot fork (no shared pre-fork blockchain history)
- https://www.btcnano.org/
- https://twitter.com/BitcoinNano1
- https://github.com/bitcoinnano/Bitcoin-Nano
- seems abandoned


Bitcoin Ore (BCO)
- fork at 501949
- http://bitcoinore.org/
- no source code available

World Bitcoin (WBTC) (1 BTC = 100 WBTC)
- fork at 503888
- http://www.wbtcteam.org
- https://github.com/worldbitcoin/worldbitcoin
- status on 2/26/2019: doesn't seem to be working anymore, 0.4 GB, last synced block 537946 on 8/8/2018

Bitcoin Smart (BCS) (1 BTC = 100 BCS + 100 BCST)
- fork at 505050
- http://bcs.info/
- no source code available

Bitvote (BTV)
- fork at 505050
- https://www.bitvote.one/
- https://twitter.com/bitvoteone
- https://github.com/bitcoinvote/bitcoin
- seems like a waste of my resources to compile/sync/test (sorry)

Bitcoin Interest (BCI)
- fork at 505083
- https://www.bitcoininterest.io/
- https://github.com/BitcoinInterestOfficial/BitcoinInterest
- example nodes: 46.236.162.178:8334, 37.16.104.242:8334, 42.190.80.149:8334, 54.38.176.216:8334
- status on 2/26/2019: still seems to be working, 0.9 GB

Bitcoin Atom (BCA)
- fork at 505888
- https://bitcoinatom.io/
- https://twitter.com/atombitcoin
- https://bitcointalk.org/index.php?topic=2515675
- https://github.com/bitcoin-atom
- txindex enabled by default!
- EPIC FAIL: there is allegedly a difficulty adjustment bug thanks to which millions of coins have been mined in less than 24 hours making the coin entirely and irrecoverably worthless
 (EDIT 1 year later: the coin indeed is entirely worthless)

- example nodes: 94.130.148.122:7333, 78.47.153.240:7333, 144.76.17.43:7333, 54.37.85.125:7333
- status on 2/26/2019: still seems to be working, 177 GB (full unpruned blockchain size; pruning is incompatible with txindex)

Bitcoin LITE (BTCL)
- fork on 30th January 2018
- http://www.bitcoinlite.us/
- no source code available
- seems abandoned


Bitcoin 2 (BTC2)
- fork at 507850
- snapshot fork (no shared pre-fork blockchain history, "the blockchain data will be pruned from over 150 GB to around 2 GB")
- https://www.bitc2.org/
- https://bitcointalk.org/index.php?topic=2871452
- https://github.com/BITC2/bitcoin2
- example nodes: 35.199.179.16:8333, 217.69.8.166:8333, 100.25.106.64:8333, 79.118.191.240:8333
- status on 2/26/2019: seems to be working, 1.2 GB

Bitcoin Flash (BTF)
- fork at 508000
- https://bitcoinflash.io/
- https://github.com/bitcoinflash/bitcoinflash
- doesn't seem to exist (anymore)


Big Bitcoin (BBC) (1 BTC = 10 BBC)
- fork at 508888
- http://www.bigbitcoins.org/
- no source code available

Bitcoin Private (BTCP)
- fork at 511346
- snapshot fork (no shared pre-fork blockchain history)
- https://bitcoinpvt.org/
- https://twitter.com/bitcoinprivate
- https://github.com/BTCPrivate/BitcoinPrivate
- Java GUI, a bit CPU intensive (at least on Windows)
- example nodes: 116.203.99.142:7933, 93.104.213.103:7933, 35.233.22.185:7933, 68.195.18.155:7933
- status on 2/26/2019: seems to be working, 9.5 GB

ClassicBitcoin (CBTC) (1 BTC = 10000 CBTC)
- fork at 516095
- https://bitclassic.info/
- https://twitter.com/bitclassic2
- https://github.com/classicbitcoins/cbitcoin
- example nodes: 85.25.242.141:7123, 158.69.125.174:7123, 61.38.133.138:7123, 74.118.139.241:7123
- status on 2/26/2019: seems to be working, 0.5 GB

bitcoinClean (BCL)
- fork at 518800
- https://bitcoinclean.org/
- https://github.com/bitcoinclean/bitcoinclean
- status on 2/26/2019: doesn't seem to be working anymore, 0.3 GB, last synced block 588600 on 11/10/2018

Smart Bitcoin (SBC)
- fork at 520000
- http://www.smartbitcoin.one/index-en.html
- no source code available



Bitcoin Cash forks

Bitcoin Candy (CDY) (1 BCH = 1000 CDY)
- forked at 512666
- http://cdy.one/index_EN.html
- https://github.com/bitcoincandyofficial/bitcoincandy
- example nodes: 47.74.144.158:8367, 5.79.85.222:8367, 188.40.206.114:8367, 61.74.82.106:8367
- status on 2/26/2019: seems to be working, 1.15 GB

Bitcoin SV (BSV)
- forked at 556767
- https://bitcoinsv.io/
- https://github.com/bitcoin-sv/bitcoin-sv
- GUI wallet entirely removed for no reason
- example nodes: 40.115.159.63:8333, 206.189.104.98:8333, 47.244.132.56:8333, 81.92.218.166:8333
- status on 2/26/2019: seems to be working, 4.34 GB

Bitcoin Stash (BSH)
- forked at 556767
- https://bstash.org/
- https://github.com/bstash/bitcoinstash
- example nodes: 68.183.130.109:10101, 39.106.250.31:10101, 104.248.124.131:10101
- status on 2/26/2019: seems to be working, 0.4 GB



Honorable mentions

Stellar Lumen (XLM)
- https://www.stellar.org/
- bitcoin holders could have claimed free lumens until August 27th, 2017

Byteball Bytes (GBYTE)
- https://byteball.org/
- bitcoin holders (as well as byteball holders themselves) were getting free bytes and blackbytes in distribution rounds since December 25th, 2016, distributed 64.5% of the total supply
- the distribution was cut short suddenly and without any prior announcement => loss of credibility

Bitcore (BTX)
- https://bitcore.cc/
- originally the bitcoin holders received free coins in two rounds and then all the bitcore holders have been receiving weekly airdrops for several months

Bitcoin Hush (BTCH)
- http://btchush.org/
- bitcoin holders can claim BTCH in 1:1 ratio
- "BTCH takes the value from four different blockchains (HUSH, SUPERNET, DEX, BTC), and then dumps it onto a host chain Komodo (KMD). It does not fork from KMD, nor does it fork from BTC or HUSH. It is technically NOT A FORK, but a merged airdrop."
- doesn't seem to exist (anymore)

3  Other / Off-topic / - on: May 17, 2017, 05:48:35 PM
-
4  Other / Off-topic / - on: May 15, 2017, 09:06:10 AM
-
5  Other / Off-topic / - on: May 11, 2017, 06:21:29 AM
-
6  Other / Off-topic / - on: November 14, 2016, 06:57:52 PM
-
7  Other / Archival / 100417 Beware of fraudulent AWS accounts sellers +My scammers&legit sellers list on: October 14, 2016, 11:38:11 AM
Update 10/04/2017

Updated the list of legit sellers and scammers (at the bottom - click).

Update 03/01/2017

I tried to sum up the danger of using EDU promotional codes here.

Update 10/13/2016

Another very important thing to check, if possible before you buy the account, is whether the address registered in the account is real - i.e. whether it really exists and is residential (a person can really live there). Just use google maps and look that address up.
Also, check whether the name registered in the account matches with the name on the card that was set as the payment method.

You also want to know how old is the account. If the account is totally new, created maybe only a few hours before you bought it, you need to be very careful. Most of the Amazon security checks are performed within the first 48 hours. If anything doesn't seem right to them they will put the account on hold and request additional documents from you and if you don't comply they will suspend the account.
You can determine the account's age by checking the Bills section. If there are no previous billing months, only the current one, you have to assume the account was just created and therefore you should be double careful.



Since there are more and more questionable posts popping up offering AWS accounts, here is something that may help you decide whether you risk sending your money to an anonymous person.

Besides checking the obvious - reputation, vouches availability, topic and trust feedback (make sure you enabled "Show untrusted feedback by default" in "Profile / Forum Profile Information") - always check whether the e-mail that the AWS account is tied to is part of the deal. Otherwise you will pay for something that the sellers may anytime block access to. Once you buy the account immediately change the password to both AWS and e-mail accounts and don't forget to remove all password recovery options in the e-mail account (secondary mail address, phone, security questions etc.).

Another very important thing is checking the EC2 limits. If the sellers don't show them on their own ask for screenshots. Here is what a real normal EC2 limits of a genuine legit AWS accounts look like:

A freshly opened AWS account



A normal AWS account after the initial limits have been lifted



If the limits claimed by the sellers are distinctly different be very careful, their screenshots may be photoshopped.

Last but not least, if your only reason for buying an AWS account is the fact that you already have one and you think you can't have another one then you are mistaken. There is no such rule as 1 AWS account per 1 person, it's perfectly legal and normal to have multiple AWS accounts. Just go on and sign up for another AWS account. You may use the same phone and card number if you wish, the e-mail address has to be different, though. But don't create too many accounts with the same phone and card - from my observation the 4th account and onward created with the same info will have the limits nearly all zeroes.
This way you can also kind of circumvent the initial 2-regions limitation of a newly created AWS account - for all subsequent AWS accounts you can simply ask the 2 enabled regions to be changed to different ones instead of the default Virginia and Oregon and that way you can cover more regions, but be careful to not make it too obvious. Just keep in mind that the free-tier 12-months benefit is allowed only 1 per a person, not 1 per an account, so even if you create 10 AWS accounts (all in the same name and with the same phone/card number) you are still entitled to only 1 free-tier bonus.

Feel free to add your own suggestions and experience regarding buying AWS accounts on this forum, it will help all of us.


P.S.: I do not sell AWS accounts nor I know any genuine AWS accounts seller on this forum that I tried and can recommend.


Also make sure that you keep consistent with access IP if you use the console, clean and fresh contact data (most important of course payment method).

A great point from RFX and this can actually be solved using roles. You can link all the other accounts to one single "master" (or "control") account and then only log (and thus expose your IP) into that account. This way you will have to actually log in a bought account only once, to set the link. After that you will never have to log into it ever again.


Here is a mini tutorial how to access multiple AWS accounts from one single AWS account without logging into each separately

What to do in every account that you want to access from your master account
You need to create a role for cross-account access, enter the account number of your master account to establish trust and attach an appropriate policy to it. If you want to be able to access the billing pages too (e.g. to apply the AWS credits there, or work with the payment information etc.), you also need to activate IAM access. See the screenshots:




What to do in your master account from which you want to access the other accounts
You need to create an IAM user and then log into the account using that IAM user via the following link:
https://123456789012.signin.aws.amazon.com/console
where the number is the master account number.
If you want to be able to access the billing pages of this master account as well, you will also need to activate IAM access.

Then you will simply use the "Switch Role" option to switch between accounts:




My personal list of legit AWS code sellers I personally obtained valid codes from

Warning: this is a list of honest people selling AWS codes, not AWS accounts!




My personal list of scammers I encountered on bitcointalk.org - click here

The general rule is: if the seller is a newbie, with no reputation, with no topic nor trust feedback, offering no vouches and/or selling from a locked or self-moderated topic and unwilling to go first or use escrow => AVOID.

Also avoid anyone calling himself "we", it's just an early teenager desperately trying to pretend he - a little boy - is some kind of legitimate business entity, truly laughable.

Always check the trust feedback first and make sure that you have enabled "Show untrusted feedback by default" in "Profile / Forum Profile Information".
8  Economy / Scam Accusations / My personal list of scammers on: September 04, 2016, 11:55:41 PM
My personal list of scammers I encountered on bitcointalk.org

Avoid these little lowlife fraudulent kids at all costs:

  • seller.aws.ec2 (reference here)
  • awsses (reference here) <-- this scammer first sold me a few working AWS codes expecting my positive feedback in an attempt to establish some kind of an apparent legitimacy and then went on and scammed everybody else ever since, therefore I eventually decided to remove my positive feedback
  • nanohits (reference here)
  • edulord (reference here)
  • DannyHamilton <-- gives fake negative feedbacks
  • mocacinno (reference here) <-- extremely dangerous, tries to make people publicly reveal their btc addresses, ownership, wallet software and other details; also gives fake neutral/negative feedbacks
  • iCEBREAKER <-- gives fake negative feedbacks
  • R00TC0IN (reference here) <-- lies, scams and tries to sell old and broken version of a free open-source software that he stole from github, hilariously retarded little scammer
  • topherhf (reference here and here)
  • pipobuccshop (reference here and here)
  • XXXXXXXXXXXXX <-- hilariously funny little scamming kid
  • iCEBREAKER (reference here and here) <-- besides scamming he gives fraudulent negative feedbacks as an extremely silly and futile revenge attempt for being exposed, I encourage everyone to give him a negative feedback
  • AmazonSESAws (reference here and here)
  • NvidiaFan (reference here and here)
  • iPhone9 (reference here and here)
  • LocalBitcoinsScript (reference here and here)
  • stableversion (reference here) <-- another account of MaxDeliver
  • MaxDeliver (reference here and here) <-- another account of stableversion
  • AmazonGCKing (reference here and here) <-- besides scamming he gives fraudulent negative feedbacks as an extremely silly and futile revenge attempt for being exposed, I encourage everyone to give him a negative feedback
  • Dadan (reference here)
  • makaveli82 (reference here)
  • white.walker (reference here and here)
  • Symeave (reference here and here)  <-- very dangerous, can steal your money repeatedly in the future!


The general rule is: if the seller is a newbie, with no reputation, with no topic nor trust feedback, offering no vouches and/or selling from a locked or self-moderated topic and unwilling to go first or use escrow => AVOID.

Also avoid anyone calling himself "we", it's just an early teenager desperately trying to pretend he - a little boy - is some kind of a legitimate business entity, truly laughable.

Always check the trust feedback first and make sure that you have enabled "Show untrusted feedback by default" in "Profile / Forum Profile Information".
9  Economy / Digital goods / -50% OFF now $6 only! [WTS] $200 AWS codes for $12 BTC [AUTOBUY] on: August 17, 2016, 03:26:22 AM
I am not really a seller but I've got a few of these codes and only 1 can be used per account so I am offering the rest here for a very reasonable price.

Expiration: 2016-12-31

You can PM me or use the following autobuy link: http://selly.io/p/28563/a290a6.

If you already have some promotional codes redeemed in your account other than AngelHack2016, MLH2015 or ActivateStartups I suggest checking up with me first via PM so that you don't buy something you already have (though I haven't seen anyone selling this particular AWS code on here yet).

I will deal with any possible complaint or a refund request on a case-to-case basis, depending on the problem description, your trust rating and whether you followed or ignored my suggestion above. (I am not here to scam anybody but I don't want to be scammed either.)

If you are an established forum member (i.e. not a newbie) with a positive trust I can go first otherwise you go first (or use the autobuy).


I can give one or two vouches to trustworthy forum members with a positive trust.



List of scammers
Avoid these little lowlife fraudulent kids at all costs:
10  Economy / Digital goods / [WTB] AWS codes: 1x $100 MLH2015 and 1x $100 AngelHack2016 on: August 14, 2016, 07:21:44 PM
For a reasonable (reasonably low) price.
11  Alternate cryptocurrencies / Pools (Altcoins) / ETH mining profitability - DwarfPool vs Ethermine vs Nicehash on: August 06, 2016, 03:17:38 AM
I don't want to start a flame war or anything, but which one of those three is in your opinion the best in the terms of profitability for ETH mining and why?

A side question: does anyone know about any ETH proxy that works with Nicehash?
Pages: [1]
Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!