DaCryptoRaccoon (OP)
|
|
November 28, 2018, 04:45:12 PM Last edit: November 28, 2018, 05:28:25 PM by MagicByt3 Merited by Symmetrick (36), ABCbits (21), LoyceV (10), AverageGlabella (10), Heisenberg_Hunter (3), Joel_Jantsen (2), vapourminer (1), Coin-1 (1), HCP (1), Last of the V8s (1), Piggy (1), REF (1), darosior (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.5Please only use V0.1.5 for this purpose. ================================================ Part 1. Genesis Block. Blockchain link : https://www.blockchain.com/btc/block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26fReference : File main.cpp Line 1467
// 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 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 : 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 :
////////////////////////////////////////////////////////////////////////////// // // 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 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. // 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.. 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 : 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/retargethttps://bitcoinwisdom.com/bitcoin/difficultyIn 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.
|
┏━━━━━━━━━━━━━━━━━┓ ┃ 𝔱𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔬𝔯ⱪ 𝔣𝔬𝔯 𝔶𝔬𝔲𝔯 𝔟𝔞𝔤𝔰 ┃ ┃ ➤21/M ┃ ┃ ███▓▓ ███▓▓ ███▓▓ ███▓▓┃
|
|
|
DaCryptoRaccoon (OP)
|
|
November 28, 2018, 04:46:04 PM Last edit: December 12, 2018, 02:14:44 PM by MagicByt3 Merited by ABCbits (6), o_e_l_e_o (2), xtraelv (1) |
|
Block Checking & Submit Blocks File - main.cpp Line - 1154 -1295 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 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 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 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 foreach(const CTransaction& tx, vtx) if (!tx.CheckTransaction()) return error("CheckBlock() : CheckTransaction failed"); // This section checks that the proof of work matches claimed amount 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 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. uint256 hash = GetHash(); if (mapBlockIndex.count(hash)) return error("AcceptBlock() : block already in mapBlockIndex"); // Here the code will get the previous block index 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 if (nTime <= pindexPrev->GetMedianTimePast()) return error("AcceptBlock() : block's timestamp is too early");
// It then performs a check on the proof of work if (nBits != GetNextWorkRequired(pindexPrev)) return error("AcceptBlock() : incorrect proof of work");
// Here the code will write the block to history file 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 // 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 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 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 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 if (pfrom) pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), GetOrphanRoot(pblock)); return true; }
// Store to disk if (!pblock->AcceptBlock()) { delete pblock; return error("ProcessBlock() : AcceptBlock FAILED"); } delete pblock; // Recursively process any orphan blocks that depended on this one 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 : printf("ProcessBlock: ACCEPTED\n"); return true;
|
┏━━━━━━━━━━━━━━━━━┓ ┃ 𝔱𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔬𝔯ⱪ 𝔣𝔬𝔯 𝔶𝔬𝔲𝔯 𝔟𝔞𝔤𝔰 ┃ ┃ ➤21/M ┃ ┃ ███▓▓ ███▓▓ ███▓▓ ███▓▓┃
|
|
|
DaCryptoRaccoon (OP)
|
|
November 28, 2018, 04:46:57 PM Last edit: December 03, 2018, 01:42:24 PM by MagicByt3 |
|
Reserved Part 3 - POW Checking
|
┏━━━━━━━━━━━━━━━━━┓ ┃ 𝔱𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔬𝔯ⱪ 𝔣𝔬𝔯 𝔶𝔬𝔲𝔯 𝔟𝔞𝔤𝔰 ┃ ┃ ➤21/M ┃ ┃ ███▓▓ ███▓▓ ███▓▓ ███▓▓┃
|
|
|
DaCryptoRaccoon (OP)
|
|
December 03, 2018, 01:38:37 PM Last edit: December 13, 2018, 03:17:47 PM by MagicByt3 |
|
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 // 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; }
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); } }
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); // This section will create the coinbase transaction (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;
// In this section we see the code to create a new block. // auto_ptr<CBlock> pblock(new CBlock()); if (!pblock.get()) return false; // Again this section will create a coinbase transaction (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;
//Here we see the creation of a new block auto_ptr<CBlock> pblock(new CBlock()); if (!pblock.get()) return false; // We must first add our coinbase tx as first transaction pblock->vtx.push_back(txNew); // The code then collect's the latest transactions into the block 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 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 // 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 for valid proof of work found 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; }
** Work in progress **
|
┏━━━━━━━━━━━━━━━━━┓ ┃ 𝔱𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔬𝔯ⱪ 𝔣𝔬𝔯 𝔶𝔬𝔲𝔯 𝔟𝔞𝔤𝔰 ┃ ┃ ➤21/M ┃ ┃ ███▓▓ ███▓▓ ███▓▓ ███▓▓┃
|
|
|
DaCryptoRaccoon (OP)
|
|
December 14, 2018, 12:19:31 AM Last edit: January 03, 2019, 06:17:19 PM by MagicByt3 |
|
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 enum { SIGHASH_ALL = 1, SIGHASH_NONE = 2, SIGHASH_SINGLE = 3, SIGHASH_ANYONECANPAY = 0x80, }; 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,
// 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.
// 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.
// 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.
// 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, // 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,
// crypto OP_RIPEMD160, OP_SHA1, OP_SHA256, OP_HASH160, OP_HASH256, OP_CODESEPARATOR, OP_CHECKSIG, OP_CHECKSIGVERIFY, OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY,
// multi-byte opcodes OP_SINGLEBYTE_END = 0xF0, OP_DOUBLEBYTE_BEGIN = 0xF000,
// template matching params OP_PUBKEY, OP_PUBKEYHASH,
OP_INVALIDOPCODE = 0xFFFF, };
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"; // 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";
// 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"; // 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";
// 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"; // 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";
// 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";
// 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"; } };
|
┏━━━━━━━━━━━━━━━━━┓ ┃ 𝔱𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔬𝔯ⱪ 𝔣𝔬𝔯 𝔶𝔬𝔲𝔯 𝔟𝔞𝔤𝔰 ┃ ┃ ➤21/M ┃ ┃ ███▓▓ ███▓▓ ███▓▓ ███▓▓┃
|
|
|
100bitcoin
|
|
December 14, 2018, 07:33:11 PM |
|
Fantastic work. Could you please point me out to the part that defines total supply to be 21m?
|
|
|
|
DaCryptoRaccoon (OP)
|
|
December 14, 2018, 11:14:10 PM Last edit: December 14, 2018, 11:31:45 PM by MagicByt3 Merited by ABCbits (1), vit05 (1) |
|
in bitcoin fixed point math is used to calculate the block subsidies. 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.mediawikiIn 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; 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
|
┏━━━━━━━━━━━━━━━━━┓ ┃ 𝔱𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔬𝔯ⱪ 𝔣𝔬𝔯 𝔶𝔬𝔲𝔯 𝔟𝔞𝔤𝔰 ┃ ┃ ➤21/M ┃ ┃ ███▓▓ ███▓▓ ███▓▓ ███▓▓┃
|
|
|
Velkro
Legendary
Offline
Activity: 2296
Merit: 1014
|
|
December 15, 2018, 03:08:06 AM |
|
Understanding The Satoshi Codebase : Bitcoin V0.1.5
Oh man, posting this in Beginners & Help 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.
|
|
|
|
DaCryptoRaccoon (OP)
|
|
December 15, 2018, 01:38:41 PM |
|
Understanding The Satoshi Codebase : Bitcoin V0.1.5
Oh man, posting this in Beginners & Help 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.
|
┏━━━━━━━━━━━━━━━━━┓ ┃ 𝔱𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔬𝔯ⱪ 𝔣𝔬𝔯 𝔶𝔬𝔲𝔯 𝔟𝔞𝔤𝔰 ┃ ┃ ➤21/M ┃ ┃ ███▓▓ ███▓▓ ███▓▓ ███▓▓┃
|
|
|
DaCryptoRaccoon (OP)
|
|
January 03, 2019, 06:10:17 PM |
|
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
|
┏━━━━━━━━━━━━━━━━━┓ ┃ 𝔱𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔬𝔯ⱪ 𝔣𝔬𝔯 𝔶𝔬𝔲𝔯 𝔟𝔞𝔤𝔰 ┃ ┃ ➤21/M ┃ ┃ ███▓▓ ███▓▓ ███▓▓ ███▓▓┃
|
|
|
darosior
|
|
January 04, 2019, 12:47:11 PM |
|
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 ?
|
|
|
|
DaCryptoRaccoon (OP)
|
|
January 04, 2019, 05:31:03 PM |
|
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.
|
┏━━━━━━━━━━━━━━━━━┓ ┃ 𝔱𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔬𝔯ⱪ 𝔣𝔬𝔯 𝔶𝔬𝔲𝔯 𝔟𝔞𝔤𝔰 ┃ ┃ ➤21/M ┃ ┃ ███▓▓ ███▓▓ ███▓▓ ███▓▓┃
|
|
|
DaCryptoRaccoon (OP)
|
|
June 23, 2019, 08:13:20 PM Last edit: June 24, 2019, 12:28:51 PM by MagicByt3 |
|
A quick breakdown of a raw block and all it's parts broken down in a much simpler way to understand. 1. BlockHeader 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 00000020702C9FD61864295E897E723E76E929D6E5099BED17432B000000000000000000AA5FB4AFB0154D2BDD3315E074F219351FDF13908F1C515E07BE12124A3D3760B4222A5CF41E371715000000 3. Coinbase transaction 01000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0487654321FFFFFFFF0100F90295000000001976A914DC863734A218BFE83EF770EE9D41A27F824A6E5688AC00000000 4. Computed block hash CB78229F85ABD927B71954CB65905F5AC9F12DBC512D2FE9CD6C7580AA814C62000000000000000000371EF4FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF Now lets say the nonce value is to move to 22. The new computed value for Block Hash would become 77F6BF7C376A4346BD28FFAB917E2B1327B8CFD77F70B986A6421FC06A21CF56 Now lets break down the Raw header in Hex 00000020702C9FD61864295E897E723E76E929D6E5099BED17432B000000000000000000AA5FB4AFB0154D2BDD3315E074F219351FDF13908F1C515E07BE12124A3D3760B4222A5CF41E371715000000 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. 000000000000000000371EF4FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ** Work In Progress **
|
┏━━━━━━━━━━━━━━━━━┓ ┃ 𝔱𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔬𝔯ⱪ 𝔣𝔬𝔯 𝔶𝔬𝔲𝔯 𝔟𝔞𝔤𝔰 ┃ ┃ ➤21/M ┃ ┃ ███▓▓ ███▓▓ ███▓▓ ███▓▓┃
|
|
|
pooya87
Legendary
Offline
Activity: 3668
Merit: 11107
Crypto Swap Exchange
|
|
June 24, 2019, 03:58:36 AM |
|
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: 624c81aa80756ccde92f2d51bc2df1c95a5f9065cb5419b727d9ab859f2278cb
but the value you posted in #4 is not even close to this, not even 32 byte (it is 64 bytes)
|
|
|
|
DaCryptoRaccoon (OP)
|
|
June 24, 2019, 12:31:05 PM Merited by TheWolf666 (1) |
|
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: 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
|
┏━━━━━━━━━━━━━━━━━┓ ┃ 𝔱𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔬𝔯ⱪ 𝔣𝔬𝔯 𝔶𝔬𝔲𝔯 𝔟𝔞𝔤𝔰 ┃ ┃ ➤21/M ┃ ┃ ███▓▓ ███▓▓ ███▓▓ ███▓▓┃
|
|
|
TheWolf666
Full Member
Offline
Activity: 615
Merit: 154
CEO of Metaisland.gg and W.O.K Corp
|
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_supplySo you will not find something like 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?
|
|
|
|
achow101
Moderator
Legendary
Offline
Activity: 3570
Merit: 6927
Just writing some code
|
|
July 01, 2019, 04:56:34 PM |
|
So you will not find something like 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: 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.
|
|
|
|
|