自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何使用Go構(gòu)建權(quán)益區(qū)塊鏈證明

區(qū)塊鏈
隨著區(qū)塊鏈給世界市場帶來的革命,在作出預(yù)測之前了解基礎(chǔ)知識至關(guān)重要。在本文中,我們將探討權(quán)益證明的基礎(chǔ)知識,該證明是一種區(qū)塊鏈協(xié)議,類似于一種在區(qū)塊鏈中偽造新區(qū)塊的彩票方法。

本文轉(zhuǎn)載自微信公眾號「區(qū)塊鏈研究實驗室」,作者鏈三豐。轉(zhuǎn)載本文請聯(lián)系區(qū)塊鏈研究實驗室公眾號。

隨著區(qū)塊鏈給世界市場帶來的革命,在作出預(yù)測之前了解基礎(chǔ)知識至關(guān)重要。在本文中,我們將探討權(quán)益證明的基礎(chǔ)知識,該證明是一種區(qū)塊鏈協(xié)議,類似于一種在區(qū)塊鏈中偽造新區(qū)塊的彩票方法。

本文的主要目標如下:

  • 了解區(qū)塊鏈領(lǐng)域的當前性能趨勢。
  • 通過GoLang中的一個工作示例學習權(quán)益證明。
  • 升級您的計算機科學和Go編程技能。

這將是一個有趣的過程,讓我們開始編寫代碼。

了解權(quán)益證明

股權(quán)證明(PoS)的基礎(chǔ)實際上很簡單。當然,該系統(tǒng)的核心組件是區(qū)塊鏈本身。簡而言之,區(qū)塊鏈是一個不變的分類賬,每個單獨的區(qū)塊都是從之前的區(qū)塊以密碼方式構(gòu)建的。您永遠都無法更改區(qū)塊鏈的任何部分,因為連接到網(wǎng)絡(luò)的每個人都可以輕松看到更改并駁斥您的區(qū)塊鏈版本。

在過程中創(chuàng)造新的塊是由您的區(qū)塊鏈協(xié)議定義,比特幣是基于工作量證明(PoW)協(xié)議構(gòu)建的,當中需要越來越多的計算能力才能通過數(shù)學過程驗證以前的交易,所以每次您驗證區(qū)塊中包含的交易列表時,都會以比特幣的形式獲得獎勵。

因此,交易歷史的證明在于您所從事的工作量,而完成這項工作的人稱為“礦工”。PoW的一個日益嚴重的問題是,隨著時間的流逝,解決這些數(shù)學難題所需的巨大計算能力。

權(quán)益證明在根本上是不同的,所以您無需在核算和擴展區(qū)塊鏈上具有計算能力,而可以在區(qū)塊鏈網(wǎng)絡(luò)上“占用”一定數(shù)量的令牌(不一定是加密貨幣)。通常情況可以通過創(chuàng)建自己的“節(jié)點”來完成的,以方便您參與區(qū)塊鏈生態(tài)系統(tǒng)。

如果節(jié)點采取勤懇的工作態(tài)度,您將有更大的機會在區(qū)塊鏈中創(chuàng)造一個新的區(qū)塊,并獲得原始返還的獎勵。被選擇偽造下一個區(qū)塊的可能性也與您在網(wǎng)絡(luò)上投入的令牌數(shù)量成比例增加;反之如果采取散惰的工作態(tài)度,您的賭注可能會受到處罰甚至被完全撤回。這種獎勵和懲罰方法旨在促進區(qū)塊鏈中的誠實工作,而沒有與工作量證明相關(guān)的計算可擴展性瓶頸。

現(xiàn)在我們已經(jīng)有了PoS與PoW的概念概念,讓我們繼續(xù)在Go中編寫一個有效的PoS示例。

Go中的權(quán)益證明

導(dǎo)入“區(qū)塊鏈”

