Author

Topic: Chain Archaeology revisited -- Any more known miners for sub 1000 blocks? (Read 169 times)

full member
Activity: 173
Merit: 120
This is a graph of bnExtraNonce not block.nNonce.  It gets incremented when blocks are found and when transactions arrive (which also causes common slope) but it is not reset when blocks are found. At difficulty 1 those shared causes of incrementing should be the primary driver of extranonce incrementing.
thanks gmaxwell for clarifying.  I will do some more research this weekend.   No more known early blocks I guess. 
staff
Activity: 4284
Merit: 8808
This is a graph of bnExtraNonce not block.nNonce.  It gets incremented when blocks are found and when transactions arrive (which also causes common slope) but it is not reset when blocks are found. At difficulty 1 those shared causes of incrementing should be the primary driver of extranonce incrementing.
jr. member
Activity: 41
Merit: 41
I'm not a C++ expert, but according to the source code for Bitcoin v0.1.0, the nonce starts at 1 and then increments after every attempt (line 2297, main.cpp).

HOWEVER, contrary to the comments in that thread, it looks like the nonce gets reset to 1 EVERY time a new block is found or accepted, whether self-mined or from the network. That means the nonce slopes are mysterious because they don't start from 1 every time a block is found!

Maybe they were running a version older than 0.1.0, which is possible because the genesis block is from Jan 3, 2009 at 6:15:05 AM UTC. Or maybe the extra miners were custom mining clients (likely Satoshi) that didn't reset the nonce.


CORRECTION: It's the global bnExtraNonce (put in the coinbase's scriptSig) that gets incremented and doesn't reset for the uptime of the v0.1.0 client (see posts below).

