一个基于DPoS共识算法的区块链案例解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 前面我们介绍了PoW以及PoS的案例,我们会发现它们都有一些缺点,比如PoW耗费能源比较多,而PoS是持有的币越多,成功挖矿的几率越大,这会造成贫富差距越来越大,并且人们都不太愿意消耗自己的币。而我们的DPoS,全名为Delegated Proof of Stake,也就是股份授权证明就解决了这些不足。DPoS就是大家投票选出一定数量的节点来挖矿,用户拥有的票的数量和他持有的币数量有关。这就和股份制公司很像了,大家投票选出董事会成员。这些被选出来的拥有挖矿权的节点的挖矿权力是一模一样的。如果某个节点挖到了矿,那么他就要将获得的币分一些给投票给他的人。

一个基于DPoS共识算法的区块链案例解析

一、前言

前面我们介绍了PoW以及PoS的案例,我们会发现它们都有一些缺点,比如PoW耗费能源比较多,而PoS是持有的币越多,成功挖矿的几率越大,这会造成贫富差距越来越大,并且人们都不太愿意消耗自己的币。

而我们的DPoS,全名为Delegated Proof of Stake,也就是股份授权证明就解决了这些不足。

DPoS就是大家投票选出一定数量的节点来挖矿,用户拥有的票的数量和他持有的币数量有关。这就和股份制公司很像了,大家投票选出董事会成员。

这些被选出来的拥有挖矿权的节点的挖矿权力是一模一样的。

如果某个节点挖到了矿,那么他就要将获得的币分一些给投票给他的人。

一、定义区块、区块链

type Node struct {
    Name string
    Votes int
}

type Block struct {
    Index     int
    Timestamp string
    Prehash   string
    Hash      string
    Data      []byte
    delegate *Node
}

相信关注这个专栏前几篇文章的老朋友应该都知道区块内的信息代表什么,这里简单说一下Index是区块高度,TimeStamp是时间戳,Data是块保存的一些数据,Hash是当前区块的哈希值,PrevHash是先前区块的哈希值,delegate是区块的挖掘者。

而这里的节点信息就是之前没有介绍的了,Name是节点名称,Votes是被投的票数。

二、生成创世区块

func firstBlock() Block {
    gene := Block{0, time.Now().String(),
        "", "", []byte("first block"), nil}
    gene.Hash = string(blockHash(gene))
    return gene
}

创世区块就是第一个区块,这里需要我们手写一个。哈希值的计算下面会讲述。

三、计算哈希值

func blockHash(block Block) []byte {
    hash := strconv.Itoa(block.Index) + block.Timestamp +
        block.Prehash + hex.EncodeToString(block.Data)
    h := sha256.New()
    h.Write([]byte(hash))
    hashed := h.Sum(nil)
    return hashed
}

这里是将所有数据拼接在一起,然后计算拼接后的数据的哈希值。

四、生成新的模块

func (node *Node) GenerateNewBlock(lastBlock Block, data []byte) Block {
    var newBlock = Block{lastBlock.Index + 1,
        time.Now().String(), lastBlock.Hash, "", data, nil}
    newBlock.Hash = hex.EncodeToString(blockHash(newBlock))
    newBlock.delegate = node
    return newBlock
}

还是讲过的逻辑,将这些数据放入区块中,便生成了一个新的区块。

五、创建节点

var NodeAddr = make([]Node, 10)


func CreateNode() {
    for i := 0; i < 10; i++ {
        name := fmt.Sprintf("节点 %d 票数", i)
        //初始化时票数为0
        NodeAddr[i] = Node{name, 0}
    }
}

假设我们这个区块链项目有10个节点,然后初始化节点,将节点的名字设为 节点0到节点9,然后初始化票数为0,将初始化的节点放入节点列表中。

六、模拟投票

func Vote() {
    for i := 0; i < 10; i++ {
        rand.Seed(time.Now().UnixNano())
        time.Sleep(100000)
        vote := rand.Intn(10000)
        NodeAddr[i].Votes = vote
        fmt.Printf("节点 [%d] 票数 [%d]\n", i, vote)
    }
}

我们这里使用随机数来分配节点被投的票数,因为要给10个节点投票,所以遍历10次,每次给节点投范围为0-9999的票数。

七、选拔挖矿节点

func SortNodes() []Node {
    n := NodeAddr
    for i := 0; i < len(n); i++ {
        for j := 0; j < len(n)-1; j++ {
            if n[j].Votes < n[j+1].Votes {
                n[j], n[j+1] = n[j+1], n[j]
            }
        }
    }
    return n[:3]
}

然后我们根据投票数来选出投票的节点,这里我们使用冒泡排序根据投票数给节点排序,最后从排序后的列表中选出前三个票数最多的节点作为挖矿节点。

八、主逻辑

func main() {
    CreateNode()
    fmt.Printf("创建的节点列表: \n")
    fmt.Println(NodeAddr)
    fmt.Print("节点票数: \n")
    
    Vote()
    
    nodes := SortNodes()
    fmt.Print("获胜者: \n")
    fmt.Println(nodes)

    first := firstBlock()
    lastBlock := first
    fmt.Print("开始生成区块: \n")
    for i := 0; i < len(nodes); i++ {
        fmt.Printf("[%s %d] 生成新的区块\n", nodes[i].Name, nodes[i].Votes)
        lastBlock = nodes[i].GenerateNewBlock(lastBlock, []byte(fmt.Sprintf("new Block %d", i)))
    }
}

