内容简介:为什么说是最简单的区块链呢,因为根本写不出一个完整的区块链,甚至连区块链的Demo都算不上。本文充其量可以当做Go语言的一个入门教程,至少对我来说是这样。所以,即使读者没有任何区块链和Go语言的知识,也可以放心往下看。本文使用Go语言实现了区块链源自比特币,当年中本聪计划打造一个完全去中心化的电子货币交易系统,区块链应运而生。发明区块链的动机,大概是中本聪觉得,任何中心化的系统都不够安全,一旦把特权赋予某些人,就存在滥用职权和腐败的可能。只有在去中心化的系统中,才会存在绝对的安全。
前言
为什么说是最简单的区块链呢,因为根本写不出一个完整的区块链,甚至连区块链的Demo都算不上。本文充其量可以当做 Go 语言的一个入门教程,至少对我来说是这样。所以,即使读者没有任何区块链和Go语言的知识,也可以放心往下看。
本文使用Go语言实现了
- 区块的定义和构建
- 区块链的定义和构建
- 添加交易
- 查看区块链内容
- 提供Go API和Web API两种方式
区块链的概念
区块链源自比特币,当年中本聪计划打造一个完全去中心化的电子货币交易系统,区块链应运而生。发明区块链的动机,大概是中本聪觉得,任何中心化的系统都不够安全,一旦把特权赋予某些人,就存在滥用职权和腐败的可能。只有在去中心化的系统中,才会存在绝对的安全。
去中心化其实很简单,直接让每一个节点都保存完整的交易信息,自然就不需要中心节点了。但这样会造成资源的极大浪费,也会造成通信的拥堵。不过比特币似乎就是这样干的,毕竟比特币的总量不算很多,交易量也不至于太大。
去中心化的另一个问题是需要共识机制。因为区块链是一个单向链表,如果两个节点同时想要向链表头部添加元素,势必造成链表的分叉。共识机制规定了整个网络中最长的那个链为有效链,任何节点一旦发现其它链比本地保存的链更长,就必须更换为那个最长的链。
此外,节点是不能随意向区块链中添加元素的,否则谁添加的最快,谁的区块链就最长,那岂不是成了速度竞赛。制约的方法是,一个节点产生的交易,必须由另一个节点记账,才能加入区块链中。为了鼓励人们积极为其他人记账,中本聪设计了“工作量证明”这一环节,也就是我们俗称的“挖矿”。成功为他人记账的节点,会收到若干个比特币的奖励。这样一来,人们蜂拥而至,争先为别人记账,但交易数量有限,多个人同时记账只会有一个人记账成功,其他人无功而返。为了使这一过程不受网速的影响,使大家能够公平竞争,中本聪规定,记账者必须得到若干个0开头的账单摘要才算记账成功。所谓账单摘要,就是把账单数据按照规定的组合方式,加上随机数,再经过某种哈希算法(比如SHA256)得到的固定长度的数据串。目前的规定是以18个0开头,每个0是一个16进制数字,也就相当于平均每尝试16 18 次才可能得到一个符合条件的账单摘要。这也是为什么挖矿需要消耗大量的计算资源,而且挖矿会越来越难(数字0开头的数量还会进一步增多)。
说了这么多理论,也该开始实践了。但说着容易做着难,我们没法把上面提到的所有特性都实现出来,只能实现最基础的功能。即使如此,对帮助大家直观地了解区块链也已经足够了。
Go语言实现区块链
如果手边有一台电脑,建议按照本节的流程亲自敲一遍代码。
0.配置开发环境
本来想把如何配置开发环境写一写,但实在太繁琐,又难以满足不同系统用户的需求,遂作罢。大家只能发挥自己的聪明才智搞一搞了。
1. 定义区块
// file: Block.go package core import ( "crypto/sha256" "encoding/hex" "time" ) type Block struct { // Block header Index int64 Timestamp int64 PrevBlockHash string Hash string // Block data Data string } func createBlock(prevBlock Block, data string) Block{ newBlock := Block{} newBlock.Index = prevBlock.Index + 1 newBlock.Timestamp = time.Now().Unix() newBlock.PrevBlockHash = prevBlock.Hash newBlock.Data = data newBlock.Hash = calculateHash(newBlock) return newBlock } func calculateHash(block Block) string { toBeHashed := string(block.Index) + string(block.Timestamp) + block.PrevBlockHash + block.Data hashInBytes := sha256.Sum256([]byte(toBeHashed)) return hex.EncodeToString(hashInBytes[:]) }
这段代码定义了一个结构体 Block
,用来表示一个区块。区块包含区块头和数据两部分,其中,区块头包括序号 Index
、时间戳 Timestamp
、上一区块的摘要 PrevBlockHash
以及当前区块的摘要 Hash
。数据为了简单起见,直接用 string
类型表示。
下面两个私有函数分别用来创建区块和计算给定区块的摘要。之所以称为私有函数,是因为函数名以小写字母开头,Go编译器自动按照函数名首字母的大小写决定该函数的访问级别。在 calculateHash
函数中,我们把序号、时间戳、上一区块的摘要以及数据连接成一个长字符串,并计算该字符串的哈希值,作为当前区块的摘要。需要注意,Go语言中声明变量可以不显式指定类型,但需要用 :=
符号来初始化。
2. 定义区块链
// file: BlockChain.go package core import "fmt" type BlockChain struct { Blocks []*Block } func CreateBlockChain() BlockChain { genesisBlock := createBlock(Block{Index:-1}, "I am genesis block.") blockChain := BlockChain{} blockChain.Blocks = append(blockChain.Blocks, &genesisBlock) return blockChain } func (blockChain *BlockChain) AddTransaction(data string) { block := createBlock(*blockChain.Blocks[len(blockChain.Blocks) - 1], data) blockChain.Blocks = append(blockChain.Blocks, █) } func (blockChain *BlockChain) Print() { for _, block := range blockChain.Blocks { fmt.Printf("Index: %d\n", block.Index) fmt.Printf("Timestamp: %d\n", block.Timestamp) fmt.Printf("PreBlockHash: %s\n", block.PrevBlockHash) fmt.Printf("Hash: %s\n", block.Hash) fmt.Printf("Data: %s\n", block.Data) fmt.Println() } }
这里,我们把区块链定义为另一个结构体,内部包含区块的数组切片。Go语言中的数组切片,其实就是变长数组,它的容量依赖于实际数组的长度。
我们提供了三个公有函数。 CreateBlockChain
用来创建一个新的区块链,在该函数中自动创建了一个区块,称为“创世区块”,该区块不含任何数据,Index为0,只用于标识区块链的起点。 AddTransaction
函数用来添加交易,内部会创建一个新的区块,并链接到区块链上。 Print
函数用来打印完整的区块链信息。
细心的话可以发现,这里的函数名前面增加了一些内容。在Go语言中,这种函数称为方法,方法名前面的部分是接收者,类似于C++中的this指针。 AddTransaction
和 Print
方法都声明了 BlockChain
类型的接收者,于是这两个方法可以当做 BlockChain
类型的成员函数来使用。
3. Go API Demo
以上已经实现了区块链的核心功能。我们现在写一个demo来测试一下效果。
// file: main.go package main import ( "BlockChainDemo/core" ) func main() { blockChain := core.CreateBlockChain() blockChain.AddTransaction("Send 1 BTC to Faye.") blockChain.AddTransaction("Send 2 BTC to Liling.") blockChain.Print() }
Go语言的主函数必须位于 main
包中,否则不能执行。运行该程序,输出结果为
Index: 0 Timestamp: 1538731505 PreBlockHash: Hash: f8970ec722193096998452516c709c1890323e5df5bd7cf1e139b9c592394f6d Data: I am genesis block. Index: 1 Timestamp: 1538731505 PreBlockHash: f8970ec722193096998452516c709c1890323e5df5bd7cf1e139b9c592394f6d Hash: 12f8ca6f66b0b21e6d1ed7682265f849f46e4a4ff10e6ba794021eb25d0ab033 Data: Send 1 BTC to Faye. Index: 2 Timestamp: 1538731505 PreBlockHash: 12f8ca6f66b0b21e6d1ed7682265f849f46e4a4ff10e6ba794021eb25d0ab033 Hash: 1c849f10a0da4f2aa45275f1585ddc700fa46c24cb8162484bf628a16aeac5a0 Data: Send 2 BTC to Liling.
可以看到,添加两次交易后,区块链的长度变为3,除了创世节点,后面每个节点表示一次交易。每个区块的 Hash
值与当前区块和上一区块都有关,因此任何人都无法篡改历史数据,任何微小的改动都会导致后面链条中所有数据的变化。
4. Web API Demo
最后一部分,发挥Go语言强大的Web编程能力,我们提供一个Web API供HTTP访问使用。
// file: server.go package main import ( "BlockChainDemo/core" "encoding/json" "io" "net/http" ) var blockChain core.BlockChain func run() { http.HandleFunc("/blockchain/get", blockchainGetHandler) http.HandleFunc("/blockchain/write", blockchainWriteHandler) http.ListenAndServe("localhost:8888", nil) } func blockchainGetHandler(writer http.ResponseWriter, request *http.Request) { bytes, error := json.MarshalIndent(blockChain, "", "\t") if error != nil { http.Error(writer, error.Error(), http.StatusInternalServerError) return } io.WriteString(writer, string(bytes)) } func blockchainWriteHandler(writer http.ResponseWriter, request *http.Request) { data := request.URL.Query().Get("data") blockChain.AddTransaction(data) blockchainGetHandler(writer, request) } func main() { blockChain = core.CreateBlockChain() run() }
实现方法非常简单,设置两个回调函数,对应两个URL,一个用来查询当前区块链,另一个用来向区块链中添加交易。运行此程序,然后打开浏览器,访问 http://localhost:8888/blockchain/get ,可以看到如下结果
get
此时只有创世区块。接下来添加一个交易
http://localhost:8888/blockchain/write?data=Send 1 BTC to Faye.现在区块链变成了这样
write
每调用一次,区块链中就添加一个区块。
好了,到此为止,我们已经实现了预定的全部功能。
完整代码已上传GitHub,请点击 jingedawang/BlockChainDemo 下载。
总结
区块链并没有想象中那么神秘,也不是无所不能。最初版本的区块链有很大局限性,所以才有了区块链2.0、3.0,以及以太坊、智能合约的出现。想真正了解区块链,不深入到行业应用中是不行的,所以本文只是浅尝辄止,抛砖引玉而已。鉴于当下区块链工程师年薪百万,我想,是时候考虑转行了:-)
参考资料
区块链技术核心概念与原理讲解 慕课网
用GO语言构建自己的区块链 慕课网
Go 语言教程 菜鸟教程
golang 函数以及函数和方法的区别 D_Guco
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 区块链技术+区块链怎么赚钱?
- 区块链技术入门:区块链是什么
- 阿里申请可“行政干预”区块链专利,区块链变味?
- 中国区块链商学院:区块链基础知识
- 从Java到区块链:如何成为区块链开发人员
- 通过python构建一个区块链来学习区块链
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
统计自然语言处理
宗成庆 / 清华大学出版社 / 2008-5 / 66.00元
内容简介 本书全面介绍了统计自然语言处理的基本概念、理论方法和最新研究进展,内容包括形式语言与自动机及其在自然语言处理中的应用、语言模型、隐马尔可夫模型、语料库技术、汉语自动分词与词性标注、句法分析、词义消歧、统计机器翻译、语音翻译、文本分类、信息检索与问答系统、自动文摘和信息抽取、口语信息处理与人机对话系统等,既有对基础知识和理论模型的介绍,也有对相关问题的研究背景、实现方法和技术现状的详......一起来看看 《统计自然语言处理》 这本书的介绍吧!
CSS 压缩/解压工具
在线压缩/解压 CSS 代码
HEX CMYK 转换工具
HEX CMYK 互转工具