Bitcoin Forum
December 14, 2019, 10:30:24 AM *
News: Latest Bitcoin Core release: 0.19.0.1 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Understanding The Satoshi Codebase (Series) PART 1 -  (Read 689 times)
MagicByt3
Full Member
***
Offline Offline

Activity: 378
Merit: 198


View Profile
November 28, 2018, 04:45:12 PM
Last edit: November 28, 2018, 05:28:25 PM by MagicByt3
Merited by AverageGlabella (10), ETFbitcoin (8), LoyceV (2), Joel_Jantsen (2), vapourminer (1), Last of the V8s (1), HCP (1), Coin-1 (1), Piggy (1), Heisenberg_Hunter (1), REF (1), darosior (1)
 #1

Understanding The Satoshi Codebase : Bitcoin V0.1.5

With the influx of new users to bitcoin I think it is important people understand some of the underlying code behind bitcoin in this I will highlight parts of the codebase that people might find  interesting or have heard words such as genesis block ect and are not quite sure what or where to find this in the codebase.

I would like to create a topic that users can contribute from the early code base and create a reference resource that people can quickly reference to learn about the early codebase.

Posts should in the format of  
Heading = Part 1 Genesis block
File Name Ref = main.cpp
Line = 1467

(Context / text / code reference)

please use code tags.

We will be looking at Version 0.1.5 which can be downloaded from the following link.

https://github.com/bitcoin/bitcoin/releases/tag/v0.1.5

Please only use V0.1.5 for this purpose.
================================================


Part 1. Genesis Block.

Blockchain link : https://www.blockchain.com/btc/block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f

Reference : File  main.cpp

Line 1467

Code:
       

// Genesis Block:
        // GetHash()      = 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
        // hashMerkleRoot = 0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
        // txNew.vin[0].scriptSig     = 486604799 4 0x736B6E616220726F662074756F6C69616220646E6F63657320666F206B6E697262206E6F20726F6C6C65636E61684320393030322F6E614A2F33302073656D695420656854
        // txNew.vout[0].nValue       = 5000000000
        // txNew.vout[0].scriptPubKey = 0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704 OP_CHECKSIG
        // block.nVersion = 1
        // block.nTime    = 1231006505
        // block.nBits    = 0x1d00ffff
        // block.nNonce   = 2083236893
        // CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
        //   CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
        //     CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
        //     CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
        //   vMerkleTree: 4a5e1e

        // Genesis block
        char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
        CTransaction txNew;
        txNew.vin.resize(1);
        txNew.vout.resize(1);
        txNew.vin[0].scriptSig     = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((unsigned char*)pszTimestamp, (unsigned char*)pszTimestamp + strlen(pszTimestamp));
        txNew.vout[0].nValue       = 50 * COIN;
        txNew.vout[0].scriptPubKey = CScript() << CBigNum("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704") << OP_CHECKSIG;
        CBlock block;
        block.vtx.push_back(txNew);
        block.hashPrevBlock = 0;
        block.hashMerkleRoot = block.BuildMerkleTree();
        block.nVersion = 1;
        block.nTime    = 1231006505;
        block.nBits    = 0x1d00ffff;
        block.nNonce   = 2083236893;

            //// debug print, delete this later
            printf("%s\n", block.GetHash().ToString().c_str());
            printf("%s\n", block.hashMerkleRoot.ToString().c_str());
            printf("%s\n", hashGenesisBlock.ToString().c_str());
            txNew.vout[0].scriptPubKey.print();
            block.print();
            assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));

        assert(block.GetHash() == hashGenesisBlock);



The genesis block is the beginning of the blockchain,  
This block is hard coded into the application of bitcoin.  

You can see from the above code on the first line we see

0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f

This is the block hash which can be found by searching in any block explorer which would give you

Code:

Block #0
Summary
Number Of Transactions
1
Output Total
$ 208,999.50
Estimated Transaction Volume
$ 0.00
Transaction Fees
$ 0.00
Height
0 (Main Chain)
Timestamp
2009-01-03 18:15:05
Received Time
2009-01-03 18:15:05
Relayed By
Unknown
Difficulty
1
Bits
486604799
Size
0.285 kB
Weight
0.896 kWU
Version
1
Nonce
2083236893
Block Reward
$ 208,999.50
Hashes
Hash
000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
Previous Block
0000000000000000000000000000000000000000000000000000000000000000
Next Block(s)
00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048
Merkle Root
4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b

Transactions
4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b 2009-01-03 18:15:0
No Inputs (Newly Generated Coins)

1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa (Genesis of Bitcoin ) $ 208,999.50



We can also see the reward of 50 Bitcoin for the block in :

Code:
 txNew.vout[0].nValue       = 50 * COIN;

The reward was sent to 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa ,



How is the bitcoin reward set in bitcoin?

If we move to lines 657 to 729 in main.cpp we see the following :

Code:


//////////////////////////////////////////////////////////////////////////////
//
// CBlock and CBlockIndex
//

bool CBlock::ReadFromDisk(const CBlockIndex* pblockindex, bool fReadTransactions)
{
    return ReadFromDisk(pblockindex->nFile, pblockindex->nBlockPos, fReadTransactions);
}

uint256 GetOrphanRoot(const CBlock* pblock)
{
    // Work back to the first block in the orphan chain
    while (mapOrphanBlocks.count(pblock->hashPrevBlock))
        pblock = mapOrphanBlocks[pblock->hashPrevBlock];
    return pblock->GetHash();
}

int64 CBlock::GetBlockValue(int64 nFees) const
{
    int64 nSubsidy = 50 * COIN;

    // Subsidy is cut in half every 4 years
    nSubsidy >>= (nBestHeight / 210000);

    return nSubsidy + nFees;
}

unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast)
{
    const unsigned int nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
    const unsigned int nTargetSpacing = 10 * 60;
    const unsigned int nInterval = nTargetTimespan / nTargetSpacing;

    // Genesis block
    if (pindexLast == NULL)
        return bnProofOfWorkLimit.GetCompact();

    // Only change once per interval
    if ((pindexLast->nHeight+1) % nInterval != 0)
        return pindexLast->nBits;

    // Go back by what we want to be 14 days worth of blocks
    const CBlockIndex* pindexFirst = pindexLast;
    for (int i = 0; pindexFirst && i < nInterval-1; i++)
        pindexFirst = pindexFirst->pprev;
    assert(pindexFirst);

    // Limit adjustment step
    unsigned int nActualTimespan = pindexLast->nTime - pindexFirst->nTime;
    printf("  nActualTimespan = %d  before bounds\n", nActualTimespan);
    if (nActualTimespan < nTargetTimespan/4)
        nActualTimespan = nTargetTimespan/4;
    if (nActualTimespan > nTargetTimespan*4)
        nActualTimespan = nTargetTimespan*4;

    // Retarget
    CBigNum bnNew;
    bnNew.SetCompact(pindexLast->nBits);
    bnNew *= nActualTimespan;
    bnNew /= nTargetTimespan;

    if (bnNew > bnProofOfWorkLimit)
        bnNew = bnProofOfWorkLimit;

    /// debug print
    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());

    return bnNew.GetCompact();
}


On line 677 we can see the block reward for bitcoin

Code:
int64 nSubsidy = 50 * COIN;

This was the initial block reward for bitcoin minting a new block would yield a reward of 50 bitcoin to the lucky miner at this time CPU is thought to have been the only mining that was available though as there has been research into this and thoughts are GPU mining did not surface until around 2011 time.

Every 4 years or 210,000 blocks bitcoin undergoes what is called the halving.  Where block reward subsidy is halved starting from 50 bitcoin the protocol follows the following structure in the codebase.  

Code:
// Subsidy is cut in half every 4 years
    nSubsidy >>= (nBestHeight / 210000);

The estimated next date for bitcoin halving is 24 May 2020 09:01:59

Currently the block reward is 12.5 Bitcoins this will drop to 6.25 bitcoins around this time.  
Current information on bitcoin : Correct at time of writing..

Code:
Total Bitcoins in circulation:
17,397,963
Total Bitcoins to ever be produced:
21,000,000
Percentage of total Bitcoins mined:
82.85%
Total Bitcoins left to mine:
3,602,038
Total Bitcoins left to mine until next blockhalf:
977,038
Bitcoin price (USD):
$4,246.80
Market capitalization (USD):
$73,885,667,145.00
Bitcoins generated per day:
1,800
Bitcoin inflation rate per annum:
3.85%
Bitcoin inflation rate per annum at next block halving event:
1.80%
Bitcoin inflation per day (USD):
$7,644,240
Bitcoin inflation until next blockhalf event based on current price (USD):
$4,149,282,855
Total blocks:
551,837
Blocks until mining reward is halved:
78,163
Total number of block reward halvings:
2
Approximate block generation time:
10.00 minutes
Approximate blocks generated per day:
144
Difficulty:
6,653,303,141,406


The bitcoin difficulty re-target is also part of this code :

Code:

 const unsigned int nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
    const unsigned int nTargetSpacing = 10 * 60;
    const unsigned int nInterval = nTargetTimespan / nTargetSpacing;

    // Genesis block
    if (pindexLast == NULL)
        return bnProofOfWorkLimit.GetCompact();

    // Only change once per interval
    if ((pindexLast->nHeight+1) % nInterval != 0)
        return pindexLast->nBits;

    // Go back by what we want to be 14 days worth of blocks
    const CBlockIndex* pindexFirst = pindexLast;
    for (int i = 0; pindexFirst && i < nInterval-1; i++)
        pindexFirst = pindexFirst->pprev;
    assert(pindexFirst);

    // Limit adjustment step
    unsigned int nActualTimespan = pindexLast->nTime - pindexFirst->nTime;
    printf("  nActualTimespan = %d  before bounds\n", nActualTimespan);
    if (nActualTimespan < nTargetTimespan/4)
        nActualTimespan = nTargetTimespan/4;
    if (nActualTimespan > nTargetTimespan*4)
        nActualTimespan = nTargetTimespan*4;

    // Retarget
    CBigNum bnNew;
    bnNew.SetCompact(pindexLast->nBits);
    bnNew *= nActualTimespan;
    bnNew /= nTargetTimespan;

    if (bnNew > bnProofOfWorkLimit)
        bnNew = bnProofOfWorkLimit;

    /// debug print
    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());

    return bnNew.GetCompact();
}


In this process we see the following

First is to translate the bits of block N + 2015 to a BigNum target and then calculate the timespan between blocks N and N +2015 into a inumber of seconds.

We would then multiply the old target by the timespan then to divide the result by the timespan ie. 2 weeks = 1209600 s this integer is arithmetic so it is rounded down and the result would be the new target.

The difficulty retarget is such that is should retarget ever 2 weeks you can check the difficulty retargeting on charts such as.

https://fork.lol/pow/retarget
https://bitcoinwisdom.com/bitcoin/difficulty

In part 2 we will look at the networking and P2P structure of the codebase,

Please feel free to contribute to this project it will become a great resource for people to reference without having to trawl the internet for information.

<3 Bitcoin
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction. Advertise here.
MagicByt3
Full Member
***
Offline Offline

Activity: 378
Merit: 198


View Profile
November 28, 2018, 04:46:04 PM
Last edit: December 12, 2018, 02:14:44 PM by MagicByt3
Merited by o_e_l_e_o (2), xtraelv (1)
 #2

Block Checking & Submit Blocks

File - main.cpp
Line -  1154 -1295