main.cpp lines 2183-2361 (file timestamped Jan 7, 2009, 9:00:00 AM UTC)
Code:
bool BitcoinMiner()
{
    printf("BitcoinMiner started\n");
    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);

    CKey key;
    key.MakeNewKey();
    CBigNum bnExtraNonce = 0;
    while (fGenerateBitcoins)
    {
        Sleep(50);
        CheckForShutdown(3);
        while (vNodes.empty())
        {
            Sleep(1000);
            CheckForShutdown(3);
        }

        unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
        CBlockIndex* pindexPrev = pindexBest;
        unsigned int nBits = GetNextWorkRequired(pindexPrev);


        //
        // Create coinbase tx
        //
        CTransaction txNew;
        txNew.vin.resize(1);
        txNew.vin[0].prevout.SetNull();
        txNew.vin[0].scriptSig << nBits << ++bnExtraNonce;
        txNew.vout.resize(1);
        txNew.vout[0].scriptPubKey << key.GetPubKey() << OP_CHECKSIG;


        //
        // Create new block
        //
        auto_ptr pblock(new CBlock());
        if (!pblock.get())
            return false;

        // Add our coinbase tx as first transaction
        pblock->vtx.push_back(txNew);

        // Collect the latest transactions into the block
        int64 nFees = 0;
        CRITICAL_BLOCK(cs_main)
        CRITICAL_BLOCK(cs_mapTransactions)
        {
            CTxDB txdb("r");
            map mapTestPool;
            vector vfAlreadyAdded(mapTransactions.size());
            bool fFoundSomething = true;
            unsigned int nBlockSize = 0;
            while (fFoundSomething && nBlockSize < MAX_SIZE/2)
            {
                fFoundSomething = false;
                unsigned int n = 0;
                for (map::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi, ++n)
                {
                    if (vfAlreadyAdded[n])
                        continue;
                    CTransaction& tx = (*mi).second;
                    if (tx.IsCoinBase() || !tx.IsFinal())
                        continue;

                    // Transaction fee requirements, mainly only needed for flood control
                    // Under 10K (about 80 inputs) is free for first 100 transactions
                    // Base rate is 0.01 per KB
                    int64 nMinFee = tx.GetMinFee(pblock->vtx.size() < 100);

                    map mapTestPoolTmp(mapTestPool);
                    if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), 0, nFees, false, true, nMinFee))
                        continue;
                    swap(mapTestPool, mapTestPoolTmp);

                    pblock->vtx.push_back(tx);
                    nBlockSize += ::GetSerializeSize(tx, SER_NETWORK);
                    vfAlreadyAdded[n] = true;
                    fFoundSomething = true;
                }
            }
        }
        pblock->nBits = nBits;
        pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(nFees);
        printf("\n\nRunning BitcoinMiner with %d transactions in block\n", pblock->vtx.size());


        //
        // Prebuild hash buffer
        //
        struct unnamed1
        {
            struct unnamed2
            {
                int nVersion;
                uint256 hashPrevBlock;
                uint256 hashMerkleRoot;
                unsigned int nTime;
                unsigned int nBits;
                unsigned int nNonce;
            }
            block;
            unsigned char pchPadding0[64];
            uint256 hash1;
            unsigned char pchPadding1[64];
        }
        tmp;

        tmp.block.nVersion       = pblock->nVersion;
        tmp.block.hashPrevBlock  = pblock->hashPrevBlock  = (pindexPrev ? pindexPrev->GetBlockHash() : 0);
        tmp.block.hashMerkleRoot = pblock->hashMerkleRoot = pblock->BuildMerkleTree();
        tmp.block.nTime          = pblock->nTime          = max((pindexPrev ? pindexPrev->GetMedianTimePast()+1 : 0), GetAdjustedTime());
        tmp.block.nBits          = pblock->nBits          = nBits;
        tmp.block.nNonce         = pblock->nNonce         = 1;

        unsigned int nBlocks0 = FormatHashBlocks(&tmp.block, sizeof(tmp.block));
        unsigned int nBlocks1 = FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));


        //
        // Search
        //
        unsigned int nStart = GetTime();
        uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
        uint256 hash;
        loop
        {
            BlockSHA256(&tmp.block, nBlocks0, &tmp.hash1);
            BlockSHA256(&tmp.hash1, nBlocks1, &hash);


            if (hash <= hashTarget)
            {
                pblock->nNonce = tmp.block.nNonce;
                assert(hash == pblock->GetHash());

                    //// debug print
                    printf("BitcoinMiner:\n");
                    printf("proof-of-work found  \n  hash: %s  \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
                    pblock->print();

                SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
                CRITICAL_BLOCK(cs_main)
                {
                    // Save key
                    if (!AddKey(key))
                        return false;
                    key.MakeNewKey();

                    // Process this block the same as if we had received it from another node
                    if (!ProcessBlock(NULL, pblock.release()))
                        printf("ERROR in BitcoinMiner, ProcessBlock, block not accepted\n");
                }
                SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);

                Sleep(500);
                break;
            }

            // Update nTime every few seconds
            if ((++tmp.block.nNonce & 0x3ffff) == 0)
            {
                CheckForShutdown(3);
                if (tmp.block.nNonce == 0)
                    break;
                if (pindexPrev != pindexBest)
                    break;
                if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)
                    break;
                if (!fGenerateBitcoins)
                    break;
                tmp.block.nTime = pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
            }
        }
    }

    return true;
}

Reference: https://satoshi.nakamotoinstitute.org/code/
full member
Activity: 173
Merit: 120
I really enjoyed  Taras' 2014 thread Chain Archaeology - Answers from the early blockchain

unfortunately most of the links don't show up so I had to manually view them to get full effect. Tongue  Kind of entertaining watching how Taras' mind was working/evolving over the thread, but I did reproduce some of Taras' work for fun and generated a final chart mapping the early miners' Extra Nonce values for their coinbase transactions from this message:
list of spent blocks we've linked so far (see link for list)



If I understand correctly some of the miners in brackets were just names assigned by Taras to unknown miners that I think were identified purely because of the pattern?, but others like Hal Finney were obtained using a screen shot of his earliest transactions so they are 100% confident at least.

Questions:

1) At this time frame using the early non customized bitcoin.exe is it expected to see the miner's coinbase block increment like Hal's until they restart their instance? It is so odd they all have approximately the same angle over time...is that a reflection of the hash rate for a typical PC in 2009 or something else?
2) Does anyone know of miners of blocks less than 1000 that aren't included in Taras' list?  Screen shots of early transactions like Hal's would be ideal  Smiley I have screen shot of theymos early transactions he posted, but they are much later than 1000.

Thanks!
Jump to: