引言

区块链是 21 世纪最具革命性的技术之一,它仍然处于不断成长的阶段,而且还有很多潜力尚未显现出来。 本质上,区块链只是一个分布式数据库而已。 不过,使它独一无二的是,区块链是一个公开的数据库,而不是一个私人数据库,也就是说,每个使用它的人都有一个完整或部分的副本。 只有经过其他数据库管理员的同意,才能向数据库中添加新的记录。 此外,也正是由于区块链,才使得加密货币和智能合约成为现实。

在本系列文章中,我们将实现一个简化版的区块链,基于它来构建简化版的加密货币。

区块

让我们从 “区块链” 中的 “区块” 谈起。在区块链中,存储有效信息的是区块。比如,比特币区块存储的有效信息,就是比特币交易,交易信息也是所有加密货币的本质。除此以外,区块还包含了一些技术信息,比如版本,当前时间戳和前一个区块的哈希。

在本文中,我们并不会实现一个像比特币技术规范所描述的区块链,而是实现一个简化版的区块链,它仅包含了一些关键信息。看起来就像是这样:

type Block struct {Timestamp     int64Data          []bytePrevBlockHash []byteHash          []byte
}
  • Timestamp 是当前时间戳,也就是区块创建的时间。
  • Data 是区块存储的实际有效的信息。
  • PrevBlockHash 存储的是前一个块的哈希。
  • Hash 是当前块的哈希。

在比特币技术规范中,Timestamp, PrevBlockHash, Hash 是区块头(block header),区块头是一个单独的数据结构。而交易,也就是这里的 Data, 是另一个单独的数据结构。为了简便起见,我把这两个混合在了一起。

那么,我们要如何计算哈希呢?如何计算哈希,是区块链一个非常重要的部分。正是由于这个特性,才使得区块链是安全的。计算一个哈希,是在计算上非常困难的一个操作。即使在高速电脑上,也要花费不少时间 (这就是为什么人们会购买 GPU 来挖比特币) 。这是一个有意为之的架构设计,它故意使得加入新的区块十分困难,因此可以保证区块一旦被加入以后,就很难再进行修改。在本系列未来几篇文章中,我们将会讨论和实现这个机制。

目前,我们仅取了 Block 结构的一些字段(Timestamp, Data 和 PrevBlockHash),并将它们相互连接起来,然后在连接后的结果上计算一个 SHA-256 的哈希. 让我们在SetHash方法中完成这个任务:

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[:]
}

接下来,按照 Golang 的惯例,我们会实现一个用于简化创建一个区块的函数:

func NewBlock(data string, prevBlockHash []byte) *Block {block := &Block{time.Now().Unix(), []byte(data), prevBlockHash, []byte{}}block.SetHash()return block
}

这就是区块部分的全部内容了!

区块链

下面让我们来实现一个区块链。本质上,区块链仅仅是一个有着特定结构的数据库,是一个有序,后向连接的列表。这也就是说,区块按照插入的顺序进行存储,每个块都被连接到前一个块。这样的结构,能够让我们快速地获取链上的最新块,并且高效地通过哈希来检索一个块。

在 Golang 中,可以通过一个 array 和 map 来实现这个结构:array 存储有序的哈希(Golang 中 array 是有序的),map 存储 hask -> block 对(Golang 中, map 是无序的)。 但是在基本的原型阶段,我们只用到了 array,因为现在还不需要通过哈希来获取块。

type Blockchain struct {blocks []*Block
}

这就是我们的第一个区块链!我从来没有想过它会是这么容易。

现在,让我们能够给它添加一个块:

func (bc *Blockchain) AddBlock(data string) {prevBlock := bc.blocks[len(bc.blocks)-1]newBlock := NewBlock(data, prevBlock.Hash)bc.blocks = append(bc.blocks, newBlock)
}

完成!不过,真的就这样了吗?

为了加入一个新的块,我们必须要有一个已有的块,但是,现在我们的链是空的,一个块都没有!所以,在任何一个区块链中,都必须至少有一个块。这样的块,也就是链中的第一个块,通常叫做创世块(genesis block). 让我们实现一个方法来创建一个创世块:

func NewGenesisBlock() *Block {return NewBlock("Genesis Block", []byte{})
}

现在,我们可以实现一个函数来创建有创世块的区块链:

func NewBlockchain() *Blockchain {return &Blockchain{[]*Block{NewGenesisBlock()}}
}

来检查一个我们的区块链是否如期工作:

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: aff955a50dc6cd2abfe81b8849eab15f99ed1dc333d38487024223b5fe0f1168Prev. hash: aff955a50dc6cd2abfe81b8849eab15f99ed1dc333d38487024223b5fe0f1168
Data: Send 1 BTC to Ivan
Hash: d75ce22a840abb9b4e8fc3b60767c4ba3f46a0432d3ea15b71aef9fde6a314e1Prev. hash: d75ce22a840abb9b4e8fc3b60767c4ba3f46a0432d3ea15b71aef9fde6a314e1
Data: Send 2 more BTC to Ivan
Hash: 561237522bb7fcfbccbc6fe0e98bbbde7427ffe01c6fb223f7562288ca2295d1

总结

我们创建了一个非常简单的区块链原型:它仅仅是一个数组构成的一系列区块,每个块都与前一个块相关联。真实的区块链要比这复杂得多。在我们的区块链中,加入新的块非常简单,而且很快,但是在真实的区块链中,加入新的块需要很多工作:你必须要经过十分繁重的计算(这个机制叫做工作量证明),来获得添加一个新块的权力。并且,区块链是一个没有单一决策者的分布式数据库。因此,一个新的块必须要被网络的其他参与者确认和同意(这个机制叫做共识(consensus))。还有一点,我们的区块链还没有任何的交易!

