比特幣原始碼解讀之區塊確認
(本文使用的是比特幣v0.1.0版本 點選下載原始碼)
本文主要描述礦工挖到區塊或者收到“block”訊息後進行的區塊處理。主要包含區塊有效性檢查,孤立區塊處理以及當前區塊處理等(ps:本文暫不涉及工作量證明以及共識, 這兩方面內容再後續文章中介紹)
流程圖如下所示:
本文主要描述bool ProcessBlock(CNode pfrom, CBlock pblock)函式的功能。
區塊重複性檢查
區塊是否在區塊鏈中,如果在則返回失敗
uint256 hash =GetHash();
if(mapBlockIndex.count(hash))
return error("AcceptBlock() : block already in mapBlockIndex"
區塊是否在孤立區塊中,如果在則返回失敗
if(mapOrphanBlocks.count(hash))
return error("ProcessBlock() : already have block (orphan) %s", hash.ToString().substr(0,14).c_str());
區塊基本檢查
if(!pblock->CheckBlock())
{
delete pblock;
return error("ProcessBlock() : CheckBlock FAILED");
}
檢查區塊大小、時間戳
// Size limits
if(vtx.empty()|| vtx.size
return error("CheckBlock() : size limits failed");
// Check timestamp
if(nTime >GetAdjustedTime()+2*60*60)
return error("CheckBlock() : block timestamp too far in the future");
檢查交易、PoW和MerkleRoot
// First transaction must be coinbase, the rest must not be
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(constCTransaction& tx, vtx)
if(!tx.CheckTransaction())
return error("CheckBlock() : CheckTransaction failed");
// Check 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");
// Check merkleroot
if(hashMerkleRoot !=BuildMerkleTree())
return error("CheckBlock() : hashMerkleRoot mismatch");
根據區塊前一區塊進行處理
如果前一區塊不存在區塊鏈中,則將前一區塊加入孤立區塊
此種情況,表示區塊鏈出現分叉或者網路延遲導致的,則需要傳送“getblocks”獲取最長鏈中缺少的區塊資訊。
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));
returntrue;
}
如果前一區塊不存在區塊鏈中,則嘗試接受區塊
if(!pblock->AcceptBlock())
{
delete pblock;
return error("ProcessBlock() : AcceptBlock FAILED");
}
delete pblock;
接受區塊
“接受區塊”包含區塊重複性檢查,前一區塊有效性區塊,時間戳檢查,工作量證明;當這些條件檢查通過後,將區塊寫入磁碟並加入到區塊鏈中。(加入到區塊鏈具體在後續“比特幣原始碼解讀之共識”一文中介紹)
boolCBlock::AcceptBlock()
{
// Check for duplicate
uint256 hash =GetHash();
if(mapBlockIndex.count(hash))// 當前區塊重複性檢查
return error("AcceptBlock() : block already in mapBlockIndex");
// Get prev 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;
// Check timestamp against prev
if(nTime <= pindexPrev->GetMedianTimePast())// 時間戳檢查
return error("AcceptBlock() : block's timestamp is too early");
// Check proof of work
if(nBits !=GetNextWorkRequired(pindexPrev))// 工作量檢查
return error("AcceptBlock() : incorrect proof of work");
// Write block to history file
unsignedint nFile;
unsignedint 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));
returntrue;
}
處理孤立區塊和當前區塊的關係,並嘗試接受孤立區塊
vector<uint256> vWorkQueue;
vWorkQueue.push_back(hash);
for(int i =0; i < vWorkQueue.size(); i++)
{
uint256 hashPrev = vWorkQueue[i];
相關推薦
比特幣原始碼解讀之區塊確認
(本文使用的是比特幣v0.1.0版本 點選下載原始碼)本文主要描述礦工挖到區塊或者收到“block”訊息後進行的區塊處理。主要包含區塊有效性檢查,孤立區塊處理以及當前區塊處理等(ps:本文暫不涉及工作量證明以及共識, 這兩方面內容再後續文章中介紹)流程圖如下所示:本文主要描述
比特幣原始碼解讀之整體框架
本文主要描述了程序啟動時初始化(載入地址、區塊、錢包資訊,啟動節點執行緒以及礦工挖礦執行緒等)、比特幣客戶端交易的發起(交易初始化、提交交易請求、確認和廣播及交易)以及比特幣客戶端當前節點地址和收款方地址。下文將根據總體框架圖分別描述各個功能在原始碼中的函式實現(
比特幣原始碼解讀之交易發起
(本文使用的是比特幣v0.1.0版本 點選下載原始碼)本文主要描述交易是如何發起中,其過程包含交易的新建(包含交易的選擇,交易費的計算、簽名);提交交易請求;本節點接受交易(驗證、檢查並儲存交易等);最後廣播交易到其他節點中。流程圖如下所示:新建交易if(!CreateTra
比特幣原始碼解讀之執行緒處理-礦工執行緒
(本文使用的是比特幣v0.1.0版本 點選下載原始碼) 比特幣原始碼解讀之執行緒處理分為兩篇,礦工執行緒處理和其他執行緒處理兩篇,本文描述礦工執行緒處理,主要包含創幣交易的產生、當前交易的打包處理,工作量等相關內容。流程圖如下所示: 新建礦
比特幣原始碼解讀之私鑰、公鑰和地址
(本文使用的是比特幣v0.1.0版本 點選下載原始碼)比特幣是建立在數字加密基礎上的,接觸過比特幣的朋友應該知道:(1)購買比特幣最後是通過一個比特幣地址進行的,比特幣地址就像支票中的支付物件(收款方);(2)而比特幣地址則是通過公鑰單向雜湊生成的;(3)而公鑰則是通過私鑰使
比特幣原始碼解讀之前期準備
前言 筆者從今天開始對bitcoin 第一個發行版v0.1.0版本進行原始碼分析(ps. 網上對比特幣高版本的分析文章很多,但是介紹第一個版本的分析很少,系統全面的分析第一個版本更是寥寥無幾)。讀者如果需要了解學習區塊鏈技術,可能從第一個版本中受到啟發。這是一系列
比特幣原始碼解讀三
這篇我們主要分析下AppInit2的程式碼,這個函式在init.cpp中。這個函式分了12步完成了初始化客戶端的功能。裡面包含了bitcoin的大部分初始程式,包括讀取'塊索引'、載入塊鏈、載入100個預產生的keys,匯入peers.dat中的資訊,以及初始化其他執行緒。現在我們就看下這12步都做了些什麼。
比特幣原始碼閱讀(1)--雜記與加密部分(爽之小刀)
比特幣原始碼閱讀(1)–雜記與加密部分(爽之小刀) 歡迎轉載和引用 若有問題請聯絡請聯絡 Email : [email protected] QQ:2279557541 最近從成都來到了杭州拼一槍 由於老婆為了圓自己的一個大公司夢來到了杭州
區塊鏈學習1.5-比特幣原始碼的學習-比特幣網路
本篇文章有部分內容直接出自《Mastering Bitcoin》 比特幣網路層主要是由 P2P網路,傳播機制,驗證機制三部分組成。 白皮書關於network的內容回顧一下: The steps to run the network are as follows:
區塊鏈學習1.4-比特幣原始碼的學習-比特幣基礎
1.3就已經提到區塊鏈的四大技術組合,我認為還是有必要了解背後的原理的。下面做一個簡要的介紹。 一. 區塊鏈資料結構和數字簽名演算法 1.資料結構Merkel樹 說到merkle樹就不得不談到交易,merkle樹就是用於存放交易的 資料結構。如下圖: 它是一個雜湊二叉樹,雜湊的
比特幣程式碼分析8 區塊校驗和確認
比特幣節點接收到一個區塊以後,都會進行校驗和確認,如下參考網路圖: 關鍵看看對區塊中的交易進行進一步的校驗程式碼:1.// First transaction must be coinbase, the rest must not be2.if (vtx.empty() || !vtx[0].IsCoinB
【區塊鏈】比特幣原始碼學習
比特幣原始碼學習 - 1 - 交易 參考部落格:here and here 一、交易概念 1、 交易形式 比特幣交易中的基礎構建單元是交易輸出。在比特幣的世界裡既沒有賬戶,也沒有餘額,只有分散到區塊鏈裡的UTXO[未花費的交易輸出]。 例如,你有20比特幣
【區塊鏈】比特幣原始碼
比特幣原始碼 - 2 - 金鑰和地址 一、基本概念 這裡摘抄一下《精通比特幣》裡面的描述: 比特幣的所有權是通過數字金鑰、比特幣地址和數字簽名來確立的。數字金鑰實際上並不是儲存在網路中,而是由使用者生成並存儲在一個檔案或簡單的資料庫中,稱為錢包。 每筆比特幣交
比特幣原始碼研讀(二)之搭環境遇到的那些坑
首先說一下度《精通比特幣》是一直不理解的一個地方: 上面兩處被圈起來的地方都提到了一個數字2256,特別是第一句話更是讓人費解,如果私鑰只能在1到2256間產生那豈不是太容易重複了。關於這點,我認為是在翻譯或者排版是出現了錯誤,2256應該是想表達2的256次方的意
比特幣原始碼情景分析之script指令碼驗證(1)
Bitcoin script是一種簡單的指令執行框架1)指令碼概述指令碼主要由兩部分構成:指令碼物件CScript和執行函式VerifyScript。指令碼物件分為兩類:scriptSig和scriptPublicKeyscriptSig位於交易中的txin中,而script
比特幣原始碼解析(7) - 資料結構 - 區塊
比特幣原始碼解析(7) - 資料結構 - 區塊 https://blog.csdn.net/u012183589/article/details/77776730 0x00 摘要 區塊是區塊鏈的組成基本結構,也是交易資訊的載體,礦工通過挖礦的形式來產生新的區
比特幣原始碼情景分析之bloom filter精讀
上一篇SPV錢包裡utxos同步提到了bloom filter,這一章節我們將從原始碼分析角度來個深度解剖Bloom filter基本原理 An example of a Bloom filter, representing the set {x, y, z}. The co
比特幣原始碼情景分析之script指令碼驗證(2)
通過上一篇的分析,我們應該已經對script有了一定的理解,這章節我們以原始碼分析的方式來了解下指令碼驗證執行流程 bitcoin節點在處理一條交易時就需要驗證交易的txin,由於一條交易可能包含多個txin,因而需要執行多個指令碼驗證,自然需要並行化,因而系統
比特幣原理入門之五:神奇的賬本——區塊鏈
在上個文章中,我們認識了那個神奇的錢包。現在大家回憶一下,我們在最開始的故事中,還提到了一個神奇的東西,那就是那本賬本對嗎?在這個文章中,我們就來看看,這個神奇的賬本。賬本的神奇之處首先,我們回憶一下,這本賬本的神奇之處在哪?對了,就是一、每家每戶都有一本賬本,二、每本賬本上
比特幣原始碼情景分析之SPV錢包輕量級錢包
SPV錢包最理想的實現方案是,伺服器是全節點,SPV錢包通過伺服器驗證和發起交易,查詢交易歷史,本地做交易封裝,即signRawTransaction和使用者互動。SPV節點不需要執行bitcoin core程式碼,由於需要監聽先的交易事件,需要伺服器通過JPush類似的機制主動通知SPV錢包新的交易等事件。