区块链,工作证明(POW)代码+原理 golang版剖析

介绍

在之前的文章中,我们构建了一个非常简单的数据结构,这是块链数据库的本质。 而且我们可以用它们之间的链式关系向它添加区块:每个区块与前一个链接。 唉,然而在现实中添加一个区块添加到链是艰巨的工作。

工作证明

块链的一个关键思想是,必须通过工作证明才能将数据放入其中。这是一个艰巨的工作,使块链安全和一致。此外,这笔辛苦的工作也得到了奖励(这是人们获得采矿硬币的方式)。

这种机制与现实生活中的机制非常相似:人们必须工作获酬劳励并维持生命。在网络中,网络的一些参与者(矿工)努力维持网络,为其添加新的块,并为他们的工作获得奖励。作为其工作的结果,块以安全的方式并入到块链中,这保持了整个块链数据库的稳定性。值得注意的是,完成工作的人必须证明这一点。

这个整体“努力工作和证明工作价值”机制被称为工作证明。这很难因为它需要很多的计算能力:即使是高性能的计算机也不能很快的完成。此外,这项工作的难度不时增加,以保持新的块率每小时大约6个块。在比特币,这样的工作的目标是找到一个块的哈希,满足一些要求。这是散列,作为证明。因此,找到证据是实际工作。

最后要注意的事情。工作证明算法必须满足要求:做完工作不易完成,证明工作容易完成。证明通常交给非工作者,所以对他们来说,验证它不应该花太多的时间。

哈希算法加密

在本文中,我们将讨论哈希值。 如果你熟悉这个概念,你可以跳过这个部分。

哈希是获取指定数据的哈希值的过程。 哈希值是对其计算的数据的唯一表示。 哈希函数是一个获取任意大小的数据并产生固定大小的哈希的函数。 以下是哈希的一些主要功能:

  • 原始数据无法从哈希值恢复。 因此,散列不是加密。
  • 数据只能有一个哈希值,散列是唯一的。
  • 更改输入数据中的一个字节将导致完全不同的散列。

哈希函数被广泛用于检查数据的一致性。在区块链中,使用哈希来保证块的一致性。 哈希算法的输入数据包含前一个块的哈希值,从而使得已经生成的链难以修改之前产生的区块(或至少相当困难):必须重新计算其后的所有块的哈希值。

哈希现金 、 Hashcash

比特币使用Hashcash,哈希现金的发明最初是为防止电子邮件垃圾邮件而开发的。它可以分为以下几个步骤:

  1. 获取公开的数据(在电子邮件的情况下,它是接收者的电子邮件地址;在比特币的情况下,它是块标题)。
  2. 添加一个计数器。计数器从0开始。
  3. 获取数据+计数器组合的散列。
  4. 检查哈希值是否符合要求。
    1. 如果满足要求,结束过程。
    2. 如果不满足要求,增加计数器并重复步骤3和4。

因此,这是一个强力算法:您更改计数器,计算一个新的哈希,检查它,增加计数器,计算哈希等。这就是为什么它在计算上是昂贵的。

现在让我们看看一个哈希必须满足的要求。在原来的Hashcash实现中“哈希的前20位必须是零”。然而在比特币中,哈希要求是不时进行调整的,因为尽管计算能力随着时间的推移而增加,越来越多的矿工加入网络,因此设计必须每10分钟生成一个块

为了演示这个算法,我从前面的例子中获取了数据(“我喜欢甜甜圈”),并发现一个以0个零字节开头的哈希:

编写代码

程序员小提醒:go和python都是不用加分号的语言

好的,我们完成了理论,让我们编写代码! 首先,我们来定义挖掘的难度:

const targetBits = 24

In Bitcoin, “target bits” is the block header storing the difficulty at which the block was mined. We won’t implement a target adjusting algorithm, for now, so we can just define the difficulty as a global constant.

24 is an arbitrary number, our goal is to have a target that takes less than 256 bits in memory. And we want the difference to be significant enough, but not too big, because the bigger the difference the more difficult it’s to find a proper hash.

在比特币中,“目标位(target bit)”是存储块被挖掘的困难的块头。 我们现在不会实现目标调整算法,所以我们可以将难度定义为全局常数

24是一个任意数字,我们的目标是在内存中占用少于256位的目标。 而且我们希望差异足够大,但不要太大,因为差异越大,找到合适的哈希越难。

type ProofOfWork struct {
    block  *Block 
    target *big.Int //定义目标位
}

func NewProofOfWork(b *Block) *ProofOfWork {
    target := big.NewInt(1)
    target.Lsh(target, uint(256-targetBits))  //左移256个 target bits位

    pow := &ProofOfWork{b, target}

    return pow
}

这里创建保存指向块的指针的工作证明结构和指向目标的指针。 “目标”是上一段所述要求的另一个名称。 我们使用一个大整数,因为我们将哈希与目标进行比较:我们将哈希转换为一个大整数,并检查它是否小于目标。

big: https://golang.org/pkg/math/big/