在接下来的文章的我们将会一一覆盖这些特性。


  1. 本文涉及的源代码:part_1
  2. 区块哈希算法:https://en.bitcoin.it/wiki/Block_hashing_algorithm

原文链接: https://jeiwan.cc/posts/building-blockchain-in-go-part-1/
作者: GOLANG BLOCKCHAIN BITCOIN
翻译: liuchengxu

liuchengxu的简书: http://www.jianshu.com/u/daf68451f175
liuchengxu的GitHub: https://github.com/liuchengxu/

用 Go 构建一个区块链 -- Part 1: 基本原型相关推荐

  1. 用 Go 构建一个区块链 ---- Part 1: 基本原型

    翻译的系列文章我已经放到了 GitHub 上:blockchain-tutorial,后续如有更新都会在 GitHub 上,可能就不在这里同步了.如果想直接运行代码,也可以 clone GitHub ...

  2. 通过python构建一个区块链来学习区块链

    了解区块链Blockchains如何工作的最快方法就是构建一个区块链.你来到这里是因为,和我一样,你对加密钱币的崛起感到很兴奋.而且你想知道区块链是如何工作的,想了解它们背后的基本技术. 但理解区块链 ...

  3. php构建一个区块链(含源码)

    php构建一个区块链(含源码) 我们要用PHP编程语言构建区块链,区块链本身就是一个非常简单的概念,它是一个非常简单的数据结构,数字货币是很复杂,但区块链不是,它们复杂的原因是共识算法,挖矿机制和运行 ...

  4. 用 Go 构建一个区块链 -- Part 7: 网络

    翻译的系列文章我已经放到了 GitHub 上:blockchain-tutorial,后续如有更新都会在 GitHub 上,可能就不在这里同步了.如果想直接运行代码,也可以 clone GitHub ...

  5. 用 Go 构建一个区块链 -- Part 6: 交易(2)

    翻译的系列文章我已经放到了 GitHub 上:blockchain-tutorial,后续如有更新都会在 GitHub 上,可能就不在这里同步了.如果想直接运行代码,也可以 clone GitHub ...

  6. 用 Go 构建一个区块链 -- Part 3: 持久化和命令行接口

    翻译的系列文章我已经放到了 GitHub 上:blockchain-tutorial,后续如有更新都会在 GitHub 上,可能就不在这里同步了.如果想直接运行代码,也可以 clone GitHub ...

  7. 【区块链新手快速入门】如何构建一个区块链

    本文翻译自<Learn Blockchains by Building One>,作者@dvf,原文链接:https://hackernoon.com/learn-blockchains- ...

  8. 200行代码构建一个区块链

    区块链的基本概念非常简单:一个存储不断增加的有序记录的分布式数据库.然而,当我们谈论区块链时,我们很容易将其与区块链要解决的问题混淆,比如误解为流行的,基于区块链的,像比特币和以太坊一样的项目.术语& ...

  9. 用Go 构建一个区块链 -- Part 5: 地址

    链客,专为开发者而生,有问必答! 此文章来自链客区块链技术问答社区,未经允许拒绝转载. 比特币地址 这就是一个真实的比特币地址:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa.这 ...

最新文章

  1. python入门指南 许半仙 txt-小九 第7章(1/1)_新笔趣阁
  2. scp 是我小看了你-基于密钥传输!
  3. RabbitMQ(三) ——发布订阅
  4. 嵌入式Linux系统编程学习之二十八线程的等待退出
  5. 十条不错的编程观点(转)
  6. Web前后端缓存技术(缓存的主要作用是什么)
  7. ENVI波段运算模块功能
  8. HTTP头部POST表单详解
  9. 关于智能家居的四大思维误区 并非你想的那样
  10. 递归算法经典实例python-python实现十大经典算法
  11. oracle 序列号连号,火并VariPrint技术指标(HaiyaaVariPrint.PDF
  12. 【Keil变量定义】定义extern类型变量
  13. Moviepy自动化视频处理:添加音频、背景音乐,实现多轨音频
  14. 4 Kubernetes资源-Pod控制器(2)
  15. 屏保:毛雷尔玫瑰屏保
  16. 一加android系统用电量大,一加6T被曝将预装Android P 这一点其它品牌比不了
  17. 3D游戏与编程——UI系统
  18. Linux 显示行数 number
  19. 2021年5月23日
  20. 记录我的缺点、优点、记录生活方式,总结并不断优化自己

热门文章

  1. 2 环境设置_用友U8V10.1安装(Windows 7环境)
  2. 对php的感受100字_这首由半个古风圈歌手演唱的王者荣耀100英雄群像歌,燃炸了...
  3. Java-java.util.concurrent.locks.AbstractQueuedSynchronizer
  4. Spring-web-MultipartFile上传文件
  5. MIT6.830 lab4 SimpleDB Transactions 实验报告
  6. mysql重装第四步报错_Mysql 8.x 安装
  7. 求一个容器的最值的索引_初中数学:一道几何好题,学会“胡不归问题”动点最值解题方法...
  8. america/los_angeles 时区 java_在Java ME中将“America / Los Angeles”时区转换为“PST”或“PDT”...
  9. Joseph_Circle(约瑟夫环)
  10. litepal创建数据库表失败