自互联网诞生以来,区块链技术就被誉为最具颠覆性的创新之一。尽管很多人将区块链与那些价格波动剧烈的数字资产划等号,但实际上,区块链的应用远不止于此。加密货币只是区块链技术的一小部分,许多实际应用正由各个机构悄悄地推动着。
随着区块链技术的快速发展,越来越多的人开始意识到,掌握区块链的基础知识及其技术影响力至关重要。
构建自己的区块链听起来似乎遥不可及,但实际上并没有那么复杂。本文将带你使用 Go 语言(2021 年最受欢迎的编程语言之一)来实现一个简单的区块链。准备好了吗?让我们开始吧!
区块链,顾名思义,就是一个由信息块(Block)组成的链条。这些信息块通过哈希值(Hash)相互连接。哈希值是由输入数据生成的加密的、固定长度的输出。由于每个区块都通过哈希值引用前一个区块,因此,如果想要篡改链上的任何一个区块,就必须同时修改链上所有后续区块的哈希值。
区块链中的每个区块都可以包含几乎任何类型的数据。一个基本的框架会包含每个区块过去交易的所有记录。比特币就是以类似的方式运作的,因此你可以追溯每一笔交易,直到中本聪的首次加密货币交易。
假设我们要创建一个包含三个区块的区块链。第一个区块是创世区块,由于它是第一个区块,所以“前一个哈希值”字段为空。我们仍然使用时间戳和初始交易作为哈希算法的输入,该算法会生成一串数字和字母,这就是创世区块的哈希值。
对于第二个区块,我们将创世区块的哈希值作为第二个区块的“前一个哈希值”。这个操作将创世区块和第二个区块连接起来!接下来,我们将时间戳、交易列表和前一个哈希值作为哈希算法的输入,该算法会为我们提供一个表示第二个区块的新哈希值。
我们可以根据需要重复这个过程任意多次,除了区块的有效性和存储区块链的能力之外(比特币的区块链大约为 330 GB),没有任何其他限制。
构建区块链的第一步是定义什么是区块。Go 语言可以轻松地创建自定义类型。我们可以使用以下代码来定义 Block 类型。在这里,Block 结构体有四个字段,与上图中的区块结构相对应。
type Block struct { timestamp time.Time transactions []string prevHash []byte Hash []byte}
下一步是创建一个构造函数(Go 版本),用于创建新的区块。该函数的输入是一个字符串数组(表示交易)和一个字节数组(表示前一个区块的哈希值)。接下来,我们将研究 NewHash() 函数,这是我们下一步要实现的功能。
func NewBlock(transactions []string, prevHash []byte) *Block { currentTime := time.Now() return &Block{ timestamp: currentTime, transactions: transactions, prevHash: prevHash, Hash: NewHash(currentTime, transactions, prevHash), }}
NewHash() 函数将时间、交易列表和前一个哈希值作为输入参数,并返回一个字节数组,表示新生成的哈希值。在这个函数中,我们基本上只是将所有输入都混合到一个名为 input 的字节数组中。我们使用 append() 函数来附加 time 参数和 prevHash。通过将 time 转换为 string,并使用 ... 将 prevHash 切片作为后缀附加到 time 切片。
然后,我们遍历 transactions,并将每个单独的 transaction 附加到 input 数据块。有趣的语法 string(rune(transaction))... 只是 Go 语言中将 transactions 中的每个元素转换为可以附加到的切片的一种方法。
func NewHash(time time.Time, transactions []string, prevHash []byte) []byte { input := append(prevHash, time.String()...) for transaction := range transactions { input = append(input, string(rune(transaction))...) } hash := sha256.Sum256(input) return hash[:]}
最后,我们使用 crypto 包调用 sha256.Sum256() 函数,并将 input 作为参数。这将为我们的所有数据输入提供一个新的哈希表示。我们返回时使用 hash[:],[:] 语法将在返回时将 hash 切成适当的长度。
这实际上是我们开始链接区块链所需的全部内容。当然,我们希望在程序中看到某种输出,因此可以添加一些辅助方法,以便在打印时使用:
func printTransactions(block *Block) {fmt.Println("\tTransactions:")for i, transaction := range block.transactions {fmt.Printf("\t\t%v: %q\n", i, transaction)}}func printBlockInformation(block *Block) { fmt.Printf("\ttime: %s\n", block.timestamp.String()) fmt.Printf("\tprevHash: %x\n", block.prevHash) fmt.Printf("\tHash: %x\n", block.Hash) printTransactions(block)}
现在剩下的就是创建新的交易、区块和哈希值。我们可以通过 main 方法来实现这一点。我们定义了一个字符串数组来记录区块链中的交易。另请注意,我们如何传递一个空字节数组给 NewBlock() 来生成第一个区块,称为 genesisBlock。
func main() {genesisTransactions := []string{"Izzy sent Will 50 bitcoin", "Will sent Izzy 30 bitcoin"}genesisBlock := NewBlock(genesisTransactions, []byte{})fmt.Println("--- First Block ---")printBlockInformation(genesisBlock)
block2Transactions := []string{"John sent Izzy 30 bitcoin"}block2 := NewBlock(block2Transactions, genesisBlock.Hash)fmt.Println("--- Second Block ---")printBlockInformation(block2)block3Transactions := []string{"Will sent Izzy 45 bitcoin", "Izzy sent Will 10 bitcoin"}block3 := NewBlock(block3Transactions, block2.Hash)fmt.Println("--- Third Block ---")printBlockInformation(block3)
}
为了创建新的区块,我们将前一个区块的哈希值传递给 NewBlock() 函数,以及对应的交易历史记录。如果你想在一个地方查看整个程序,代码如下:
package main
import ("crypto/sha256""fmt""time")
type Block struct {timestamp time.Timetransactions []stringprevHash []byteHash []byte}
func main() {genesisTransactions := []string{"Izzy sent Will 50 bitcoin", "Will sent Izzy 30 bitcoin"}genesisBlock := NewBlock(genesisTransactions, []byte{})fmt.Println("--- First Block ---")printBlockInformation(genesisBlock)
block2Transactions := []string{"John sent Izzy 30 bitcoin"}block2 := NewBlock(block2Transactions, genesisBlock.Hash)fmt.Println("--- Second Block ---")printBlockInformation(block2)block3Transactions := []string{"Will sent Izzy 45 bitcoin", "Izzy sent Will 10 bitcoin"}block3 := NewBlock(block3Transactions, block2.Hash)fmt.Println("--- Third Block ---")printBlockInformation(block3)
}
func NewBlock(transactions []string, prevHash []byte) *Block {currentTime := time.Now()return &Block{timestamp: currentTime,transactions: transactions,prevHash: prevHash,Hash: NewHash(currentTime, transactions, prevHash),}}
func NewHash(time time.Time, transactions []string, prevHash []byte) []byte {input := append(prevHash, time.String()...)for transaction := range transactions {input = append(input, string(rune(transaction))...)}hash := sha256.Sum256(input)return hash[:]}
func printBlockInformation(block *Block) {fmt.Printf("\ttime: %s\n", block.timestamp.String())fmt.Printf("\tprevHash: %x\n", block.prevHash)fmt.Printf("\tHash: %x\n", block.Hash)printTransactions(block)}
func printTransactions(block *Block) {fmt.Println("\tTransactions:")for i, transaction := range block.transactions {fmt.Printf("\t\t%v: %q\n", i, transaction)}}
如果要运行此程序,将得到以下输出:
$ go run example.go--- First Block ---time: 2021-04-05 15:12:18.813294 -0600 MDT m=+0.000074939prevHash:Hash: 43ec51c50d2b9565f221155a29d8b72307247b08eaf6731ccaTransactions:0: "Izzy sent Will 50 bitcoin"1: "Will sent Izzy 30 bitcoin"--- Second Block ---time: 2021-04-05 15:12:18.813477 -0600 MDT m=+0.000257244prevHash: 43ec51c50d2b9565f221155a29d8b72307247b08eaf6731ccaHash: fcce5323a35cb67b45fe75866582db00fd32baeb92aac448c7Transactions:0: "John sent Izzy 30 bitcoin"--- Third Block ---time: 2021-04-05 15:12:18.813488 -0600 MDT m=+0.000269168prevHash: fcce5323a35cb67b45fe75866582db00fd32baeb92aac448c7Hash: fc1d3eee286970d85812b47c3a5bf016ae8c1de4f86b8ace972ffaTransactions:0: "Will sent Izzy 45 bitcoin"1: "Izzy sent Will 10 bitcoin"
这个过程可能看起来有些粗糙,但这正是创建自己的区块链的基础!
丁丁打折网©版权所有,未经许可严禁复制或镜像 ICP证: 湘ICP备20009233号-2
Powered by 丁丁打折网本站为非营利性网站,本站内容均来自网络转载或网友提供,如有侵权或夸大不实请及时联系我们删除!本站不承担任何争议和法律责任!
技术支持:丁丁网 dddazhe@hotmail.com & 2010-2020 All
rights reserved