Code:
bool CBlock::CheckBlock() const
{
    These are checks that are independent of context
    that can be verified before saving an orphan block.

    // This section checks the Size limits

Code:
   if (vtx.empty() || vtx.size() > MAX_SIZE || ::GetSerializeSize(*this, SER_DISK) > MAX_SIZE)
        return error("CheckBlock() : size limits failed");

    // This section of code if for checking the timestamp of the block, a timestamp is valid if it is greater than the median timestamp of last 11 blocks and less than the network-adjusted time + 2 hours

Code:
   if (nTime > GetAdjustedTime() + 2 * 60 * 60)
        return error("CheckBlock() : block timestamp too far in the future");

    // This section checks to make sure the first transaction is a coinbase transaction and everything else is not a coinbase TX

Code:
   if (vtx.empty() || !vtx[0].IsCoinBase())
        return error("CheckBlock() : first tx is not coinbase");
    for (int i = 1; i < vtx.size(); i++)
        if (vtx[i].IsCoinBase())
            return error("CheckBlock() : more than one coinbase");

    // Check transactions

Code:
   foreach(const CTransaction& tx, vtx)
        if (!tx.CheckTransaction())
            return error("CheckBlock() : CheckTransaction failed");

    // This section checks that the proof of work matches claimed amount

Code:
   if (CBigNum().SetCompact(nBits) > bnProofOfWorkLimit)
        return error("CheckBlock() : nBits below minimum work");
    if (GetHash() > CBigNum().SetCompact(nBits).getuint256())
        return error("CheckBlock() : hash doesn't match nBits");

    // It is then passed to check the merkleroot

Code:
   if (hashMerkleRoot != BuildMerkleTree())
        return error("CheckBlock() : hashMerkleRoot mismatch");

    return true;
}

Now the code will check for AcceptBlock by checking the following aspects.

bool CBlock::AcceptBlock()

    // In this section the code performs a check for duplicate block.

  
Code:
 uint256 hash = GetHash();
    if (mapBlockIndex.count(hash))
        return error("AcceptBlock() : block already in mapBlockIndex");

    // Here the code will get the previous block index

    
Code:
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashPrevBlock);
    if (mi == mapBlockIndex.end())
        return error("AcceptBlock() : prev block not found");
    CBlockIndex* pindexPrev = (*mi).second;

    // It will then check the timestamp against previous block

  
Code:
if (nTime <= pindexPrev->GetMedianTimePast())
        return error("AcceptBlock() : block's timestamp is too early");

    // It then performs a check on the proof of work

  
Code:
if (nBits != GetNextWorkRequired(pindexPrev))
        return error("AcceptBlock() : incorrect proof of work");

    // Here the code will write the block to history file

 
Code:
 if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK)))
        return error("AcceptBlock() : out of disk space");
    unsigned int nFile;
    unsigned int nBlockPos;
    if (!WriteToDisk(!fClient, nFile, nBlockPos))
        return error("AcceptBlock() : WriteToDisk failed");
    if (!AddToBlockIndex(nFile, nBlockPos))
        return error("AcceptBlock() : AddToBlockIndex failed");

    if (hashBestChain == hash)
        RelayInventory(CInv(MSG_BLOCK, hash));

The next section is commented out of the code and I am still looking for some references for the code below and relations to VAtoms.

    // // Add atoms to user reviews for coins created

    
Code:
// vector<unsigned char> vchPubKey;
    // if (ExtractPubKey(vtx[0].vout[0].scriptPubKey, false, vchPubKey))
    // {
    //     unsigned short nAtom = GetRand(USHRT_MAX - 100) + 100;
    //     vector<unsigned short> vAtoms(1, nAtom);
    //     AddAtomsAndPropagate(Hash(vchPubKey.begin(), vchPubKey.end()), vAtoms, true);
    // }

    return true;
}

Next the code looks to process the block by the following.

bool ProcessBlock(CNode* pfrom, CBlock* pblock)

    // Check for duplicate
  
Code:
uint256 hash = pblock->GetHash();
    if (mapBlockIndex.count(hash))
        return error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString().substr(0,14).c_str());
    if (mapOrphanBlocks.count(hash))
        return error("ProcessBlock() : already have block (orphan) %s", hash.ToString().substr(0,14).c_str());

    // Preliminary checks
Code:
   if (!pblock->CheckBlock())
    {
        delete pblock;
        return error("ProcessBlock() : CheckBlock FAILED");
    }

    // If don't already have its previous block, shunt it off to holding area until we get it
  
Code:
if (!mapBlockIndex.count(pblock->hashPrevBlock))
    {
        printf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString().substr(0,14).c_str());
        mapOrphanBlocks.insert(make_pair(hash, pblock));
        mapOrphanBlocksByPrev.insert(make_pair(pblock->hashPrevBlock, pblock));

        // Ask this guy to fill in what we're missing
  
Code:
    if (pfrom)
            pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), GetOrphanRoot(pblock));
        return true;
    }

    // Store to disk
 
Code:
  if (!pblock->AcceptBlock())
    {
        delete pblock;
        return error("ProcessBlock() : AcceptBlock FAILED");
    }
    delete pblock;

    // Recursively process any orphan blocks that depended on this one
  
Code:
 vector<uint256> vWorkQueue;
    vWorkQueue.push_back(hash);
    for (int i = 0; i < vWorkQueue.size(); i++)
    {
        uint256 hashPrev = vWorkQueue[i];
        for (multimap<uint256, CBlock*>::iterator mi = mapOrphanBlocksByPrev.lower_bound(hashPrev);
             mi != mapOrphanBlocksByPrev.upper_bound(hashPrev);
             ++mi)
        {
            CBlock* pblockOrphan = (*mi).second;
            if (pblockOrphan->AcceptBlock())
                vWorkQueue.push_back(pblockOrphan->GetHash());
            mapOrphanBlocks.erase(pblockOrphan->GetHash());
            delete pblockOrphan;
        }
        mapOrphanBlocksByPrev.erase(hashPrev);
    }

At this point the miner would be very happy! as the block has passed the checked and can be called Valid.
The code then prints below :

Code:
   printf("ProcessBlock: ACCEPTED\n");
    return true;



<3 Bitcoin
MagicByt3
Full Member
***
Offline Offline

Activity: 378
Merit: 198