在新的工作证明的函数中,我们初始化一个值为1的big.Int,并将其左移256个 - targetBits位。 256是SHA-256哈希的长度,以比特为单位,它是我们要使用的SHA-256散列算法。 目标的十六进制表示为:

0x10000000000000000000000000000000000000000000000000000000000

它在内存中占用29个字节。 这是与以前的例子中的哈希的比较:

0fac49161af82ed938add1d8725835cc123a1a87b1b196488360e58d4bfb51e3
0000010000000000000000000000000000000000000000000000000000000000
0000008b0f41ec78bab747864db66bcb9fb89920ee75f43fdaaeb5544f7f76ca

第一个哈希(以“我喜欢甜甜圈”计算)大于目标,因此它不是有效的工作证明。 第二个哈希(以“我喜欢甜甜圈ca07ca”计算)小于目标,因此这是一个有效的证明。

您可以将目标视为范围的上限:如果数字(哈希)低于边界,则它是有效的,反之亦然。 降低边界将导致有效数量减少,因此找到有效数量所需的工作更加困难。

现在,对数据进行哈希处理。

func (pow *ProofOfWork) prepareData(nonce int) []byte {
    data := bytes.Join(
        [][]byte{
            pow.block.PrevBlockHash,
            pow.block.Data,
            IntToHex(pow.block.Timestamp),
            IntToHex(int64(targetBits)),
            IntToHex(int64(nonce)),
        },
        []byte{},
    )

    return data
}

我们只是将块区域与目标和随机数合并。 nonce这里是从上面的Hashcash描述的计数器,这是加密术语。

好的,所有的准备工作都完成了,我们来实现PoW算法的核心:

func (pow *ProofOfWork) Run() (int, []byte) {
    var hashInt big.Int
    var hash [32]byte
    nonce := 0

    fmt.Printf("Mining the block containing \"%s\"\n", pow.block.Data)
    for nonce < maxNonce {
        data := pow.prepareData(nonce) // 准备数据
        hash = sha256.Sum256(data) // SHA-256加密
        fmt.Printf("\r%x", hash)
        hashInt.SetBytes(hash[:])  // 讲hash转换成Big Integer

        if hashInt.Cmp(pow.target) == -1 {
            break
        } else {
            nonce++
        }
    }
    fmt.Print("\n\n")

    return nonce, hash[:]
}

首先,我们初始化变量:hashInt是哈希的整数表示; nonce是柜台。 接下来,我们运行一个“无限”循环:它受限于maxNonce,它等于math.MaxInt64; 这样做是为了避免可能的随机数溢出。 虽然我们的PoW实施的难度太低,以至于防止溢出,但最好是进行此检查,以防万一。

在循环中我们:

  • 准备数据
  • 用SHA-256进行哈希。
  • 将散列转换为大整数。
  • 将整数与目标进行比较。

现在我们可以删除BlockSetHash方法并修改NewBlock函数:

func NewBlock(data string, prevBlockHash []byte) *Block {
    block := &Block{time.Now().Unix(), []byte(data), prevBlockHash, []byte{}, 0}
    pow := NewProofOfWork(block)
    nonce, hash := pow.Run()

    block.Hash = hash[:]
    block.Nonce = nonce

    return block
}

Here you can see that nonce is saved as a Block property. This is necessary because nonce is required to verify a proof. The Blockstructure now looks so:

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

验证工作证明

func (pow *ProofOfWork) Validate() bool {
    var hashInt big.Int

    data := pow.prepareData(pow.block.Nonce)
    hash := sha256.Sum256(data)
    hashInt.SetBytes(hash[:])

    isValid := hashInt.Cmp(pow.target) == -1

    return isValid
}

主函数代代码再次检查

func main() {
    ...

    for _, block := range bc.blocks {
        ...
        pow := NewProofOfWork(block)
        fmt.Printf("PoW: %s\n", strconv.FormatBool(pow.Validate()))
        fmt.Println()
    }
}

结论

我们的块链是一个更接近其实际架构的一步:添加块现在需要努力工作,因此挖掘是可能的。 但是它仍然缺乏一些关键的特征:块链数据库不是持久的,没有钱包,地址,交易,没有共识机制。 所有这些我们将在以后的文章中实现的,现在,开采开采!

原文地址:http://blog.51cto.com/iceman123/2089546

时间: 2024-11-05 15:56:36

区块链,工作证明(POW)代码+原理 golang版剖析的相关文章

区块链项目实战视频课程(Java版)

区块链项目实战视频课程(Java版)网盘地址:https://pan.baidu.com/s/1EiONxCp7JBw6GJKhjK_zHQ 提取码:tzr1备用地址(腾讯微云):https://share.weiyun.com/5al0zSz 密码:3rgeye 本课程是基于java语言的区块链实战教程.目的是让更多的java编程者了解区块链,掌握区块链开发. 区块链是分布式数据存储.点对点传输.共识机制.加密算法等计算机技术的新型应用模式. 区块链(Blockchain)是比特币的一个重要概

2.3 区块链工作过程

