1 区块链

引言

Blockchain是21世纪最具革命性的技术之一,它仍在不断成长发展,潜力无限。本质上来说,Blockchain是一个分布式数据库。但Blockchain的独特之处在于其是一个公开的数据库,而非私有数据库,每个人都可以拥有部分甚至整个数据库。如果想在数据库中添加一个新记录,需要征得其他数据库拥有者的同意。此外,Blockchain技术使数字货币和智能合约成为可能。
本文将基于Go语言构建简化版的blockchain,来实现数字货币。

区块(Block)

让我们从“ blockchain”中的“block”开始整个旅程。block存储价值信息,例如,比特币中的block存储交易信息。除此之外,block中包含一些其他信息,如版本、时间戳和上一个Block的hash值等
本文中,我们并不会按照比特币规范实现一个完整的blockchain,而是实现一个简化版本,仅仅包含一些重要的信息。block结构如下所示:
  • type Block struct {
  •     Timestamp     int64 
  •     Data          []byte
  •     PrevBlockHash []byte
  •     Hash          []byte
  • }
Timestamp表示Block被创建的时间戳,Data表示block中实际的价值信息,PrevBlockHash表示上一个Block的hash值,Hash表示该block本身的Hash值。比特币规范中,Timestamp、PrevBlockHash、Hash存储在独立的数据结构中,作为block的头信息;Data存储在另一个独立的数据结构种。本文中,我们将它们放在一个数据结构中,从而简化实现。
Hash值用于确保blockchain的安全。Hash计算是计算敏感的操作,即使在高性能电脑也需要花费一段时间来完成计算(这也就是为什么人们购买高性能GPU进行比特币挖矿的原因)。blockchain架构设计有意使Hash计算变得困难,这样做是为了加大新增一个block的难度,进而防止block在增加后被随意修改。
现在,我们首先SetHash方法,将Block中的字段信息组合后,生成该block的SHA-256 Hash值:
  • func (b *Block) SetHash() {
  •     timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))
  •     headers := bytes.Join([][]byte{b.PrevBlockHash, b.Data, timestamp}, []byte{})
  •     hash := sha256.Sum256(headers)

  •     b.Hash = hash[:]
  • }
接下来,实现NewBlock方法用于创建一个Block:
  • func NewBlock(data string, prevBlockHash []byte) *Block {
  •     block := &Block{time.Now().Unix(), []byte(data), prevBlockHash, []byte{}}
  •     block.SetHash()
  •     return block
  • }
OK,block实现完成啦!

区块链

现在,让我们来实现blockchain吧。本质上,blockchain仅仅是具备某种特殊结构的数据库:有序,反向链接链表。这意味着,block按照插入的顺序存放,同时每个block都保存指向上一个block的链接。这种结构保证可以快速获取最新插入的block同时获取它的hash值。
Go语言中,可以通过slice和map来实现该结构。slice(有序)用于保存有序的hash值,map(无序)用于保存hash->block对。对于我们的blockchain原型,目前不需要根据hash值来获取block,因此仅仅使用slice即可满足需求。blockchain结构如下:
  • type Blockchain struct {
  •     blocks []*Block
  • }
这就是我们的Blockchain,怎么样够简单吧??
接下来,我们事先AddBlock方法,用于将block添加到blockchain中:
  • func (bc *Blockchain) AddBlock(data string) {
  •     prevBlock := bc.blocks[len(bc.blocks)-1]
  •     newBlock := NewBlock(data, prevBlock.Hash)
  •     bc.blocks = append(bc.blocks, newBlock)
  • }
新增一个block的前提是另一个block已经存在,但是一开始blockchain中并没有任何block。因此,在任何blockchain中都必须有一个特殊的block存在,称之为GenesisBlock。下面实现NewGenesisBlock方法用于创建GenesisBlock:
  • func NewGenesisBlock() *Block {
  •     return NewBlock("Genesis Block", []byte{})
  • }
接下来,实现NewBlockchain方法,该方法会创建一个包含Genesis Block的blockchain:
  • func NewBlockchain() *Blockchain {
  •     return &Blockchain{[]*Block{NewGenesisBlock()}}
  • }
最后让我们看看Blockchain是否可以正常工作吧:
  • func main() {
  •     bc := NewBlockchain()

  •     bc.AddBlock("Send 1 BTC to Ivan")
  •     bc.AddBlock("Send 2 more BTC to Ivan")

  •     for _, block := range bc.blocks {
  •         fmt.Printf("Prev. hash: %x\n", block.PrevBlockHash)
  •         fmt.Printf("Data: %s\n", block.Data)
  •         fmt.Printf("Hash: %x\n", block.Hash)
  •         fmt.Println()
  •     }
  • }
输出:
  • Prev. hash:
  • Data: Genesis Block
  • Hash: aff955a50dc6cd2abfe81b8849eab15f99ed1dc333d38487024223b5fe0f1168

  • Prev. hash: aff955a50dc6cd2abfe81b8849eab15f99ed1dc333d38487024223b5fe0f1168
  • Data: Send 1 BTC to Ivan
  • Hash: d75ce22a840abb9b4e8fc3b60767c4ba3f46a0432d3ea15b71aef9fde6a314e1

  • Prev. hash: d75ce22a840abb9b4e8fc3b60767c4ba3f46a0432d3ea15b71aef9fde6a314e1
  • Data: Send 2 more BTC to Ivan
  • Hash: 561237522bb7fcfbccbc6fe0e98bbbde7427ffe01c6fb223f7562288ca2295d1
大功告成!

总结

我们构建了一个简单的blockchain原型:目前该blockchain仅仅是一个block数组,每个block有一个指向上一个block的链接。而实际应用的blockchain更加复杂。在我们的blockchain中,添加新的block简单而快速,而实际应用中的blockchain添加block之前需要进行一些复杂计算操作(即工作量证明机制)。同时,blockchain是一个非单一决策者的分布式数据库。因此,添加新block需要被所有参与者同意(即一致性协议)。此外,在我们的blockchain中还没有任何Transaction信息!
在未来的文章中,我们讨论上述的所有特性。

本文来自 gitbooks zhangli1的书一章, 他翻译自Ivan Kuznetsov的系列文章《Building Blockchain in Go》,原文地址: https://jeiwan.cc . 程序代码都在 https://github.com/Jeiwan/blockchain_go中.

我在阅读和实践中, 为本文做了一些注解以便更好的理解.

有任何问题欢迎在下方评论讨论.

立即登录, 发表评论.
没有帐号? 立即注册