ротор карьерного экскаватора

Каждый майнер желает добавить блок в блокчейн

13 октября 2017 г., 13:00 в разделе блокчейн

За каждый добавленный блок полагается награда. Задумывались ли вы как это происходит на самом деле? Заглянем в код программы, которую написал Сатоши Накамото. Она доступна для всех на Гитхабе.

Транзакция — это запись вида «перевести X биткоинов с кошелька A на кошелек B». Майнер собирает несколько таких транзакций в блок и пытается добавить его в блокчейн.

Код майнера находиться в файле miner.cpp. Функция CreateNewBlock создает пустой блок, в который потом будут добавляться транзакции. Покажу только часть функции


std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn, bool fMineWitnessTx)
{
...
// Create coinbase transaction.
CMutableTransaction coinbaseTx;
coinbaseTx.vin.resize(1);
coinbaseTx.vin[0].prevout.SetNull();
coinbaseTx.vout.resize(1);
coinbaseTx.vout[0].scriptPubKey = scriptPubKeyIn;
coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus());
coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;
pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx));
pblocktemplate->vchCoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus());
pblocktemplate->vTxFees[0] = -nFees;

}

Этот код добавляет в начало блока coinbase-транзакцию. Это особый вид транзакции, потому что в ней нет ссылки на кошелёк отправителя. То есть, деньги майнеру попадают просто записью в блок транзакции «перевести X биткоинов на кошелёк B» без указания отправителя. Об этом говорит строчка coinbaseTx.vin[0].prevout.SetNull();

Если блок будет добавлен в блокчейн, майнер получит nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus()). nFees — это сумма, которую владельцы транзакций готовы заплатить за добавление транзакции в блокчейн. Функция GetBlockSubsidy() возвращает вознаграждение, причитающееся майнеру согласно правил работы биткоина. Она находится в файле validaiona.cpp и выглядит так:


CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
{
int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;
// Force block reward to zero when right shift is undefined.
if (halvings >= 64)
return 0;

CAmount nSubsidy = 50 * COIN;
// Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years.
nSubsidy >>= halvings;
return nSubsidy;
}

Помните, что приблизительно каждые четыре года вознаграждение майнерам сокращается вдвое? Точнее сказать вознаграждение уменьшается каждые 210 000 блоков. Это записано в файле chainparams.cpp


сlass CMainParams : public CChainParams {
public:
CMainParams() {
strNetworkID = "main";
consensus.nSubsidyHalvingInterval = 210000; <--- вот они эти магические 210 000 блоков

Блок генерируется приблизительно раз в 10 минут. 210 000 блоков потребуют 2 100 000 минут или, приблизительно, 3 года 11 месяцев и 26 дней. На текущий момент последний блок № 489 340. Возьмем целое от halvings = nHeight / consensusParams.nSubsidyHalvingInterval = 489 340 / 210 000 = 2, то есть начальное вознаграждение 50 биткоинов нужно дважды разделить пополам:

nSubsidy = 50 * COIN;
nSubsidy >>= 2;

Сегодня вознаграждение составляет 12,5 биткоинов.