主逻辑也是比较简单的,先初始化10个节点,然后投票,再根据票数选出前三名。然后前三名来生成新的区块。

是不是很简单,如果有兴趣的话,还可以看看前面描述的关于PoW和PoS的简单实例。

目录
相关文章
|
2月前
|
算法 前端开发 数据处理
小白学python-深入解析一位字符判定算法
小白学python-深入解析一位字符判定算法
53 0
|
2月前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
54 3
|
2月前
|
存储 分布式计算 算法
大数据-106 Spark Graph X 计算学习 案例:1图的基本计算、2连通图算法、3寻找相同的用户
大数据-106 Spark Graph X 计算学习 案例:1图的基本计算、2连通图算法、3寻找相同的用户
72 0
|
16天前
|
机器学习/深度学习 人工智能 算法
深入解析图神经网络:Graph Transformer的算法基础与工程实践
Graph Transformer是一种结合了Transformer自注意力机制与图神经网络(GNNs)特点的神经网络模型,专为处理图结构数据而设计。它通过改进的数据表示方法、自注意力机制、拉普拉斯位置编码、消息传递与聚合机制等核心技术,实现了对图中节点间关系信息的高效处理及长程依赖关系的捕捉,显著提升了图相关任务的性能。本文详细解析了Graph Transformer的技术原理、实现细节及应用场景,并通过图书推荐系统的实例,展示了其在实际问题解决中的强大能力。
107 30
|
20天前
|
存储 算法
深入解析PID控制算法:从理论到实践的完整指南
前言 大家好,今天我们介绍一下经典控制理论中的PID控制算法,并着重讲解该算法的编码实现,为实现后续的倒立摆样例内容做准备。 众所周知,掌握了 PID ,就相当于进入了控制工程的大门,也能为更高阶的控制理论学习打下基础。 在很多的自动化控制领域。都会遇到PID控制算法,这种算法具有很好的控制模式,可以让系统具有很好的鲁棒性。 基本介绍 PID 深入理解 (1)闭环控制系统:讲解 PID 之前,我们先解释什么是闭环控制系统。简单说就是一个有输入有输出的系统,输入能影响输出。一般情况下,人们也称输出为反馈,因此也叫闭环反馈控制系统。比如恒温水池,输入就是加热功率,输出就是水温度;比如冷库,
151 15
|
17天前
|
存储 监控 调度
云服务器成本优化深度解析与实战案例
本文深入探讨了云服务器成本优化的策略与实践,涵盖基本原则、具体策略及案例分析。基本原则包括以实际需求为导向、动态调整资源、成本控制为核心。具体策略涉及选择合适计费模式、优化资源配置、存储与网络配置、实施资源监控与审计、应用性能优化、利用优惠政策及考虑多云策略。文章还通过电商、制造企业和初创团队的实际案例,展示了云服务器成本优化的有效性,最后展望了未来的发展趋势,包括智能化优化、多云管理和绿色节能。
|
2月前
|
搜索推荐 算法
插入排序算法的平均时间复杂度解析
【10月更文挑战第12天】 插入排序是一种简单直观的排序算法,通过不断将未排序元素插入到已排序部分的合适位置来完成排序。其平均时间复杂度为$O(n^2)$,适用于小规模或部分有序的数据。尽管效率不高,但在特定场景下仍具优势。
|
1月前
|
存储 人工智能 自然语言处理
高效档案管理案例介绍:文档内容批量结构化解决方案解析
档案文件内容丰富多样,传统人工管理耗时低效。思通数科AI平台通过自动布局分析、段落与标题检测、表格结构识别、嵌套内容还原及元数据生成等功能,实现档案的高精度分块处理和结构化存储,大幅提升管理和检索效率。某历史档案馆通过该平台完成了500万页档案的数字化,信息检索效率提升60%。
|
1月前
|
算法 Linux 定位技术
Linux内核中的进程调度算法解析####
【10月更文挑战第29天】 本文深入剖析了Linux操作系统的心脏——内核中至关重要的组成部分之一,即进程调度机制。不同于传统的摘要概述,我们将通过一段引人入胜的故事线来揭开进程调度算法的神秘面纱,展现其背后的精妙设计与复杂逻辑,让读者仿佛跟随一位虚拟的“进程侦探”,一步步探索Linux如何高效、公平地管理众多进程,确保系统资源的最优分配与利用。 ####
71 4
|
1月前
|
缓存 负载均衡 算法
Linux内核中的进程调度算法解析####
本文深入探讨了Linux操作系统核心组件之一——进程调度器,着重分析了其采用的CFS(完全公平调度器)算法。不同于传统摘要对研究背景、方法、结果和结论的概述,本文摘要将直接揭示CFS算法的核心优势及其在现代多核处理器环境下如何实现高效、公平的资源分配,同时简要提及该算法如何优化系统响应时间和吞吐量,为读者快速构建对Linux进程调度机制的认知框架。 ####

推荐镜像

更多