專案 GitHub 位置: https://github.com/weiawesome/block-chain_go
在區塊運算當中 還有一環非常重要的環節
便是 區塊的流向
新區塊 獲得的方式
新區塊會影響的範圍
因此這篇主要以分幾點為敘述
完成的範圍便是 接受驗證區塊 與 刷新資料庫 與 刷新區塊
接受驗證區塊
Channel 名稱 | Channel 類型 | 地點 |
---|---|---|
BlockChannel | 進 | 廣播系統 |
MinersSuccessBlockChannel | 進 | 礦工管理者 |
BroadcastBlockChannel | 出 | 廣播系統 |
RefreshBlockChannel | 出 | 刷新資料庫 |
刷新資料庫
Channel 名稱 | Channel 類型 | 地點 |
---|---|---|
RefreshBlockChannel | 進 | 接受驗證區塊 |
CompleteBlockChannel | 出 | 刷新區塊 |
刷新區塊
Channel 名稱 | Channel 類型 | 地點 |
---|---|---|
BlockTransactionChannel | 進 | 接受驗證交易 |
CompleteBlockChannel | 進 | 刷新資料庫 |
MinersBlockChannel | 出 | 礦工管理者 |
檔案位置: "./service/receive_validate_block/receive_validate_block.go"
func ReceiveValidateBlock(BroadcastBlockChannel chan blockchain.Block, MinersSuccessBlockChannel chan blockchain.Block, BlockChannel chan blockchain.Block, RefreshBlockChannel chan blockchain.Block) {
for {
select {
case mb := <-MinersSuccessBlockChannel:
BroadcastBlockChannel <- mb
RefreshBlockChannel <- mb
case b := <-BlockChannel:
_, err := block.GetBlock(b.BlockHash)
if err != nil {
if b.CheckDifficulty() {
tmpBlockHash := b.BlockHash
b.ComputeBlockHash()
if tmpBlockHash == b.BlockHash {
tmpMarkleRoot := b.BlockTop.MarkleRoot
b.ComputeMarkleRoot()
if tmpMarkleRoot == b.BlockTop.MarkleRoot {
BroadcastBlockChannel <- b
RefreshBlockChannel <- b
}
}
}
}
default:
continue
}
}
}
首先對於獲取新區塊的方式 分為兩種渠道(Channel)
由於是自己運算的 因此不浪費時間運算 而是直接廣播與
首先檢查資料庫是否存在該筆區塊 若已存在則不計算該區塊
若無則檢查區塊哈希、Markle root、區塊難度等等 再廣播與設定資料庫
檔案位置: "./service/refresh_db/refresh_db.go"
func RefreshDb(RefreshBlockChannel chan blockchain.Block, CompleteBlockChannel chan blockchain.Block) {
for {
select {
case rb := <-RefreshBlockChannel:
if rb.BlockTop.PreviousHash == conseous.GenesisBlockPreviousHash {
_, err := block_control.GetLastBlock()
if err != nil {
err := block_control.SetLastBlock(rb.BlockHash)
if err != nil {
continue
}
}
err = block_control.SetCandidateBlock(rb.BlockHash)
if err != nil {
continue
}
err = block.SetBlock(rb)
if err != nil {
continue
}
for _, transaction := range rb.BlockTransactions {
err := utxo.SetUTXO(transaction)
if err != nil {
continue
}
}
CompleteBlockChannel <- rb
continue
} else {
_, err := block.GetBlock(rb.BlockTop.PreviousHash)
if err != nil {
continue
}
}
lastBlockHash, err := block_control.GetLastBlock()
if err != nil {
continue
}
lastBlock, err := block.GetBlock(lastBlockHash)
if err != nil {
continue
}
if rb.BlockTop.BlockHeight > lastBlock.BlockTop.BlockHeight-conseous.BlockChecked {
err := block_control.SetCandidateBlock(rb.BlockHash)
if err != nil {
continue
}
for _, transaction := range rb.BlockTransactions {
err := utxo.SetUTXO(transaction)
if err != nil {
continue
}
}
if rb.BlockTop.BlockHeight > lastBlock.BlockTop.BlockHeight {
err := block_control.SetLastBlock(rb.BlockHash)
if err != nil {
continue
}
lastBlock = rb
if lastBlock.BlockTop.BlockHeight-conseous.BlockChecked >= conseous.GenesisBlockHeight {
tmpBlock := lastBlock
for i := 0; i < conseous.BlockChecked; i++ {
tmpBlock, err = block.GetBlock(tmpBlock.BlockTop.PreviousHash)
if err != nil {
continue
}
}
err := block_control.DeleteCandidateBlock(tmpBlock.BlockHash)
if err != nil {
continue
}
candidateBlocks, err := block_control.GetCandidateBlock()
if err != nil {
continue
}
for _, candidateBlock := range candidateBlocks {
b, err := block.GetBlock(candidateBlock)
if err != nil {
return
}
if b.BlockTop.BlockHeight == tmpBlock.BlockTop.BlockHeight+1 {
if b.BlockTop.PreviousHash != tmpBlock.BlockHash {
err := block_control.DeleteCandidateBlock(b.BlockHash)
if err != nil {
continue
}
for _, transaction := range b.BlockTransactions {
err := utxo.ReverseUTXO(transaction)
if err != nil {
continue
}
}
err = block.DeleteBlock(b.BlockHash)
if err != nil {
continue
}
}
} else if b.BlockTop.BlockHeight == tmpBlock.BlockTop.BlockHeight+1 {
err := block_control.DeleteCandidateBlock(b.BlockHash)
if err != nil {
continue
}
for _, transaction := range b.BlockTransactions {
err := utxo.ReverseUTXO(transaction)
if err != nil {
continue
}
}
err = block.DeleteBlock(b.BlockHash)
if err != nil {
continue
}
}
}
err = block_control.SetCheckedBlock(tmpBlock.BlockHash)
if err != nil {
continue
}
}
}
CompleteBlockChannel <- rb
}
default:
continue
}
}
}
基本上 就是一進一出
會檢查該筆區塊 在該個節點的位置
並適當處理分支的問題
以上圖為例
當新增區塊時 會先確認該區塊的位置
當有個區塊已經達到多區塊認證(數量多少為協議決定)
則該 該個區塊則被視為已被確認
接下來會刪除掉非此塊分支的區塊
圖片順序分別為
這便是區塊鏈對於分支的處理
最後再將資料庫做更正與處理
若是該筆區塊是最後區塊則再傳遞給 更新區塊
檔案位置: "./service/service/refresh_block.go"
func RefreshBlock(BlockTransactionChannel chan blockchain.BlockTransaction, MinersBlockChannel chan blockchain.Block, CompleteBlockChannel chan blockchain.Block) {
TransactionPool := make(utils.PriorityQueue, 0)
var TargetBlock blockchain.Block
key, err := utils.DecodePublicKey(utils.GetPublicKey())
if err != nil {
return
}
address := utils.GetAddress(conseous.VersionPrefix, key)
minerTransaction, err := transactionUtils.MinerTransaction(address)
if err != nil {
return
}
for {
select {
case bt := <-BlockTransactionChannel:
heap.Push(&TransactionPool, &bt)
var tmpBlock blockchain.Block
tmpBlock.BlockTransactions = append(tmpBlock.BlockTransactions, minerTransaction)
tmpTransactionPool := TransactionPool
for tmpTransactionPool.Len() > 0 {
t := heap.Pop(&tmpTransactionPool).(*blockchain.BlockTransaction)
tmpBlock.BlockTransactions = append(tmpBlock.BlockTransactions, *t)
if unsafe.Sizeof(tmpBlock) > conseous.BlockSize {
tmpBlock.BlockTransactions = tmpBlock.BlockTransactions[:len(tmpBlock.BlockTransactions)-1]
break
}
}
tmpBlock.ComputeMarkleRoot()
if tmpBlock.BlockTop.MarkleRoot != TargetBlock.BlockTop.MarkleRoot {
TargetBlock = tmpBlock
TargetBlock.BlockTop.Version = conseous.Version
TargetBlock.BlockTop.TimeStamp = time.Now().Unix()
blockHash, err := block_control.GetLastBlock()
if err != nil || blockHash == conseous.GenesisBlockPreviousHash {
blockHash = conseous.GenesisBlockPreviousHash
TargetBlock.BlockMeta = blockchain.BlockMeta{Content: conseous.GenesisBlockContent}
TargetBlock.BlockTop.BlockHeight = conseous.GenesisBlockHeight
TargetBlock.BlockTop.Difficulty = conseous.GenesisBlockDifficulty
} else {
b, err := block.GetBlock(blockHash)
fmt.Println(b.BlockHash, err)
if err != nil {
continue
}
TargetBlock.BlockTop.BlockHeight = b.BlockTop.BlockHeight + 1
TargetBlock.BlockTop.Difficulty = b.BlockTop.Difficulty
if TargetBlock.BlockTop.BlockHeight%conseous.DifficultyCycle == 0 {
speed, err := block.CheckGenerateSpeed(TargetBlock.BlockTop.BlockHeight)
if err == nil {
if speed {
if TargetBlock.BlockTop.Difficulty > conseous.DifficultyLower {
TargetBlock.BlockTop.Difficulty -= 1
}
} else {
if TargetBlock.BlockTop.Difficulty < conseous.DifficultyUpper {
TargetBlock.BlockTop.Difficulty += 1
}
}
}
}
}
TargetBlock.BlockTop.PreviousHash = blockHash
MinersBlockChannel <- TargetBlock
}
case cb := <-CompleteBlockChannel:
TargetBlock = blockchain.Block{}
TargetBlock.BlockTop.Version = conseous.Version
TargetBlock.BlockTop.TimeStamp = time.Now().Unix()
TargetBlock.BlockTop.PreviousHash = cb.BlockHash
TargetBlock.BlockTransactions = append(TargetBlock.BlockTransactions, minerTransaction)
tmpTransactionPool := make(utils.PriorityQueue, 0)
for TransactionPool.Len() > 0 {
t := heap.Pop(&TransactionPool).(*blockchain.BlockTransaction)
flag := false
for _, transaction := range cb.BlockTransactions {
if transaction.TransactionHash == t.TransactionHash {
flag = true
}
}
if !flag {
heap.Push(&tmpTransactionPool, t)
TargetBlock.BlockTransactions = append(TargetBlock.BlockTransactions, *t)
if unsafe.Sizeof(TargetBlock) > conseous.BlockSize {
TargetBlock.BlockTransactions = TargetBlock.BlockTransactions[:len(TargetBlock.BlockTransactions)-1]
}
}
}
TargetBlock.ComputeMarkleRoot()
TransactionPool = tmpTransactionPool
MinersBlockChannel <- TargetBlock
default:
continue
}
}
}
分為兩種進入的渠道(Channel)
第一種是新交易進入的方式 這裡便不贅述
第二種則是透過更新資料庫後結果傳過來的新區塊
理解 區塊的流向 是很重要的一環
怎麼獲得? 影響的範圍是甚麼?
對於這些基礎的疑惑 有基礎的概念
方能找出對應的解決方式
而且對於整個區塊鏈的運行更能理解其內容與機制
希望透過這篇能夠知曉
好的 今日也解決 關於區塊的流向問題
因此目前對於 區塊運算當中
已有 區塊 與 交易 的資訊
那接下來是時候 該輪到挖礦的環節了吧