View Profile
November 28, 2018, 04:46:57 PM
Last edit: December 03, 2018, 01:42:24 PM by MagicByt3
 #3

Reserved Part 3 - POW Checking

<3 Bitcoin
MagicByt3
Full Member
***
Offline Offline

Activity: 378
Merit: 198


View Profile
December 03, 2018, 01:38:37 PM
Last edit: December 13, 2018, 03:17:47 PM by MagicByt3
 #4

Part 4 - BitcoinMiner - In this section of code we can see the working of the early client and how the block is processed by the client before being submitted to the network as a valid POW.

File - main.cpp
lines 2168 - 2390
Reference - https://github.com/bitcoin/bitcoin/releases/tag/v0.1.5

//////////////////////////////////////////////////////////////////////////////
//
// BitcoinMiner
//

Code:
int FormatHashBlocks(void* pbuffer, unsigned int len)
{
    unsigned char* pdata = (unsigned char*)pbuffer;
    unsigned int blocks = 1 + ((len + 8) / 64);
    unsigned char* pend = pdata + 64 * blocks;
    memset(pdata + len, 0, 64 * blocks - len);
    pdata[len] = 0x80;
    unsigned int bits = len * 8;
    pend[-1] = (bits >> 0) & 0xff;
    pend[-2] = (bits >> 8) & 0xff;
    pend[-3] = (bits >> 16) & 0xff;
    pend[-4] = (bits >> 24) & 0xff;
    return blocks;
}


Code:
using CryptoPP::ByteReverse;
static int detectlittleendian = 1;

void BlockSHA256(const void* pin, unsigned int nBlocks, void* pout)
{
    unsigned int* pinput = (unsigned int*)pin;
    unsigned int* pstate = (unsigned int*)pout;

    CryptoPP::SHA256::InitState(pstate);

    if (*(char*)&detectlittleendian != 0)
    {
        for (int n = 0; n < nBlocks; n++)
        {
            unsigned int pbuf[16];
            for (int i = 0; i < 16; i++)
                pbuf[i] = ByteReverse(pinput[n * 16 + i]);
            CryptoPP::SHA256::Transform(pstate, pbuf);
        }
        for (int i = 0; i < 8; i++)
            pstate[i] = ByteReverse(pstate[i]);
    }
    else
    {
        for (int n = 0; n < nBlocks; n++)
            CryptoPP::SHA256::Transform(pstate, pinput + n * 16);
    }
}


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);
        }

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


        // This section will create the coinbase transaction (TX)
        //
      
Code:
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;

       
        // In this section we see the code to create a new block.
        //
      
Code:
 auto_ptr<CBlock> pblock(new CBlock());
        if (!pblock.get())
            return false;

        // Again this section will create a coinbase transaction (TX)
        //
      
Code:
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;

       
        //Here we see the creation of a new block
        
      
Code:
 auto_ptr<CBlock> pblock(new CBlock());
        if (!pblock.get())
            return false;

        // We must first add our coinbase tx as first transaction

        
Code:
pblock->vtx.push_back(txNew);

        // The code then collect's the latest transactions into the block

    
