这篇文章在之前的基础上,解决多个节点网络内,如何生成块、如何通信、如何广播消息等。
流程:
- 第一个节点创建“创始区块”,同时启动TCPserver并监听一个端口,等待其他节点连接。 - 启动其他节点,并与第一个节点建立TCP连接(这里我们通过不同的终端来模拟其他节点) - 创建新的块 - 第一个节点验证新生成块 - 验证之后广播(链的新状态)给其他节点 - 所有的节点都同步了最新的链的状态
之后你可以重复上面的步骤,使得每个节点都创建TCPserver并监听(不同的)端口以便其他节点来连接。通过这样的流程你将建立一个简化的模拟的(本地的)P2P网络,当然你也可以将节点的代码编译后,将二进制程序部署到云端。
开始coding吧
设置与导入依赖:
参考之前第一篇文章,我们使用相同的计算hash的函数、验证块数据的函数等。
设置:
在工程的根目录创建一个.env文件,并添加配置:
ADDR=9000
通过go-spew包将链数据输出到控制台,方便我们阅读:
go get github.com/davecgh/go-spew/spew
通过godotenv包来加载配置文件:
go get github.com/joho/godotenv
之后创建main.go文件。
导入:
接着我们导入所有的依赖:
import ( "bufio" "crypto/sha256" "encoding/hex" "encoding/json" "io" "log" "net" "os" "strconv" "time" "github.com/davecgh/go-spew/spew" "github.com/joho/godotenv" )
回顾:
让我们再快速回顾下之前的重点,我们创建一个Block结构体,并声明一个Block类型的slice,Blockchain:
// Block represents each "item" in the blockchain type Block struct { Index int Timestamp string BPM int Hash string PrevHash string }
// Blockchain is a series of validated Blocks var Blockchain []Block
创建块时计算hash值的函数:
// SHA256 hashing function func calculateHash(block Block) string { record := string(block.Index) + block.Timestamp + string(block.BPM) + block.PrevHash h := sha256.New() h.Write([]byte(record)) hashed := h.Sum(nil) return hex.EncodeToString(hashed) }
创建块的函数:
// create a new block using previous block's hash func generateBlock(oldBlock Block, BPM int) (Block, error) { var newBlock Block
t := time.Now() newBlock.Index = oldBlock.Index + 1 newBlock.Timestamp = t.String() newBlock.BPM = BPM newBlock.PrevHash = oldBlock.Hash newBlock.Hash = calculateHash(newBlock)
return newBlock, nil }
验证块数据的函数:
// make sure block is valid by checking index, and comparing the hash of the previous block func isBlockValid(newBlock, oldBlock Block) bool { if oldBlock.Index+1 != newBlock.Index { return false }
if oldBlock.Hash != newBlock.PrevHash { return false }
if calculateHash(newBlock) != newBlock.Hash { return false }
return true }
确保各个节点都以最长的链为准:
// make sure the chain we're checking is longer than the current blockchain func replaceChain(newBlocks []Block) { if len(newBlocks) > len(Blockchain) { Blockchain = newBlocks } }
网络通信:
接着我们来建立各个节点间的网络,用来传递块、同步链状态等。
我们先来声明一个全局变量bcServer,以channel(译者注:channel类似其他语言中的Queue,代码中声明的是一个Block数组的channel)的形式来接受块。
// bcServer handles incoming concurrent Blocks var bcServer chan []Block
注:Channel是Go语言中很重要的特性之一,它使得我们以流的方式读写数据,特别是用于并发编程。通过这里[2]可以更深入地学习Channel。
接下来我们声明main函数,从.env加载配置,也就是端口号,然后实例化bcServer
func main() { err := godotenv.Load() if err != nil { log.Fatal(err) } bcServer = make(chan []Block)
2021年,互联网与科技迈入了一个新的关口,一方面,旧的蓝海已被悉数挖掘,增量市场已达到天花板,智能手机、消费生活、本地出行都慢慢进入存量市场的厮杀。另一方面,突破性的基础技术又处于爆发前夕,虚拟现实、人工智能、电动汽车...
所谓区块链技术,简称BT(Blockchain technology),又称分布式账本技术,是一种网络数据库技术,其特点是分散、开放、透明,使每个人都能参与数据库记录。区块链的基本原理理解起来并不难。基本概念包括:交易(...
最近,由中国、硅谷、韩国、德国和英国技术团队联合发起的以太国际项目(ETU区块链和覆盖网络,中文名称:以太宇宙)引起了公众的关注。经过深入的分析和比较,提出了具有技术优势和特点的解决方案,即提供高效可行的基础EOS.IO...
今天的区块链市场仍然充满了安全问题。2021年,与加密货币有关的犯罪损失超过 140 1亿美元,比去年增长了近 57%。然而,与集中网络相比,区块链在设计上有许多固有的安全优势。这就导致了一个问题:由于区块链在设计上是安...