美文网首页区块链开发
比特币原理第一讲-区块结构

比特币原理第一讲-区块结构

作者: 夜千寻墨 | 来源:发表于2018-08-03 19:46 被阅读69次

## 引言

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

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

## 区块

首先从 “区块” 谈起。在区块链中,真正存储有效信息的是区块(block)。而在比特币中,真正有价值的信息就是交易(transaction)。实际上,交易信息是所有加密货币的价值所在。除此以外,区块还包含了一些技术实现的相关信息,比如版本,当前时间戳和前一个区块的哈希。

不过,我们要实现的是一个简化版的区块链,而不是一个像比特币技术规范所描述那样成熟完备的区块链。所以在我们目前的实现中,区块仅包含了部分关键信息,它的数据结构如下:


type Block struct {

Timestamp  int64

Data []byte

PrevBlockHash []byte

Hash []byte

}

字段 | 解释

:----: | :----

Timestamp | 当前时间戳,也就是区块创建的时间

PrevBlockHash | 前一个块的哈希,即父哈希

Hash | 当前块的哈希

Data | 区块存储的实际有效信息,也就是交易

我们这里的 TimestampPrevBlockHash, Hash,在比特币技术规范中属于区块头(block header),区块头是一个单独的数据结构。

完整的 比特币的区块头(block header)结构 如下:

Field | Purpose | Updated when... | Size (Bytes)

:---- | :---- | :---- | :----

Version | Block version number | You upgrade the software and it specifies a new version | 4

hashPrevBlock | 256-bit hash of the previous block header | A new block comes in | 32

hashMerkleRoot | 256-bit hash based on all of the transactions in the block | A transaction is accepted | 32

Time | Current timestamp as seconds since 1970-01-01T00:00 UTC | Every few seconds | 4

Bits | Current target in compact format | The difficulty is adjusted | 4

Nonce | 32-bit number (starts at 0) | A hash is tried (increments) | 4

下面是比特币的 golang 实现 btcd 的 BlockHeader 定义:


// BlockHeader defines information about a block and is used in the bitcoin

// block (MsgBlock) and headers (MsgHeaders) messages.

type BlockHeader struct {

  // Version of the block. This is not the same as the protocol version.

 Version int32

  // Hash of the previous block in the block chain.

 PrevBlock chainhash.Hash

  // Merkle tree reference to hash of all transactions for the block.

 MerkleRoot chainhash.Hash

  // Time the block was created. This is, unfortunately, encoded as a

  // uint32 on the wire and therefore is limited to 2106.

 Timestamp time.Time

  // Difficulty target for the block.

 Bits uint32

  // Nonce used to generate the block.

 Nonce uint32

}

而我们的 Data, 在比特币中对应的是交易,是另一个单独的数据结构。为了简便起见,目前将这两个数据结构放在了一起。在真正的比特币中,区块 的数据结构如下:

Field | Description | Size

:---- | :---- | :----

Magic no | value always 0xD9B4BEF9 | 4 bytes

Blocksize | number of bytes following up to end of block | 4 bytes

Blockheader | consists of 6 items | 80 bytes

Transaction counter | positive integer VI = VarInt | 1 - 9 bytes

transactions | the (non empty) list of transactions | <Transaction counter>-many transactions

在我们的简化版区块中,还有一个 Hash 字段,那么,要如何计算哈希呢?哈希计算,是区块链一个非常重要的部分。正是由于它,才保证了区块链的安全。计算一个哈希,是在计算上非常困难的一个操作。即使在高速电脑上,也要耗费很多时间 (这就是为什么人们会购买 GPU,FPGA,ASIC 来挖比特币) 。这是一个架构上有意为之的设计,它故意使得加入新的区块十分困难,继而保证区块一旦被加入以后,就很难再进行修改。在接下来的内容中,我们将会讨论和实现这个机制。

目前,我们仅取了 Block 结构的部分字段(Timestamp, DataPrevBlockHash),并将它们相互拼接起来,然后在拼接后的结果上计算一个 SHA-256,然后就得到了哈希.


Hash = SHA256(PrevBlockHash + Timestamp + Data)

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 的惯例,我们会实现一个用于简化创建区块的函数 NewBlock


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 存储 ****hash -> block**** 对(Golang 中, map 是无序的)。 但是在基本的原型阶段,我们只用到了 array,因为现在还不需要通过哈希来获取块。


type Blockchain struct {

blocks []*Block

}

这就是我们的第一个区块链!是不是出乎意料地简单? 就是一个 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: aff955a50dc6cd2abfe81b8849eab15f99ed1dc333d38487024223b5fe0f1168

Prev. hash: aff955a50dc6cd2abfe81b8849eab15f99ed1dc333d38487024223b5fe0f1168

Data: Send 1 BTC to Ivan

Hash: d75ce22a840abb9b4e8fc3b60767c4ba3f46a0432d3ea15b71aef9fde6a314e1

Prev. hash: d75ce22a840abb9b4e8fc3b60767c4ba3f46a0432d3ea15b71aef9fde6a314e1

Data: Send 2 more BTC to Ivan

Hash: 561237522bb7fcfbccbc6fe0e98bbbde7427ffe01c6fb223f7562288ca2295d1

## 总结

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

进入 src 目录查看代码,执行 make 即可运行:


$ cd src

$ make

==> Go build

==> Running

Prev. hash:

Data: Genesis Block

Hash: 4693b71eee96760de4b0f051083376dcbed2f0711a44294ee5fd42fbeacc9579

Prev. hash: 4693b71eee96760de4b0f051083376dcbed2f0711a44294ee5fd42fbeacc9579

Data: Send 1 BTC to Ivan

Hash: 839380a2d0af1dc4686f16ade5423fecdc5f287db9322d9e18adcb4071e7c8ff

Prev. hash: 839380a2d0af1dc4686f16ade5423fecdc5f287db9322d9e18adcb4071e7c8ff

Data: Send 2 more BTC to Ivan

Hash: b38052a029bd2b1b9d4bb478af45b4c88605e99bc64e49031ba06d21ad4b0b38

参考:

[1] Block hashing algorithm

[2] Building Blockchain in Go. Part 1: Basic Prototype


bitcoin wiki 的区块结构:

Field | Description | Size

:----: | :----: | :----:

Magic no | value always 0xD9B4BEF9 | 4 bytes

Blocksize | number of bytes following up to end of block | 4 bytes

Blockheader | consists of 6 items | 80 bytes

Transaction | counter positive integer VI = VarInt | 1 - 9 bytes

transactions | the (non empty) list of transactions | <Transaction counter>-many transactions


配套项目地址:https://github.com/suifengqjn/PublicChain

更多区块链资料,关注公众号block001


qrcode_for_gh_6a9a93ef3f38_344.jpg

相关文章

  • 2018-07-15区块链技术

    一: 区块链的前世今生, 前景,比特币,比特币原理 Cypherpunk(密码朋克) 比特币-----区块链 账户...

  • 区块链和比特币基础技术原理

    前言:区块链和比特币的基本概念和技术原理:存储结构、区块头结构、Merkle 树,解锁脚本、挖矿过程、P2P 网络...

  • 一些基本比特币概念

    BitCoin区块头 比特币区块结构: 比特币的区块头结构: 1)版本号Version:大小4字节,每一个区块的版...

  • 201951-数字账本技术

    想知道比特币(和其他加密货币)的原理吗? 比特币和区块链啥原理?矿机挖矿咋回事?李永乐老师讲比特币(1) 比特币交...

  • 区块链共识技术一:pow共识机制

    一.前言 在了解pow共识机制前,我们先了解下比特币区块的结构,下图是比特币区块的结构图: 从图上可知,比特币的结...

  • 区块链1.0之比特币

    一、区块链与比特币之间的关系 比特币是区块链技术的第一个应用程序。首先有了比特币,然后人们研究比特币的技术原理,提...

  • 比特币结构

    比特币结构 区块结构 ==注意:比特币的区块大小目前被严格限制在1MB以内。4字节的区块大小字段不包含在此内。==...

  • 区块链技术架构分析(2)-区块数据和链式结构

    区块数据主要是保存交易数据,不同的系统采用的结构不同,下面以比特币的区块结构为例做介绍。 比特币的交易记录会保存在...

  • 比特币与数字货币(5)

    每天5分钟,学点区块链 比特币的交易 比特币交易是比特币系统中最重要的部分。根据比特币系统的设计原理,系统中任何其...

  • 小白也能懂的比特币及区块链原理

    小白也能懂的比特币及区块链原理 文中尽量以大白话讲解比特币及区块链的基本原理,一步一步的画出区块链的鸟瞰图。!!!...

网友评论

    本文标题:比特币原理第一讲-区块结构

    本文链接:https://www.haomeiwen.com/subject/kwcmuftx.html