(二)區塊鏈的共識算法:PoS 及其 例子 代碼 實現


作者:林冠宏 / 指尖下的幽靈

掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8

博客:http://www.cnblogs.com/linguanh/

GitHub : https://github.com/af913337456/

騰訊雲專欄: https://cloud.tencent.com/developer/user/1148436/activities


目錄

  • 前序
  • PoS 共識算法
  • PoS 的特點
  • 編寫 PoS 代碼
    • 候選塊數組
    • 塊中的節點地址
    • 進行股權分配
    • 根據股權選出贏家
    • 結束

前序

這篇文章是上一篇的序章,上一篇的鏈接地址是:

https://juejin.im/post/5b78f6e46fb9a019e8227162,(一)區塊鏈的共識算法:整體介紹 及 分叉 的通俗講解

本篇文章將會着重介紹 PoS 共識算法和采用代碼例子來實在地闡述它

關於什么是共識算法這個問題,請查看(一)區塊鏈的共識算法:整體介紹 及 分叉 的通俗講解 ,里面已經給出了答案。

PoS 共識算法

PoS 全稱為 Proof of Stake 股權證明。字面意思就是,股份制。就是說,誰的股份越多,誰的話事權越大,這和我們生活中的股份制公司中的股東的意思的差不多的。

但是,在區塊鏈的應用中,我們並不可能真實地分配給鏈中的節點股份,取而代之的是另外一些東西,這些東西充當股份,我們將這些東西分配給鏈中節點。下面將舉一些例子來加以闡述這個概念。

例如 PoS虛擬貨幣的應用中,我們可以把持幣量的多少,來看作擁有股權、股份的多少,現在 以太坊 ETH 中是擁有 PoS 共識機制的,所以在以太坊中,就是把各個以太坊節點 所擁有的 ETH 代幣的數量來衡量,這個節點的股份有多少,它的話事權有多少。假設一個以太坊網絡,共有3個節點,A 和 B 和 C,其中 A 節點擁有10000 個 ETH 代幣,而 B 和 C 分別有 1000 和 2000 個,那么在這個以太坊網絡中,A 的區塊是最有可能被選中的,話事權是比較大的。

再例如,假設日后的某個非虛擬貨幣的區塊鏈、公有鏈,一條實體業結合的鏈,例如 汽車鏈,我們就可以把每一位車主所擁有的車輛數目他的車價值多少錢來分配股份,例如規定一條公式:車數*車價值 = 股份的多少,在 PoS 中股份是一個概念,一個衡量話事權的概念。

PoS 的特點

上面的描述已經說明了 PoS 共識算法的概念。因為它是以擁有某樣東西的數量衡量話事權的,這就意味着,只要我們的節點,擁有這類東西,例如 ETH 代幣,哪怕擁有的只有 一個,都是有話事權的,即使很小,甚至都沒機會露面,但它還是有機會。

PoS 中,塊是已經鑄造好的(這里沒有“挖礦”的概念,所以我們不用這個詞來證明股份),PoW 是有挖礦概念的。

這也就造成了它有下面的特點:

  • 優點:

    • 縮短了共識達成的時間,鏈中共識塊的速度更快
    • 不再需要大量消耗能源挖礦
    • 作弊得不嘗失,因為如果一名持有 51% 以上股權的人作弊,相當於他坑了自己,因為他是擁有股權最多的人,作弊導致的結果往往是擁有着越多的損失越多
  • 缺點:

    • 攻擊成本低,只有節點有物品數量,例如代幣數量,就能發起臟數據的區塊攻擊
    • 另外擁有代幣數量大的節點獲得記賬權的概率會更大,會使得網絡共識受少數富裕賬戶支配,從而失去公正性

編寫 PoS 代碼

為了能讓更多人,以及非 go 開發者能看懂,下面將通過 偽代碼 來實現,完整的 go 代碼請留郵箱。

首先我們使用一個候選區塊數組來保存,每一個 節點 廣播過來的和自己當前節點生成的區塊對象:


candidateBlocks [ ]Blocks   候選區塊數組

每個區塊結構體里面有一個變量 是用來記錄生成這個區塊的節點地址

type Block struct {
    Timestamp   string    // 時間戳,代表該區塊的生成時間
    Hash        string    // 這個區塊的 hash 值
    PrevHash    string    // 這個區塊的 上一個 區塊的 hash 值
    NodeAddress string    // 生成這個區塊的 節點地址
    Data        string    // 區塊攜帶的數據
}

然后有一個 子線程,專門負責遍歷 候選區塊數組,來根據區塊里面的節點地址 獲取 它的代幣數量,然后分配股權


stakeRecord []string  // 數組

for block ~ candidateBlocks {
   coinNum = getCoinBalance(block.NodeAddress) // 獲取代幣數量
   for i ~ coinNum {  // 幣有多少,就循環添加多少次
       if stakeRecord.contains(block.NodeAddress) {  // 是否以及包含了
           break // 包含的就不再重復添加
       }
       stakeRecord = append(block.NodeAddress) // 添加
   }
}

然后從 stakeRecord選出一個競選勝利者。這個概率就和上面的 coinNum 有關,越大就越有機會。


index = randInt()  // 得出一個整形隨機數

winner = stakeRecord[index]  // 取出勝利者節點的地址

最后,我們就能取出這個 winner 所生成的區塊來進行公鏈的接入,然后廣播出去


for block ~ candidateBlocks {
    if block.NodeAddress == winner {
        // 添加
    }
}

// 廣播出去

...

以上,就是一個很簡單的, PoS 算法機制的代碼實現,單純地根據持幣數量來做股權分配。而事實上,事情往往是比較復雜的,想想一下,如果我的股權的分配,不僅僅和代幣的數量有關系呢,對吧,這樣的話,就能衍生各種各樣的想法變種方式

例如以太坊加入了幣齡,在候選成功后,以太坊在這個步驟還會扣除幣齡。種種的這些,都是可以變的,我們要理解 PoS 的精髓,才能在開發自己的公有鏈的時候,隨心而行


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM