100行代码实现一个区块链!
  Ld1ydcUEqbSi 2023年11月02日 55 0


废话不多说,开始跟我用golang搭建个迷你区块链:

首先,引入包:

package main

import (
"bytes"
"crypto/sha256"
"encoding/binary"
"fmt"
"math"
"math/big"
"time"
)

设置一些常量,工作量证明难度系数dif,搜索上界INT64_MAX:

const (
dif = 20
INT64_MAX = math.MaxInt64
)

然后我们设计一个简单的区块体和区块链体,每个区块呢有前个区块哈希,本区块哈希,数据,链长,时间戳和随机数:

type Block struct {
PrevHash []byte
Hash []byte
Data string
Height int64
Timestamp int64
Nonce int
}

type BlockChain struct {
Blocks []Block
}

实现一段工作量证明函数,这个工作量证明呢以后聊共识算法会细讲的,也就是这里实现了不可篡改(reigns最近被raft血虐的,TAT):

func IntToHex(num int64) []byte {
buff := new(bytes.Buffer)
err := binary.Write(buff, binary.BigEndian, num)
if err != nil {
panic(err)
}
return buff.Bytes()
}

func ProofOfWork(b Block, dif int) ([]byte, int) {
target := big.NewInt(1)
target.Lsh(target, uint(256-dif))
nonce := 0
for ; nonce < INT64_MAX; nonce++ {
check := bytes.Join(
[][]byte{b.PrevHash,
[]byte(b.Data),
IntToHex(b.Height),
IntToHex(b.Timestamp),
IntToHex(int64(nonce))},
[]byte{})
hash := sha256.Sum256(check)
var hashInt big.Int
hashInt.SetBytes(hash[:])
if hashInt.Cmp(target) == -1 {
return hash[:], nonce
}
}
return []byte(""), nonce
}

然后呢这段函数实现生成创世块,也就是链头啦:

func GenesisBlock(data string) BlockChain {
var bc BlockChain
bc.Blocks = make([]Block, 1)
bc.Blocks[0] = Block{
PrevHash: []byte(""),
Data: data,
Height: 1,
Timestamp: time.Now().Unix(),
}
bc.Blocks[0].Hash, bc.Blocks[0].Nonce = ProofOfWork(bc.Blocks[0], dif)
return bc
}

这段呢是生成新的区块,也就是俗称的挖矿,当然了真实的挖矿可比这个复杂多了:

func GenerateBlock(bc *BlockChain, data string) {
prevBlock := bc.Blocks[len(bc.Blocks)-1]
block := Block{
PrevHash: prevBlock.Hash,
Data: data,
Height: prevBlock.Height + 1,
Timestamp: time.Now().Unix(),
}
block.Hash, block.Nonce = ProofOfWork(block, dif)
bc.Blocks = append(bc.Blocks, block)
}

再写个打印区块函数:

func Print(bc BlockChain) {
for _, i := range bc.Blocks {
fmt.Printf("PrevHash: %x\n", i.PrevHash)
fmt.Printf("Hash: %x\n", i.Hash)
fmt.Println("Block's Data: ", i.Data)
fmt.Println("Current Height: ", i.Height)
fmt.Println("Timestamp: ", i.Timestamp)
fmt.Println("Nonce: ", i.Nonce)
}
}

好啦,各个函数都写完了,不多不少99行

100行代码实现一个区块链!_区块链

100行代码实现一个区块链!_区块链_02

100行代码实现一个区块链!_unix_03

写个main函数看看吧~

来,reigns开始挖矿,先挖个创世块,给alice转账2刀,然后再给alice转3刀,看看这几次次操作怎么记录在区块链中吧:

func main() {
blockchain := GenesisBlock("i am reigns")
GenerateBlock(&blockchain, "send 2$ to alice")
GenerateBlock(&blockchain, "send 3$ to alice")
Print(blockchain)
}

输出结果:

100行代码实现一个区块链!_区块链_04

由于创世块没有前面的区块,所以他的PrevHash就是空,记录给alice转账2刀的这个区块,它的PrevHash就是创世块了,后面的以此类推,得到一个不可篡改链。

也可以发现啊,区块生成并不是一下子执行完成的,三个区块用了接近7秒钟,这就是工作量证明算法起的作用了,防止恶意节点不劳而获,每个新的区块都需要付出一定计算力才能得到,当然这里没有设置很高的困难度(dif = 20),也没有根据时间动态增加难度,比特币网络中一般设置的挖矿难度都需要10分钟左右的,想想2009年的10分钟和2019的10分钟,难度提了多少~

怎么样,是不是了解了区块链的基本结构呢,当然了成熟的链使用的数据存储结构肯定不会是一个字符串,比如比特币用的是默克尔树,交易也不会这么随便就成功,都需要依靠一个叫做智能合约的东东进行约束的。

好啦,今天就讲这么多。

如果对区块链感兴趣,可以关注下面这个公众号哦,推送的全是区块链干货~

100行代码实现一个区块链!_区块链_05

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
Ld1ydcUEqbSi