Code:
  int64 nFees = 0;
        CRITICAL_BLOCK(cs_main)
        CRITICAL_BLOCK(cs_mapTransactions)
        {
            CTxDB txdb("r");
            map<uint256, CTxIndex> mapTestPool;
            vector<char> vfAlreadyAdded(mapTransactions.size());
            bool fFoundSomething = true;
            unsigned int nBlockSize = 0;
            while (fFoundSomething && nBlockSize < MAX_SIZE/2)
            {
                fFoundSomething = false;
                unsigned int n = 0;
                for (map<uint256, CTransaction>::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

                    
Code:
int64 nMinFee = tx.GetMinFee(pblock->vtx.size() < 100);

                    map<uint256, CTxIndex> 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
        //
      
Code:
 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
        //
      
Code:
 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 for valid proof of work found
                  
Code:
 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
                
Code:
  if (!AddKey(key))
                        return false;
                    key.MakeNewKey();
                   // Process this block the same as if we had received it from another node
                  
Code:
 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
          
Code:
 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;
}

** Work in progress **

<3 Bitcoin
MagicByt3
Full Member
***
Offline Offline

Activity: 378
Merit: 198


View Profile
December 14, 2018, 12:19:31 AM
Last edit: January 03, 2019, 06:17:19 PM by MagicByt3
 #5

Original Op Codes - Bitcoin includes a script system for transactions.

In simple, a script is a just a list of instructions that is recorded with each transaction that describe how the next user wanting to spend the Bitcoins being transferred can gain access to them.

The script for a Bitcoin transaction to a Bitcoin address simply enduce future spending of the bitcoins with two things that must be provided.
 
    1. a public key that when hashed results in the destination address in the script.
    2. a signature to prove ownership of the private key corresponding to the public key.

Definition

Operation codes from the Bitcoin Script language which push data or perform functions within a pubkey script or signature script.

OP Code descriptions taken from https://en.bitcoin.it/wiki/
Op Code list taken from

File - script.h
@Lines 7-293

Code:
enum
{
    SIGHASH_ALL = 1,
    SIGHASH_NONE = 2,
    SIGHASH_SINGLE = 3,
    SIGHASH_ANYONECANPAY = 0x80,
};



Code:
enum opcodetype
{
    // push value
    OP_0=0,
    OP_FALSE=OP_0,       - Empty array of bytes pushed onto the stack. This is not classed as an no-op as a item is added to stack.
    OP_PUSHDATA1=76, - The next byte will contain the number of bytes to be pushed to the stack.
    OP_PUSHDATA2,        - The next two bytes contain the number of bytes to be pushed to the stack in little endian order.
    OP_PUSHDATA4,        - The next four bytes contain the number of bytes to be pushed to the stack in little endian order.
    OP_1NEGATE,            - The number -1 is pushed onto the stack.
    OP_RESERVED,          - Transaction is invalid unless occurring in an un-executed OP_IF branch
    OP_1,
    OP_TRUE=OP_1,       - The number 1 is pushed onto the stack.
    OP_2,
    OP_3,
    OP_4,
    OP_5,
    OP_6,
    OP_7,
    OP_8,
    OP_9,
    OP_10,
    OP_11,
    OP_12,
    OP_13,
    OP_14,
    OP_15,
    OP_16,
 
Code:
// control
    OP_NOP,          - Does nothing.
    OP_VER,          - Transaction is invalid unless occurring in an un-executed OP_IF branch
    OP_IF,              - <expression> if [statements] [else [statements]]* endif If the top stack value is not False the statements are executed. The top stack value is removed.
    OP_NOTIF,       - <expression> notif [statements] [else [statements]]* endif  If the top stack value is False the statements are executed. The top stack value is removed.
    OP_VERIF,       - True / false - Marks transaction as invalid if top stack value is not true the top stack value is removed.
    OP_VERNOTIF,- Transaction is invalid even when occurring in an un-executed OP_IF branch
    OP_ELSE,         - <expression> if [statements] [else [statements]]* endif If the preceding OP_IF or OP_NOTIF or OP_ELSE was not executed then these statements are and if the preceding
                               OP_IF or OP_NOTIF or OP_ELSE was  executed then these statements are not.
    OP_ENDIF,       - <expression> if [statements] [else [statements]]* endif Ends an if/else block. All blocks must end, or the transaction is invalid. An OP_ENDIF without OP_IF earlier is also invalid.
    OP_VERIFY,     -   True / false Marks transaction as invalid if top stack value is not true. The top stack value is removed.
    OP_RETURN,   - Marks transaction as invalid. A standard way of attaching extra data to transactions is to add a zero-value output with a scriptPubKey consisting of OP_RETURN followed by exactly one pushdata op. Such outputs are provably undependable, reducing their cost to the network. Currently it is usually considered non-standard (though valid) for a transaction to have more than one OP_RETURN output or an OP_RETURN output with more than one pushdata op.

 
Code:
// stack ops
    OP_TOALTSTACK,       [Input = x1] [Output (alt)x] = Puts the input onto the top of the alt stack. Removes it from the main stack.
    OP_FROMALTSTACK,  [Input = (alt)x1] [Output x1]  = Puts the input onto the top of the main stack. Removes it from the alt stack.
    OP_2DROP,                Removes the top stack item.
    OP_2DUP,                  Duplicates the top two stack items.
    OP_3DUP,                  Duplicates the top three stack items.
    OP_2OVER,                Copies the pair of items two spaces back in the stack to the front.
    OP_2ROT,                  The fifth and sixth items back are moved to the top of the stack.
    OP_2SWAP,               Swaps the top two pairs of items.
    OP_IFDUP,                 If the top stack value is not 0, duplicate it.
    OP_DEPTH,                Puts the number of stack items onto the stack.
    OP_DROP,                 Removes the top stack item.
    OP_DUP,                   Duplicates the top stack item.
    OP_NIP,                    Removes the second-to-top stack item.
    OP_OVER,                Copies the second-to-top stack item to the top.
    OP_PICK,                 The item n back in the stack is copied to the top.
    OP_ROLL,                The item n back in the stack is moved to the top.
    OP_ROT,                 The top three items on the stack are rotated to the left.
    OP_SWAP,              Swaps the top two pairs of items.
    OP_TUCK,              The item at the top of the stack is copied and inserted before the second-to-top item.

  
Code:
// splice ops
    OP_CAT,          Concatenates two strings. [b]disabled. [/b]
    OP_SUBSTR,   Returns a section of a string. [b]disabled.[/b]
    OP_LEFT,        Keeps only characters left of the specified point in a string.[b] disabled. [/b]
    OP_RIGHT,     Keeps only characters right of the specified point in a string. [b]disabled. [/b]
    OP_SIZE,        Pushes the string length of the top element of the stack.

Code:
   // bit logic
    OP_INVERT,             Flips all of the bits in the input. [b]disabled.[/b]
    OP_AND,                 Boolean and between each bit in the inputs. [b]disabled. [/b]
    OP_OR,                   Boolean or between each bit in the inputs. [b]disabled. [/b]
    OP_XOR,                 Boolean exclusive or between each bit in the inputs. [b]disabled[/b].
    OP_EQUAL,             Returns 1 if the inputs are exactly equal, 0 otherwise.
    OP_EQUALVERIFY,  Same as OP_EQUAL, but runs OP_VERIFY afterward.
    OP_RESERVED1,
    OP_RESERVED2,

Code:
   // numeric
    OP_1ADD,                  1 is added to the input.
    OP_1SUB,                   1 is subtracted from the input.
    OP_2MUL,                   The input is multiplied by 2. [b]disabled. [/b]
    OP_2DIV,                    The input is divided by 2. [b]disabled. [/b]
    OP_NEGATE,               The sign of the input is flipped.
    OP_ABS,                     The input is made positive.
    OP_NOT,                     If the input is 0 or 1, it is flipped. Otherwise the output will be 0.
    OP_0NOTEQUAL,        Returns 0 if the input is 0. 1 otherwise.

    OP_ADD,
    OP_SUB,
    OP_MUL,
    OP_DIV,
    OP_MOD,
    OP_LSHIFT,
    OP_RSHIFT,

    OP_BOOLAND,
    OP_BOOLOR,
    OP_NUMEQUAL,
    OP_NUMEQUALVERIFY,
    OP_NUMNOTEQUAL,
    OP_LESSTHAN,
    OP_GREATERTHAN,
    OP_LESSTHANOREQUAL,
    OP_GREATERTHANOREQUAL,
    OP_MIN,
    OP_MAX,

    OP_WITHIN,
Code:
   // crypto
    OP_RIPEMD160,
    OP_SHA1,
    OP_SHA256,
    OP_HASH160,
    OP_HASH256,
    OP_CODESEPARATOR,
    OP_CHECKSIG,
    OP_CHECKSIGVERIFY,
    OP_CHECKMULTISIG,
    OP_CHECKMULTISIGVERIFY,

 
Code:
  // multi-byte opcodes
    OP_SINGLEBYTE_END = 0xF0,
    OP_DOUBLEBYTE_BEGIN = 0xF000,
 
Code:
// template matching params
    OP_PUBKEY,
    OP_PUBKEYHASH,

    OP_INVALIDOPCODE = 0xFFFF,
};


Code:
inline const char* GetOpName(opcodetype opcode)
{
    switch (opcode)
    {
    // push value
    case OP_0                      : return "0";
    case OP_PUSHDATA1              : return "OP_PUSHDATA1";
    case OP_PUSHDATA2              : return "OP_PUSHDATA2";
    case OP_PUSHDATA4              : return "OP_PUSHDATA4";
    case OP_1NEGATE                : return "-1";
    case OP_RESERVED               : return "OP_RESERVED";
    case OP_1                      : return "1";
    case OP_2                      : return "2";
    case OP_3                      : return "3";
    case OP_4                      : return "4";
    case OP_5                      : return "5";
    case OP_6                      : return "6";
    case OP_7                      : return "7";
    case OP_8                      : return "8";
    case OP_9                      : return "9";
    case OP_10                     : return "10";
    case OP_11                     : return "11";
    case OP_12                     : return "12";
    case OP_13                     : return "13";
    case OP_14                     : return "14";
    case OP_15                     : return "15";
    case OP_16                     : return "16";

  
Code:
// control
    case OP_NOP                    : return "OP_NOP";
    case OP_VER                    : return "OP_VER";
    case OP_IF                     : return "OP_IF";
    case OP_NOTIF                  : return "OP_NOTIF";
    case OP_VERIF                  : return "OP_VERIF";
    case OP_VERNOTIF               : return "OP_VERNOTIF";
    case OP_ELSE                   : return "OP_ELSE";
    case OP_ENDIF                  : return "OP_ENDIF";
    case OP_VERIFY                 : return "OP_VERIFY";
    case OP_RETURN                 : return "OP_RETURN";
Code:
  // stack ops
    case OP_TOALTSTACK             : return "OP_TOALTSTACK";
    case OP_FROMALTSTACK           : return "OP_FROMALTSTACK";
    case OP_2DROP                  : return "OP_2DROP";
    case OP_2DUP                   : return "OP_2DUP";
    case OP_3DUP                   : return "OP_3DUP";
    case OP_2OVER                  : return "OP_2OVER";
    case OP_2ROT                   : return "OP_2ROT";
    case OP_2SWAP                  : return "OP_2SWAP";
    case OP_IFDUP                  : return "OP_IFDUP";
    case OP_DEPTH                  : return "OP_DEPTH";
    case OP_DROP                   : return "OP_DROP";
    case OP_DUP                    : return "OP_DUP";
    case OP_NIP                    : return "OP_NIP";
    case OP_OVER                   : return "OP_OVER";
    case OP_PICK                   : return "OP_PICK";
    case OP_ROLL                   : return "OP_ROLL";
    case OP_ROT                    : return "OP_ROT";
    case OP_SWAP                   : return "OP_SWAP";
    case OP_TUCK                   : return "OP_TUCK";

 
Code:
  // splice ops
    case OP_CAT                    : return "OP_CAT";
    case OP_SUBSTR                 : return "OP_SUBSTR";
    case OP_LEFT                   : return "OP_LEFT";
    case OP_RIGHT                  : return "OP_RIGHT";
    case OP_SIZE                   : return "OP_SIZE";
 
Code:
 // bit logic
    case OP_INVERT                 : return "OP_INVERT";
    case OP_AND                    : return "OP_AND";
    case OP_OR                     : return "OP_OR";
    case OP_XOR                    : return "OP_XOR";
    case OP_EQUAL                  : return "OP_EQUAL";
    case OP_EQUALVERIFY            : return "OP_EQUALVERIFY";
    case OP_RESERVED1              : return "OP_RESERVED1";
    case OP_RESERVED2              : return "OP_RESERVED2";

Code:
   // numeric
    case OP_1ADD                   : return "OP_1ADD";
    case OP_1SUB                   : return "OP_1SUB";
    case OP_2MUL                   : return "OP_2MUL";
    case OP_2DIV                   : return "OP_2DIV";
    case OP_NEGATE                 : return "OP_NEGATE";
    case OP_ABS                    : return "OP_ABS";
    case OP_NOT                    : return "OP_NOT";
    case OP_0NOTEQUAL              : return "OP_0NOTEQUAL";
    case OP_ADD                    : return "OP_ADD";
    case OP_SUB                    : return "OP_SUB";
    case OP_MUL                    : return "OP_MUL";
    case OP_DIV                    : return "OP_DIV";
    case OP_MOD                    : return "OP_MOD";
    case OP_LSHIFT                 : return "OP_LSHIFT";
    case OP_RSHIFT                 : return "OP_RSHIFT";
    case OP_BOOLAND                : return "OP_BOOLAND";
    case OP_BOOLOR                 : return "OP_BOOLOR";
    case OP_NUMEQUAL               : return "OP_NUMEQUAL";
    case OP_NUMEQUALVERIFY         : return "OP_NUMEQUALVERIFY";
    case OP_NUMNOTEQUAL            : return "OP_NUMNOTEQUAL";
    case OP_LESSTHAN               : return "OP_LESSTHAN";
    case OP_GREATERTHAN            : return "OP_GREATERTHAN";
    case OP_LESSTHANOREQUAL        : return "OP_LESSTHANOREQUAL";
    case OP_GREATERTHANOREQUAL     : return "OP_GREATERTHANOREQUAL";
    case OP_MIN                    : return "OP_MIN";
    case OP_MAX                    : return "OP_MAX";
    case OP_WITHIN                 : return "OP_WITHIN";
 
Code:
// crypto
    case OP_RIPEMD160              : return "OP_RIPEMD160";
    case OP_SHA1                   : return "OP_SHA1";
    case OP_SHA256                 : return "OP_SHA256";
    case OP_HASH160                : return "OP_HASH160";
    case OP_HASH256                : return "OP_HASH256";
    case OP_CODESEPARATOR          : return "OP_CODESEPARATOR";
    case OP_CHECKSIG               : return "OP_CHECKSIG";
    case OP_CHECKSIGVERIFY         : return "OP_CHECKSIGVERIFY";
    case OP_CHECKMULTISIG          : return "OP_CHECKMULTISIG";
    case OP_CHECKMULTISIGVERIFY    : return "OP_CHECKMULTISIGVERIFY";

  
Code:
 // multi-byte opcodes
    case OP_SINGLEBYTE_END         : return "OP_SINGLEBYTE_END";
    case OP_DOUBLEBYTE_BEGIN       : return "OP_DOUBLEBYTE_BEGIN";
    case OP_PUBKEY                 : return "OP_PUBKEY";
    case OP_PUBKEYHASH             : return "OP_PUBKEYHASH";



    case OP_INVALIDOPCODE          : return "OP_INVALIDOPCODE";
    default:
        return "UNKNOWN_OPCODE";
    }
};

<3 Bitcoin
100bitcoin
Sr. Member
****
Offline Offline

Activity: 677
Merit: 343


View Profile
December 14, 2018, 07:33:11 PM
 #6

Fantastic work. Could you please point me out to the part that defines total supply to be 21m?

MagicByt3
Full Member
***
Offline Offline

Activity: 378
Merit: 198


View Profile
December 14, 2018, 11:14:10 PM
Last edit: December 14, 2018, 11:31:45 PM by MagicByt3
Merited by vit05 (1)
 #7

in bitcoin fixed point math is used to calculate the block subsidies.

Code:
int64 CBlock::GetBlockValue(int64 nFees) const
{
    int64 nSubsidy = 50 * COIN;

    // Subsidy is cut in half every 4 years
    nSubsidy >>= (nBestHeight / 210000);

This BIP might also be of some use to you.

https://github.com/bitcoin/bips/blob/master/bip-0042.mediawiki

In later versions of the codebase  V0.5.1 we can see this defined as a int64 value in main.h file near the top.

as :  static const int64 MAX_MONEY = 21000000 * COIN;

Code:
static const unsigned int MAX_BLOCK_SIZE = 1000000;
static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
static const int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
static const int64 COIN = 100000000;
static const int64 CENT = 1000000;
static const int64 MIN_TX_FEE = 50000;
static const int64 MIN_RELAY_TX_FEE = 10000;
static const int64 MAX_MONEY = 21000000 * COIN;
inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
static const int COINBASE_MATURITY = 100;
// Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp.
static const int LOCKTIME_THRESHOLD = 500000000; // Tue Nov  5 00:53:20 1985 UTC

<3 Bitcoin
Velkro
Legendary
*
Offline Offline

Activity: 2002
Merit: 1011


<3 Vanity Addresses :)


View Profile
December 15, 2018, 03:08:06 AM
 #8

Understanding The Satoshi Codebase : Bitcoin V0.1.5
Oh man, posting this in Beginners & Help Cheesy it fits anywhere but not here. Its for computer scientist only which is rare case in overall public.
Anyway good guide, detailed, well formatted. GJ.

MagicByt3
Full Member
***
Offline Offline

Activity: 378
Merit: 198


View Profile
December 15, 2018, 01:38:41 PM
 #9

Understanding The Satoshi Codebase : Bitcoin V0.1.5
Oh man, posting this in Beginners & Help Cheesy it fits anywhere but not here. Its for computer scientist only which is rare case in overall public.
Anyway good guide, detailed, well formatted. GJ.

Thank you,  I was thinking of asking the topic to be moved to a more suitable area of the forum say "technical" section.

I thought posting here as a guide could serve as a reference to the early codebase and allow people to try to understand how bicoin works under the hood as they say.

But I do agree possibly the beginner section is not such a good place for the topic.

Magic.

<3 Bitcoin
MagicByt3
Full Member
***
Offline Offline

Activity: 378
Merit: 198


View Profile
January 03, 2019, 06:10:17 PM
 #10

Updating the OP_Code sections to include the descriptions of each OP code.
Looking for collaboration on this to try have the entire codebase in sections if anyone is willing to help with this please send me a PM to being collaboration

<3 Bitcoin
darosior
Full Member
***
Offline Offline

Activity: 210
Merit: 257



View Profile WWW
January 04, 2019, 12:47:11 PM
 #11

Updating the OP_Code sections to include the descriptions of each OP code.
Looking for collaboration on this to try have the entire codebase in sections if anyone is willing to help with this please send me a PM to being collaboration
Hi,

They are already described here, why do you want to redescribe them ?

MagicByt3
Full Member
***
Offline Offline

Activity: 378
Merit: 198


View Profile
January 04, 2019, 05:31:03 PM
 #12

Updating the OP_Code sections to include the descriptions of each OP code.
Looking for collaboration on this to try have the entire codebase in sections if anyone is willing to help with this please send me a PM to being collaboration
Hi,

They are already described here, why do you want to redescribe them ?

I am going to cover the entire early code base in one topic so people don't need to hunt about to find the things they want to know.
I think it would be a good way for people to visualize bitcoin and understand the underlying code behind it.

Its not just about op codes the entire codebase will be layed out here to help people understand it a little better or to allow a quick reference point  for questions regarding all things bitcoin.

<3 Bitcoin
MagicByt3
Full Member
***
Offline Offline

Activity: 378
Merit: 198


View Profile
June 23, 2019, 08:13:20 PM
Last edit: June 24, 2019, 12:28:51 PM by MagicByt3
 #13

A quick breakdown of a raw block and all it's parts broken down in a much simpler way to understand.

1. BlockHeader


Code:
Block headers
Version: 536870912
Prev block: 0000000000000000002B4317ED9B09E5D629E9763E727E895E296418D69F2C70
Merkle root: AA5FB4AFB0154D2BDD3315E074F219351FDF13908F1C515E07BE12124A3D3760
Timestamp December 31, 2018, 14:07:48 +0000
Bits: 17371EF4
Nonce: 21


2. Raw headers in hex


Code:
00000020702C9FD61864295E897E723E76E929D6E5099BED17432B000000000000000000AA5FB4AFB0154D2BDD3315E074F219351FDF13908F1C515E07BE12124A3D3760B4222A5CF41E371715000000


3. Coinbase transaction

Code:
01000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0487654321FFFFFFFF0100F90295000000001976A914DC863734A218BFE83EF770EE9D41A27F824A6E5688AC00000000


4. Computed block hash
Code:
CB78229F85ABD927B71954CB65905F5AC9F12DBC512D2FE9CD6C7580AA814C62000000000000000000371EF4FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

Now lets say the nonce value is to move to 22.

The new computed value for Block Hash would become

Code:
77F6BF7C376A4346BD28FFAB917E2B1327B8CFD77F70B986A6421FC06A21CF56


Now lets break down the Raw header in Hex


Code:
00000020702C9FD61864295E897E723E76E929D6E5099BED17432B000000000000000000AA5FB4AFB0154D2BDD3315E074F219351FDF13908F1C515E07BE12124A3D3760B4222A5CF41E371715000000

Code:
00000020 = Block Version Number

702C9FD61864295E897E723E76E929D6E5099BED17432B000000000000000000 = Previous Block Hash

AA5FB4AFB0154D2BDD3315E074F219351FDF13908F1C515E07BE12124A3D3760 = Merkel Root

B4222A5C = Time Stamp

F41E3717 = Bits Value Diff target

15000000 = Nonce


Each time the hash changes until the block hash is equal to or below this number in order to be valid.

Code:
000000000000000000371EF4FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

** Work In Progress **

<3 Bitcoin
pooya87
Legendary
*
Offline Offline

Activity: 1848
Merit: 2111


Remember tonight for it's the beginning of forever


View Profile
June 24, 2019, 03:58:36 AM
 #14

A quick breakdown of the genesis block.

sorry but this post doesn't make any sense!
first of all what you are posting below this is not genesis block.
secondly the block header you posted doesn't exist since the block that has 0<...>02B431... as its previous block is block #556397 which has a different everything from version to merkle root.
and finally i think you made a mistake with the hash of the header since hash (2x SHA256) of what you posted in #2 is:
Code:
624c81aa80756ccde92f2d51bc2df1c95a5f9065cb5419b727d9ab859f2278cb
but the value you posted in #4 is not even close to this, not even 32 byte (it is 64 bytes)

MagicByt3
Full Member
***
Offline Offline

Activity: 378
Merit: 198


View Profile
June 24, 2019, 12:31:05 PM
Merited by TheWolf666 (1)
 #15

A quick breakdown of the genesis block.

sorry but this post doesn't make any sense!
first of all what you are posting below this is not genesis block.
secondly the block header you posted doesn't exist since the block that has 0<...>02B431... as its previous block is block #556397 which has a different everything from version to merkle root.
and finally i think you made a mistake with the hash of the header since hash (2x SHA256) of what you posted in #2 is:
Code:
624c81aa80756ccde92f2d51bc2df1c95a5f9065cb5419b727d9ab859f2278cb
but the value you posted in #4 is not even close to this, not even 32 byte (it is 64 bytes)


Thanks for pointing that out it should have been called the raw block not geneisis block was quite tired when posting.

I will fix the above and I think you are correct I did make a mistake with the header thank you for pointing this out @pooya87

<3 Bitcoin
TheWolf666
Full Member
***
Offline Offline

Activity: 420
Merit: 123


Author & Prog of Franc / Prog of Kryptofranc


View Profile WWW
July 01, 2019, 10:36:03 AM
Merited by MagicByt3 (1)
 #16

There is no code that limits the subsidy... it is mathematically decided.

Since the amount rewarded by Bitcoin is /2 every 210000 blocks (about 4 years), this reward will reach zero 34 years after the genesis approximately
You can refer to this table in order to have a better idea about how it happens.

https://en.bitcoin.it/wiki/Controlled_supply

So you will not find something like

Code:
if (height>21000000) then reward=0

Also the number of coins mined is not 21 Millions, it is an approximation. The real number is 20999999.97690000
But of course it is more convenient to round it to 21 Millions.

Fantastic work. Could you please point me out to the part that defines total supply to be 21m?

Author and Programmer: https://franc.eu.com
Programmer: https://kryptofranc.com
achow101
Moderator
Legendary
*
expert
Offline Offline

Activity: 1974
Merit: 2952


bc1qshxkrpe4arppq89fpzm6c0tpdvx5cfkve2c8kl


View Profile WWW
July 01, 2019, 04:56:34 PM
Merited by MagicByt3 (1)
 #17

So you will not find something like

Code:
if (height>21000000) then reward=0
Fun fact, you actually will find something like that.

Since halving an integer is the same as shifting all of the bits in the integer one bit to the right, the block of code that determines the block subsidy uses a right bit shift. The size of the integer being shifted is 64 bits, so after 64 bit shifts (so 64 halvings), the subsidy will be 0. However, this is not the case. After bit shifting 63 times, it is undefined behavior is C++ to shift it again for a 64th time. On many platforms, this will actually result in the entire 64 bit value wrapping around and returning to its original value which would cause the block subsidy to return to 50 Bitcoin on the 64th bit shift. So to prevent this from actually happening, there is a line that is like:
Code:
if (halvings >= 64) then reward = 0

This is described (along with several jokes) in BIP 42 (the BIP is an April fool's joke, but the bug it describes is very real and has been fixed). You can see the code for this here.

Pages: [1]
  Print  
 
Jump to:  

Sponsored by , a Bitcoin-accepting VPN.
Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!