主页 > 怎么看出来imtoken真伪 > 区块链共识算法系列-PoW

区块链共识算法系列-PoW

怎么看出来imtoken真伪 2023-06-12 05:43:54

区块链共识算法系列-PoW

本专栏将介绍区块链共识算法、以太坊智能合约、Hyperledger 智能合约和 EOS 智能合约。 它还将详细介绍几个实际项目。 如果可能,我们也可以一起阅读以太坊的源代码。 感兴趣的话,一起来学习区块链技术吧~

一、简介

说到区块链,首先要了解什么是P2P。 这个P2P不是金融里的名词,而是点对点网络。 在中本聪的白皮书中,指出微信支付、支付宝等点对点支付系统需要通过第三方是没有意义的。

而我们的P2P就是这样一个不需要经过第三方的概念。 它出现的一个重要原因是避开第三方和中心。

在P2P对等网络中,所有的节点都具有相同的功能,没有一个节点是特殊的,它们相互提供服务。

因为没有第三方,没有中心,保证了数据的透明、自由和平等。

我们经常听到的比特币使用的是 PoW 共识算法。 PoW是Proof-of-Work的缩写,即工作量证明。 就是计算出一个值,这个值和数据结合起来满足要求后,会立即广播全网打包区块。 全网节点收到广播后,将验证广播的正确性。 如果节点作弊,将无法通过验证。 打包后的区块将被丢弃,不能记录在账本中。 挖矿成本这么高。 如果作弊导致区块被丢弃,比特币将无法使用,不是吗? 还是得赔钱。 因此,矿工愿意遵守比特币系统的共识协议。

2. 生成创世块

我们首先定义块的结构:

type Block struct {
    //上一个区块的哈希值
    PreHash string
    //当前区块的哈希值
    HashCode string
    //时间戳
    TimeStamp string
    //难度系数
    Diff int
    //交易信息
    Data string
    //区块高度
    Index int
    //随机值
    Nonce int
}

根据比特币,我们将这个区块的信息设置为以下几点:前一个区块的哈希值,当前区块的哈希值,时间戳,难度系数,交易信息,区块高度,随机值。

然后我们创建一个创世块。

//创世区块
func GneFirBlock(data string) Block {
    //创建第一个区块
    var firstblock Block
    firstblock.PreHash = ""
    firstblock.TimeStamp = time.Now().String()
    firstblock.Diff = 3
    firstblock.Index = 1
    firstblock.Nonce = 0
    //通过sha256计算哈希值
    firstblock.HashCode =GneHashValue(firstblock)
    return firstblock
}

因为是第一个块,之前的块是空的,我们使用当前时间作为时间戳,我们暂时把难度设置为3,因为是第一个块,所以块高为1,随机值可以be 随便吧,我们用0吧。然后我们要计算当前块的hash值以太坊基于pow算法叫,需要用sha256来计算。

3.生成哈希值

func GneHashValue(block Block) string {
   var hashdata = strconv.Itoa(block.Index) + strconv.Itoa(block.Nonce) + strconv.Itoa(block.Diff) +
      block.TimeStamp + block.PreHash
​
   var sha = sha256.New()
   sha.Write([]byte(hashdata))
   hashed := sha.Sum(nil)
   return hex.EncodeToString(hashed)
}

我们的区块链是一个模拟的比特币区块,所以我们需要把所有的数据拼接在一起,然后计算哈希值。 这里我们使用sha256加密算法。 这里首先使用sha256.New,这个方法会返回一个hash.Hash。 这个 Hash 实现了 encoding.BinaryMarshaler 和 encoding.BinaryUnmarshaler,它们可以编组和解组散列的内部状态。 然后使用Write向底层数据流写入数据,它会返回写入的字节数或者错误以太坊基于pow算法叫,我们这里不需要它的返回值。 Sum方法的参数是nil,意思是我们要将当前的hash值追加到nil上,返回一个生成的slice。 该方法不会改变哈希值的底层状态。 EncodeToString 返回散列的十六进制编码。

4.看看创世块

让我们来看看创世块。

func main() {
    var firstBlock = GneFirBlock("Regan Yue")
    fmt.Println(firstBlock)
    fmt.Println(firstBlock.Data)
}

{ e42d311dd9ba42d8f1907ba60a7c1112c1720ccbdad938aaad91b4990089ece8 2021-11-06 21:34:32.3711993 +0800 CST m=+0.023002101 3 Regan Yue 1 0}
Regan Yue
​

我们可以看到创世块的数据已经保存好了,接下来我们写入生成一个新的块。

5. 生成新区块

func GneNewBlock(data string, oldBlock Block) Block {
    var newBlock Block
    newBlock.TimeStamp = time.Now().String()
    newBlock.Diff = 3
    newBlock.Index = 2
    newBlock.Data = data
    newBlock.PreHash = oldBlock.HashCode
    newBlock.Nonce = 0
    newBlock.HashCode = pow(newBlock.Diff, &newBlock)
​
    return newBlock
}
​

接下来我们需要生成一个新的区块,这里的区块高度应该是2,新区块的PreHash应该是前一个区块的哈希值,然后我们计算这个区块的哈希值,这里我们模仿比特币,Count前导 0 的数量。

func pow(diff int, block *Block) string {
    for {
        hashValue := GneHashValue(*block)
        fmt.Println(hashValue)
        if strings.HasPrefix(hashValue, strings.Repeat("0", diff)) {
            //成功
            fmt.Println("success")
            return hashValue
        } else {
            block.Nonce++
        }
​
    }
}

如果生成的哈希值前导0个数等于难度值,则返回哈希值,否则Nonce值发生变化。

image-20211106215025924