首先,除了定義自定義對象類型外,我們還需要在項目中包含一些Go包。這是您需要的軟件包-我們將使用math/rand,crypto/sha256以及encoding/hex用于加密區(qū)塊鏈方法。當然,這errors是Go的標準!

  1. package main 
  2.  
  3. import ( 
  4.   "crypto/sha256" 
  5.   "encoding/hex" 
  6.   "errors" 
  7.   "fmt" 
  8.   "log" 
  9.   math "math/rand" 
  10.   "time" 

接下來是我們的自定義數(shù)據(jù)類型。使用Go可以使此超級簡單structs。在這里我們有3個習慣types,第一個是PoSNetwork我們有一個Blockchain字段,該字段是對實例的引用的數(shù)組Block struct。我們將通過BlockchainHead字段跟蹤最近添加的塊,并且還將有一系列對的引用以Node struct用作Validators。

  1. type PoSNetwork struct { 
  2.   Blockchain     []*Block 
  3.   BlockchainHead *Block 
  4.   Validators     []*Node 
  5.  
  6. type Node struct { 
  7.   Stake   int 
  8.   Address string 
  9.  
  10. type Block struct { 
  11.   Timestamp     string 
  12.   PrevHash      string 
  13.   Hash        string 
  14.   ValidatorAddr string 

該Node結(jié)構(gòu)將具有一個Stake字段,該字段代表它添加到網(wǎng)絡(luò)中的令牌數(shù)量。該地址將是一個隨機生成的字符串,以便我們可以跟蹤哪個節(jié)點成功驗證了下一個塊。

最后,Block struct將包含跟蹤區(qū)塊鏈所需的信息。Timestamp創(chuàng)建該塊時,我們將有一個for,來自上一個塊的前一個哈希,Hash表示自身以及Node驗證此塊的的地址-所有type string。

逐塊建造區(qū)塊鏈磚

這是我們構(gòu)建區(qū)塊鏈的第一種方法。首先,在函數(shù)簽名中,將此方法附加到,PoSNetwork struct并將該結(jié)構(gòu)引用為n。然后,我們Node將對a的引用作為唯一參數(shù)。我們將返回一個新的Block引用數(shù)組來表示new Blockchain,對a的引用Block將是new BlockchainHead,以及可能出現(xiàn)error毛病的可能。

您會看到,ValidateBlockchain()我們甚至在嘗試添加任何內(nèi)容之前就立即調(diào)用了該方法。稍后我們將進行驗證,但是只要知道我們發(fā)現(xiàn)要更改的區(qū)塊鏈,就會知道有邏輯要懲罰a Node。

  1. func (n PoSNetwork) GenerateNewBlock(Validator *Node) ([]*Block, *Block, error) { 
  2.   if err := n.ValidateBlockchain(); err != nil { 
  3.     Validator.Stake -= 10 
  4.     return n.Blockchain, n.BlockchainHead, err 
  5.   } 
  6.  
  7.   currentTime := time.Now().String() 
  8.  
  9.   newBlock := &Block { 
  10.     Timestamp: currentTime, 
  11.     PrevHash: n.BlockchainHead.Hash, 
  12.     Hash: NewBlockHash(n.BlockchainHead), 
  13.     ValidatorAddr: Validator.Address, 
  14.   } 
  15.  
  16.   if err := n.ValidateBlockCandidate(newBlock); err != nil { 
  17.     Validator.Stake -= 10 
  18.     return n.Blockchain, n.BlockchainHead, err 
  19.   } else { 
  20.     n.Blockchain = append(n.Blockchain, newBlock) 
  21.   } 
  22.   return n.Blockchain, newBlock, nil 

在檢查Blockchain是否完好無損之后,我們獲得了系統(tǒng)的當前時間,將其存儲為Timestamp實例化new時的時間Block。我們還附上了Hash以前值,您可以輕松訪問BlockchainHead。之后我們將在NewBlockHash()上調(diào)用方法BlockchainHead,并將輸入的地址分配Node為我們的驗證器地址。

一旦新塊的字段被填滿,我們調(diào)用ValidateBlockCandidate()上新Block,看看有沒有錯誤。如果有,我們返回一層。如果沒有,我們將把新塊附加到區(qū)塊鏈上。

但是,NewBlockHash()是如何工作的呢?我們有兩個函數(shù)來完成為每個塊創(chuàng)建唯一Hash的任務(wù)。函數(shù) New Block Hash ()只是獲取 Block 的所有信息,并將其連接成一個字符串傳遞給 new Hash ()。

  1. func NewBlockHash(block *Block) string { 
  2.   blockInfo := block.Timestamp + block.PrevHash + block.Hash + block.ValidatorAddr 
  3.   return newHash(blockInfo) 
  4.  
  5. func newHash(s string) string { 
  6.   h := sha256.New() 
  7.   h.Write([]byte(s)) 
  8.   hashed := h.Sum(nil) 
  9.   return hex.EncodeToString(hashed) 

接下來,newHash()將利用該crypto/sha256包創(chuàng)建一個存儲為的新SHA256對象h。然后,我們將輸入字符串s轉(zhuǎn)換為字節(jié)數(shù)組,并將其寫入h。最后,我們使用h.Sum()讓h進入的格式,我們可以調(diào)用hex.EncodeToString(),使我們有一個string為我們的最終輸出。

驗證我們的區(qū)塊鏈

如果你不能驗證,則區(qū)塊鏈就沒有用。在這里,我們將ValidateBlockchain()方法附加到PoSNetwork結(jié)構(gòu),并返回一個可能的錯誤。如果區(qū)塊鏈是空的或者只有一個區(qū)塊,我們無法確保它是正確的所以我們只返回nil。

接下來,我們評估區(qū)塊鏈中每對塊之間的三個獨立條件。第一個檢查是前一個塊的哈希值是否等于當前塊為它的前一哈希值存儲的值。

  1. func (n PoSNetwork) ValidateBlockchain() error { 
  2.   if len(n.Blockchain) <= 1 { 
  3.     return nil 
  4.   } 
  5.  
  6.   currBlockIdx := len(n.Blockchain)-1 
  7.   prevBlockIdx := len(n.Blockchain)-2 
  8.  
  9.   for prevBlockIdx >= 0 { 
  10.     currBlock := n.Blockchain[currBlockIdx] 
  11.     prevBlock := n.Blockchain[prevBlockIdx] 
  12.     if currBlock.PrevHash != prevBlock.Hash { 
  13.       return errors.New("blockchain has inconsistent hashes"
  14.     } 
  15.  
  16.     if currBlock.Timestamp <= prevBlock.Timestamp { 
  17.       return errors.New("blockchain has inconsistent timestamps"
  18.     } 
  19.  
  20.     if NewBlockHash(prevBlock) != currBlock.Hash { 
  21.       return errors.New("blockchain has inconsistent hash generation"
  22.     } 
  23.     currBlockIdx-- 
  24.     prevBlockIdx-- 
  25.   } 
  26.   return nil 

我們還要檢查是否在任何點上一個塊的時間戳比當前塊新。如果當前的Block是在2020年制造的,但之前的Blot是在2021年制造,此時就知道出問題了。

最后,我們還要直接計算Hash前一個的Block,我們?nèi)匀粫』豀ash當前的Block。如果滿足這些條件中的任何一個,則error由于我們的區(qū)塊鏈處于篡改狀態(tài),我們將返回。

現(xiàn)在我們已經(jīng)驗證了整個區(qū)塊鏈,我們需要確保要添加的下一個Block也是有效的。遵循與上述相同的條件檢查,僅適用于要添加的單個新塊。

  1. func (n PoSNetwork) ValidateBlockCandidate(newBlock *Block) error { 
  2.   if n.BlockchainHead.Hash != newBlock.PrevHash { 
  3.     return errors.New("blockchain HEAD hash is not equal to new block previous hash"
  4.   } 
  5.  
  6.   if n.BlockchainHead.Timestamp >= newBlock.Timestamp { 
  7.     return errors.New("blockchain HEAD timestamp is greater than or equal to new block timestamp"
  8.   } 
  9.  
  10.   if NewBlockHash(n.BlockchainHead) != newBlock.Hash { 
  11.     return errors.New("new block hash of blockchain HEAD does not equal new block hash"
  12.   } 
  13.   return nil 

現(xiàn)在我們已經(jīng)完成了向區(qū)塊鏈添加新區(qū)塊以及驗證其正確性的步驟。那么,我們?nèi)绾螞Q定何時添加新塊?

這就是我們的驗證器起作用的地方,對于每個與網(wǎng)絡(luò)有利益關(guān)系的節(jié)點,我們將通過抽獎方法隨機選擇一個節(jié)點,以偽造區(qū)塊鏈中的下一個區(qū)塊并獲得獎勵。

首先,我們首先需要一個Node。要添加新的Node給我們的PoSNetwork,我們稱之為NewNode()它接受的初始股份Node,并返回一個新的數(shù)組Node引用。這里沒有什么幻想,我們只是追加到n.Validators數(shù)組并調(diào)用randAddress()以為new生成唯一地址Node。

  1. func (n PoSNetwork) NewNode(stake int) []*Node { 
  2.   newNode := &Node{ 
  3.     Stake:   stake, 
  4.     Address: randAddress(), 
  5.   } 
  6.   n.Validators = append(n.Validators, newNode) 
  7.   return n.Validators 
  8.  
  9. func randAddress() string { 
  10.   b := make([]byte, 16) 
  11.   _, _ = math.Read(b) 
  12.   return fmt.Sprintf("%x", b) 

那么,我們?nèi)绾螌嶋H選擇獲勝者呢?有一點概率和統(tǒng)計信息!在該SelectWinner()方法中,我們首先通過覆蓋范圍找到網(wǎng)絡(luò)內(nèi)持有的全部股份n.Validators。我們還將所有權(quán)益大于零的節(jié)點添加到數(shù)組中winnerPool以進行可能的選擇。

如果發(fā)現(xiàn)winnerPool為空,則返回error。。然后,我們使用該Intn()方法選擇一個中獎號碼,該方法將從0到我們的總投注額之間選擇一個隨機數(shù)。

  1. func (n PoSNetwork) SelectWinner() (*Node, error) { 
  2.   var winnerPool []*Node 
  3.   totalStake := 0 
  4.   for _, node := range n.Validators { 
  5.     if node.Stake > 0 { 
  6.       winnerPool = append(winnerPool, node) 
  7.       totalStake += node.Stake 
  8.     } 
  9.   } 
  10.   if winnerPool == nil { 
  11.     return nil, errors.New("there are no nodes with stake in the network"
  12.   } 
  13.   winnerNumber := math.Intn(totalStake) 
  14.   tmp := 0 
  15.   for _, node := range n.Validators { 
  16.     tmp += node.Stake 
  17.     if winnerNumber < tmp { 
  18.       return node, nil 
  19.     } 
  20.   } 
  21.   return nil, errors.New("a winner should have been picked but wasn't"

最后一部分是概率發(fā)揮作用的地方。為了使每個節(jié)點都有Stake與網(wǎng)絡(luò)中的總數(shù)成正比的獲勝機會,我們將Stake電流的增量累加Node到tmp變量中。如果在任何時候獲勝的數(shù)字小于tmp,Node則被選為我們的獲勝者。

匯集全部

我們現(xiàn)在所需要的就是將我們的函數(shù)和數(shù)據(jù)類型綁定在一起。我們在main()函數(shù)中做好所有的事情,第一步是設(shè)置一個隨機種子與當前時間作為我們的輸入。不要使用時間作為隨機種子的輸入,因為它實際上會在解碼哈希輸出時引入安全漏洞。

在這個示例中,我們需要實例化一個新的ProofStake網(wǎng)絡(luò),其中有一個被稱為Genesis塊,也就是我們所知的塊。區(qū)塊鏈中的第一個區(qū)塊。一旦我們這樣做,我們也設(shè)置網(wǎng)絡(luò)的BlockchainHead等于第一個塊。

  1. func main() { 
  2.   // set random seed 
  3.   math.Seed(time.Now().UnixNano()) 
  4.  
  5.   // generate an initial PoS network including a blockchain with a genesis block. 
  6.   genesisTime := time.Now().String() 
  7.   pos := &PoSNetwork{ 
  8.     Blockchain: []*Block{ 
  9.       { 
  10.         Timestamp: genesisTime, 
  11.         PrevHash: ""
  12.         Hash: newHash(genesisTime), 
  13.         ValidatorAddr: ""
  14.       }, 
  15.     }, 
  16.   } 
  17.   pos.BlockchainHead = pos.Blockchain[0] 
  18.  
  19.   // instantiate nodes to act as validators in our network 
  20.   pos.Validators = pos.NewNode(60) 
  21.   pos.Validators = pos.NewNode(40) 
  22.  
  23.   // build 5 additions to the blockchain 
  24.   for i := 0; i < 5; i++ { 
  25.     winner, err := pos.SelectWinner() 
  26.     if err != nil { 
  27.       log.Fatal(err) 
  28.     } 
  29.     winner.Stake += 10 
  30.     pos.Blockchain, pos.BlockchainHead, err = pos.GenerateNewBlock(winner) 
  31.     if err != nil { 
  32.       log.Fatal(err) 
  33.     } 
  34.     fmt.Println("Round ", i) 
  35.     fmt.Println("\tAddress:", pos.Validators[0].Address, "-Stake:", pos.Validators[0].Stake) 
  36.     fmt.Println("\tAddress:", pos.Validators[1].Address, "-Stake:", pos.Validators[1].Stake) 
  37.   } 
  38.  
  39.   pos.PrintBlockchainInfo() 

然后,我們添加兩個節(jié)點的網(wǎng)絡(luò)作為驗證器與60和40令牌作為他們的初始股份。在五次迭代中,我們將為區(qū)塊鏈選擇一個新的贏家,如果有任何錯誤,我們的程序?qū)⒈罎?因為做原型我們通過新選擇的贏家產(chǎn)生一個新的塊,并打印出每一輪的每個節(jié)點的總樁。

最后,我們將打印出我們新制作的區(qū)塊鏈:

  1. $ go run main.go  
  2. Round  0 
  3.         Address: f8d44bb083078de97b8428f4f9548130 -Stake: 70 
  4.         Address: de6ae18584f02b3388569191a04a4b4a -Stake: 40 
  5. Round  1 
  6.         Address: f8d44bb083078de97b8428f4f9548130 -Stake: 70 
  7.         Address: de6ae18584f02b3388569191a04a4b4a -Stake: 50 
  8. Round  2 
  9.         Address: f8d44bb083078de97b8428f4f9548130 -Stake: 80 
  10.         Address: de6ae18584f02b3388569191a04a4b4a -Stake: 50 
  11. Round  3 
  12.         Address: f8d44bb083078de97b8428f4f9548130 -Stake: 90 
  13.         Address: de6ae18584f02b3388569191a04a4b4a -Stake: 50 
  14. Round  4 
  15.         Address: f8d44bb083078de97b8428f4f9548130 -Stake: 100 
  16.         Address: de6ae18584f02b3388569191a04a4b4a -Stake: 50 
  17. Block 0 Info: 
  18.         Timestamp: 2021-04-12 MDT m=+0.000120025 
  19.         Previous Hash:  
  20.         Hash: c5d04de14efed52ce84889c6382f9d307d5b98093d93a84b419478 
  21.         Validator Address:  
  22. Block 1 Info: 
  23.         Timestamp: 2021-04-12 MDT m=+0.000277288 
  24.         Previous Hash: c5d04de14efed52ce84889c6382f9d307d5b98093d93a 
  25.         Hash: d58e90a75b71ac62ef938fc0148314a7f864ad50bd702f959e2d27 
  26.         Validator Address: f8d44bb083078de97b8428f4f9548130 
  27. Block 2 Info: 
  28.         Timestamp: 2021-04-12 MDT m=+0.000306562 
  29.         Previous Hash: d58e90a75b71ac62ef938fc0148314a7f864ad50bd702 
  30.         Hash: e6bfdd6c2c869607e2d9a81b84ddf4478756fedff78a03746cde11 
  31.         Validator Address: de6ae18584f02b3388569191a04a4b4a 
  32. Block 3 Info: 
  33.         Timestamp: 2021-04-12 MDT m=+0.000321755 
  34.         Previous Hash: e6bfdd6c2c869607e2d9a81b84ddf4478756fedff78a0 
  35.         Hash: 8e3dbacc4a610b1665658bc9e7238963eda0d5bbbf3ce809e8fa6e 
  36.         Validator Address: f8d44bb083078de97b8428f4f9548130 
  37. Block 4 Info: 
  38.         Timestamp: 2021-04-12 MDT m=+0.000333024 
  39.         Previous Hash: 8e3dbacc4a610b1665658bc9e7238963eda0d5bbbf3ce 
  40.         Hash: 22760f8deb96c354a4050a3c48741be062bccfa9c51571c170065a 
  41.         Validator Address: f8d44bb083078de97b8428f4f9548130 
  42. Block 5 Info: 
  43.         Timestamp: 2021-04-12 MDT m=+0.000347521 
  44.         Previous Hash: 22760f8deb96c354a4050a3c48741be062bccfa9c5157 
  45.         Hash: d2a5047f7d8a7696c1d0fb9ec49b56d2e71bbcedaaebc83a18b7a5 
  46.         Validator Address: f8d44bb083078de97b8428f4f9548130 

 

責任編輯:武曉燕 來源: 區(qū)塊鏈研究實驗室
相關(guān)推薦

2021-04-09 20:04:34

區(qū)塊鏈Go加密

2019-03-13 11:23:29

區(qū)塊鏈區(qū)塊鏈技術(shù)身份驗證

2019-06-24 16:30:33

區(qū)塊鏈零知識證明比特幣

2021-03-12 19:17:38

區(qū)塊鏈GoPython

2021-03-17 20:29:36

區(qū)塊鏈DEMOPython

2021-03-16 21:39:47

區(qū)塊鏈DEMOGo

2021-12-22 23:28:04

區(qū)塊鏈人工智能技術(shù)

2021-03-14 10:21:36

數(shù)據(jù)庫區(qū)塊鏈DNS

2022-01-10 10:56:37

區(qū)塊鏈技術(shù)比特幣

2021-04-08 18:39:57

JavaScriptExpress區(qū)塊鏈

2023-06-13 11:49:35

2021-12-13 14:05:27

區(qū)塊鏈金融技術(shù)

2021-09-23 22:40:10

區(qū)塊鏈比特幣技術(shù)

2018-03-27 09:52:30

區(qū)塊鏈數(shù)字貨幣比特幣

2021-05-10 15:09:47

區(qū)塊鏈互聯(lián)網(wǎng)金融

2021-04-20 10:30:43

區(qū)塊鏈安全互聯(lián)網(wǎng)

2021-05-13 16:13:21

區(qū)塊鏈以太坊NFT

2020-12-22 14:33:25

區(qū)塊鏈行業(yè)發(fā)展物聯(lián)網(wǎng)

2022-03-09 15:22:41

區(qū)塊鏈比特幣數(shù)字技術(shù)

2022-10-11 09:05:58

IPFS區(qū)塊鏈存儲
點贊
收藏

51CTO技術(shù)棧公眾號