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)
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/