用 golang 实现区块链系列一 | 基本原型

介绍

区块链是二十一世纪以来最具革命性的科技之一,它仍在发展中,并且其潜力仍未被充分认知。本质上,区块链只是一个分布式的记录数据库,但使它和其他数据库不一样的是,他并不是一个私有数据库,而是公开的。每个使用它的人都有完整或者部分副本。并且一条新的记录只能在被数据库的其他管理员同意的情况下才能被加入。区块链也使得加密货币和智能合约成为可能。

本系列文章将会构建一个基于简单区块链实现的简单加密货币。

Block

我们从 “区块链” 的 “区块” 开始讲起。在区块链中, block 存储着有价值的信息。例如,比特币区块存储着交易信息,这是加密货币的本质。除此之外,区块还包含着一些技术信息,像是版本号,当前时间戳,还有上一个区块的 hash 值。 在本文中,我们不会去着手实现一个区块链中描述的区块,也不会是比特币标准的区块,而是一个它的简化版本。它只会包含着最重要的信息。长得像是这样:

type Block struct {
    Timestamp     int64
    Data          []byte
    PrevBlockHash []byte
    Hash          []byte

Timestamp 是当前时间戳(区块被创建时), Data 是区块中所包含的有实际价值的信息, PrevBlockHash 是存储着上个区块的 hash,而 Hash 是当前区块的 hash 。在比特币标准中, TimestampPrevBlockHash 和 Hash 是区块头,它是一个单独的数据结构,而且 transactions(我们的例子中是Data)也是一个单独的数据结构。我们在这边简化处理,合在一起了。

那么怎么取算 hash 值呢? hash 的计算方式在区块链中是一个非常重要的特性,这个特性使得区块链安全。计算 hash 值是一个难以计算的操作。在很快的电脑上也要花费大量的时间(这也是为什么人们买强大的 GPU 去挖比特币)。添加新的区块很困难是一个很有意思的架构设计,它阻止了添加之后的修改。我们将在以后的文章中去讨论和实现这个机制。

现在,我们先弄几个区块字段,把它们放在一起,再算个 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[:]
}

下一步,遵循 Go 语言的惯例,我们实现一个方法来简化区块的创建:

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

好啦,这就是区块啦!

区块链

现在,我们来实现一个简单的区块链。区块链的本质是保存着特定的数据结构的数据库。它是一个有序的,尾部相连的链表。这就意味着区块是以插入的顺序被存储的,每个区块连接着前一个区块。这种结构就可以很快的获取链上的最后一个区块,而且可以很高效地通过 hash 获取区块。

在 Go 语言中,这种结构可以通过使用 array 和 map 来实现:数组可以保存着有序 hash (Go 语言中,数组是有序的), map 结构可以保存 hash -> block 的匹配信息。但在我们的区块链原型中,我们只会使用一个数组,因为我们暂时并不需要通过 hash 获取区块信息。

type Blockchain struct {
    blocks []*Block
}

这就是我们的第一个区块链啦,难以想象竟然会这么简单

你可能感兴趣的:(区块链)