区块链的工作过程分交易产生.交易广播.节点计算.获取记账权.记录权广播.接收区块.验证区块和完成记账七个过程. 1) 交易产生:用户向区块链发了一笔交易信息,将产生交易:2) 交易广播:当一笔新交易产生时,区块链网络会广播出去,网络中的其它节点都会收到该交易信息:3) 节点计算:收到交易信息的节点把新交易放到区块中,通过共识算法决定谁有记账权,共识算法有POW.POS.DPOS.PBFT:4) 获取记账权:根据不同的共识算法,其中一个节点将获取记账权,如POW,使用工作量证明,谁最快计算出,将获

区块链DAPP 开发入门 代码实现 场景应用

第一章 智能合约概述 智能合约是运行在区块链公链上的一种代码. 可以将区块链公链理解成操作系统,智能合约虚拟机则是编程语言编译之后的代码运行环境. 1. 区块链 1.1 区块链基础知识 区块链通常被理解为超级账本,账户与账户直接可以通过交易来完成转账,但这种转账区别于传统银行. (1)这是一个完全去中心化的金融系统.因为整个系统中没有这样的中心化部门来管理账户信息.使用者只需要根据一种[非对称加密算法]来生成一个密钥对,其公钥作为账户地址,也就是常说的[区块链钱包地址],这个地址可以在网络中传播

兄弟连区块链入门教程分享区块链POW证明代码实现demo

这里强调一下区块链的协议分层?应用层?合约层?激励机制?共识层?网络层?数据层上 一篇主要实现了区块链的 数据层,数据层主要使用的技术就是对数据的校验,求hash.这里介绍工作量证明POW, POW是属于共识机制的内容.PoW机制中根据矿工的工作量来执行货币的分配和记账权的确定.算力竞争的胜者将获得相应区块记账权和比特币奖励.因此,矿机芯片的算力越高,挖矿的时间更长,就可以获得更多的数字货币.优点:算法简单,容易实现:节点间无需交换额外的信息即可达成共识:破坏系统需要投入极大的成本.缺点:浪费能

区块链中的RESTFUL链码调用API原理详解

本文适合于熟悉开源区块链技术Hyperledger Fabric,以及希望更高效地使用华为云区块链服务的读者.当然,也欢迎任何对区块链技术有兴趣的读者阅读本文,相信读者们都能从中受益. 2018年2月1日 华为云发布企业级区块链开放平台区块链服务BCS(Blockchain Service),是基于开源区块链技术和华为在分布式并行计算.数据管理.安全加密等核心技术领域多年积累基础上推出的企业级区块链云服务产品,旨在帮助各行业.企业在华为云上快速.高效的搭建企业级区块链行业方案和应用. 如前所述,

golang区块链开发的视频教程推荐

目前网上关于golang区块链开发的资源很少,以太坊智能合约相关的课程倒是很多,可能是由于前者的难度比后者难度大,课程开发需要投入更多精力.搜了一圈之后没结果,我就直接去之前没覆盖的视频网站找资源,包括慕课网.腾讯课堂.网易云课堂. 结果还真找到了,不过这个golang区块链开发的课程名字太文艺了点,不够直白,不容易用搜索引擎搜索到.讲师的讲解思路清晰,简练易懂,实在是学习go语言开发区块链居家旅行之良课(课程免费). 下面是链接和截图. <私有区块链,我们一起GO> https://www.

从概念到底层技术,一文看懂区块链架构设计

转自:http://www.8btc.com/ebook-blockchain https://blog.csdn.net/lucky_greenegg/article/details/52821924 前言 区块链作为一种架构设计的实现,与基础语言或平台等差别较大.区块链是加密货币背后的技术,是当下与VR虚拟现实等比肩的热门技术之一,本身不是新技术,类似Ajax,可以说它是一种技术架构,所以我们从架构设计的角度谈谈区块链的技术实现. 无论你擅长什么编程语言,都能够参考这种设计去实现一款区块链产

什么是区块链?

一.什么是区块链? 说到区块链,就不得不说比特币. 2008年底,比特币之父中本聪发表了一个关于他研究的电子现金系统的九页白皮书,2009年初,中本聪在位于芬兰赫尔辛基的一个小型服务器上挖出了比特币的第一个区块——创世区块,并将当天泰晤士报头版一则关于救助银行的新闻标题写入创世区块,这也代表着比特币诞生了. 区块链是比特币的底层技术,它可以理解为一种公共记账的机制(技术方案),它并不是一款具体的产品.其基本思想是:通过建立一组互联网上的公共账本,由网络中所有的用户共同在账本上记账与核账,来保证信

区块链(Blockchain)

一 .什么是区块链? 区块链(Blockchain)是由节点参与的分布式数据库系统[1],它的特点是不可更改,不可伪造,也可以将其理解为账簿系统(ledger).它是比特币的一个重要概念,完整比特币区块链的副本,记录了其代币(token)的每一笔交易.通过这些信息,我们可以找到每一个地址,在历史上任何一点所拥有的价值. 区块链是由一串使用密码学方法产生的数据块组成的,每一个区块都包含了上一个区块的哈希值(hash),从创始区块(genesis block)开始连接到当前区块,形成块链.每一个区块