联盟链系列 - 适用于联盟链的PoA共识

2023-10-07 03:59
文章标签 系列 适用 联盟 共识 poa

本文主要是介绍联盟链系列 - 适用于联盟链的PoA共识,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Clique PoA技术原理

1.共识机制

决定哪个节点能获得当前区块的记账权

  • PoW(Proof-of-Work): 工作量证明机制就是区块链网络中一堆计算机通过计算随机数的Hash值,谁先找到这个随机数谁就赢的当前区块的记账权。拼算力
  • PoA(Proof of Authority): 授权证明机制就是由一组授权节点来负责新区块的产生和区块验证,按授权节点的地址升序排序后,按顺序轮流获得记账权。 人人平等

Ethereum存在两个PoA测试网,分别是Kovan(PoA算法,Parity专用,Rust 语言)和Rinkeby(Clique PoA共识算法,Geth专用(版本号>=1.6),Go语言)
Kovan
PoA (Immune to spam attacks)
Supported by parity only
Chaindata size 13 GB - Apr 2018
Rinkeby
PoA (Immune to spam attacks)
Supported by geth only
Chaindata size 6 GB - Apr 2018

2.PoA的特点

  • PoW该有的功能PoA都有,使用方法也一样,包括交易,智能合约,发币,DAPP
  • 节点分类
    • 普通节点(node):
      • 普通的以太坊节点,没有区块生成的权利。不能挖矿,无选举权,有被选举权
    • 授权节点(signer):
      • 具有区块生成权利的以太坊节点,即矿工。能挖矿,有选举权和被选举权
  • 授权节点的职能
    • 授权节点(signers)负责产生block。可以由已授权的signer选举(投票超过50%)加入新的signer,或者投票(超过50%)踢出某个signer。
  • 创世块配置
    • 指定出块时间,
    • 预设默认的一批signers(至少一个),
    • 给指定地址设置ETH余额(得预先配置好)
  • ETH币
    • 挖矿无奖励

3.挖矿

对于一个新区块被挖掘出的过程,代码实现上基本分为两个环节:

  • 一是组装出一个新区块,这个区块的数据基本完整,包括成员Header的部分属性,和叔区块组uncles[],以及交易列表txs,并且所有交易已经执行完毕,所有收据(Receipt)也已收集完毕,这部分主要由worker完成;

  • 二是填补该区块剩余的成员属性,比如Header.Difficulty,coinbase等,并完成授权,这些工作是由Agent调用接口实现体Prepare,Seal,利用共识算法来完成的。

第一步 收集数据 worker.commitNewWork()(miner/worker.go)

  • 4种情况会调用到这个函数

  • 程序启动时,执行newWorker方法初始化worker对象时,调用commitNewWork方法,开始组装新区块。

  • 启动挖矿时,miner.start里会调用worker.start()和worker.commitNewWork()

  • 网络接收到其他矿工广播过来的新区块,该区块验证有效插入到区块链后,会产生ChainHeadEvent事件,worker对象的update协程检测到该事件后,会调用commitNewWork方法,开始生成新的区块。

  • 矿工自己生成新的区块并入链后,会向全网广播NewMinedBlockEvent,同时也会给自己发一个ChainHeadEvent,之后就跟上面的一样

挖矿UML_1
挖矿UML_2

  • commitNewWork()做了什么?
    • 准备新区块的Header属性,可确定的有Time,Number,ParentHash,其余留待之后共识算法中确定
    • 调用engine.Prepare()函数,完成部分Header对象的准备
    • 准备新区块的交易列表,并执行这些交易
    • 准备新区块的叔块uncles[]
    • 调用engine.Finalize()函数,对新区块“定型”,填充Header对象 Root(默克尔根),TxHash(默克尔根), ReceiptHash(默克尔根), UncleHash等属性。
    • 把创建的Work对象,通过channel发送给每一个登记过的Agent,进行后续的挖掘。
      worker.push() -> CpuAgent.update()

第二步 授权 CpuAgent(miner/agent.go)

  • 和共识有关的主要是这几个函数Start(),update()和mine()
    • CpuAgent.Start() 用来启动CpuAgent.update()协程
      • miner.New() -> miner.Register(NewCpuAgent) -> (if Mining) agent.Start() -> go agent.update()
      • miner.Start() -> worker.start() -> agent.Start() -> go agent.update()
    • CpuAgent.update() 用来监听worker.commitNewWork()结束前通过worker.push()发出的channel
      • worker.push() -> CpuAgent.update() -> CpuAgent.mine()
    • CpuAgent.mine() 利用Engine实现体的共识算法对传入的Block进行最终的授权, 如果成功,就将Block同Work一起通过channel发还给worker,那边worker.wait()会接收并处理
      • CpuAgent.mine() -> engine.Seal() -> worker.wait()

挖矿UML_3

到此,形成一个大的消息循环, 产生出了新区块,哦也!!!

4.共识

不过真正的主角还未出场,注意到这三个函数engine.Prepare() , engine.Finalize() , engine.Seal() ,它们是共识算法对外暴露的接口.该接口有两种实现体,即PoW和PoA
共识

5.Clique PoA的实现

POA 共识算法通过复用当前以太坊区块头中可用的 Extra 字段,将签名者列表(epoch块)和当前节点的签名者对该区块头的签名数据写入其中。更新一个动态的签名者列表的方法是复用区块头中的 Coinbase 和 Nonce 字段,以创建投票方案。
在这里插入图片描述

投票规则设定

  • 投票方必须是已认证的
  • 有效投票必须满足:被投票地址的新认证状态与其现状相反。
  • 任意地值A只能给地址B投一张票
  • 只有获得记账权时,才能将票投出去
  • 不允许反复连续投 (由于有最近签名者的限制,在SIGNER_COUNT / 2 + 1个块内,签名者只能签署一个块)

共识的过程 也是 动态管理所有认证地址的过程

  • 通过API提供的方法,插入或删除投票(未上链,只缓存在本地节点内存中)
    • clique.Propose(address,bool)
    • clique.Discard(address)
  • 通过clique.Prepare() 方法,从本地众多未上链的有效投票中,随机出一张票,准备上链
    • 遍历最近一次缓存快照之后的块(最多checkpointInterval=1024个块),更新票数和授权地址列表
    • clique.Prepare() -> clique.snapshot() -> Snapshot.apply()
    • 填充header对象的Coinbase,Nonce,Difficulty,Extra(预留后缀,用于Seal()存入当前块签名者的签名)
  • 通过clique.Finalize() 方法,对新区块“定型”,计算header.Root的值(默克尔根),丢弃叔块,且不给挖矿奖励
  • 通过clique.Seal()方法,生成签名到header.Extra的后缀中
    • 更新票数和授权列表,保证即将充当公钥的地址在最新的Signers中
    • clique.Seal() -> clique.snapshot() -> Snapshot.apply()
    • 依据header.Difficulty的值,如果优先级低,则随机延迟 rand((SIGNER_COUNT / 2 + 1) * 500) ms 再签名

Clique PoA_2

Snapshot.apply() 做了什么

遍历传入的所有Header对象,是一个遍历历史区块头的过程

  • 首先从数字签名中恢复出签名所用公钥,转化为common.Address类型,作为signer地址。数字签名(signagure)长度65 bytes,存放在Header.Extra[]的末尾。
  • 如果signer地址是尚未认证的,则直接退出本次迭代;如果是已认证的,则记名投票+1。所以一个父区块可添加一张记名投票,signer作为投票方地址,Header.Coinbase作为被投票地址,投票内容authorized可由Header.Nonce取值确定
  • 更新投票统计信息。如果被投票地址的总投票次数达到已认证地址个数的一半,则通过之
  • 该被投票地址的认证状态立即被更改,根据是何种更改,相应的更新缓存数据,并删除过时的投票信息

在这里插入图片描述

总结

Clique(PoA)利用数字签名算法完成Seal操作,签名所用公钥必须是已认证的。所有认证地址基于投票规则进行动态管理,记名投票由不记名投票和投票方地址随机组合而成,杜绝重复的不记名投票,严格限制外部代码恶意操纵投票数据。

参考文章

https://blog.csdn.net/teaspring/article/details/78050274

Clique联盟链搭建

https://blog.csdn.net/liuzhijun301/article/details/80784529


往期精彩回顾:
区块链知识系列
密码学系列
零知识证明系列
共识系列
公链调研系列
比特币系列
以太坊系列
EOS系列
联盟链系列
Fabric系列
智能合约系列
Token系列

这篇关于联盟链系列 - 适用于联盟链的PoA共识的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/155898

相关文章

mysql重置root密码的完整步骤(适用于5.7和8.0)

《mysql重置root密码的完整步骤(适用于5.7和8.0)》:本文主要介绍mysql重置root密码的完整步骤,文中描述了如何停止MySQL服务、以管理员身份打开命令行、替换配置文件路径、修改... 目录第一步:先停止mysql服务,一定要停止!方式一:通过命令行关闭mysql服务方式二:通过服务项关闭

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

GPT系列之:GPT-1,GPT-2,GPT-3详细解读

一、GPT1 论文:Improving Language Understanding by Generative Pre-Training 链接:https://cdn.openai.com/research-covers/languageunsupervised/language_understanding_paper.pdf 启发点:生成loss和微调loss同时作用,让下游任务来适应预训

Java基础回顾系列-第七天-高级编程之IO

Java基础回顾系列-第七天-高级编程之IO 文件操作字节流与字符流OutputStream字节输出流FileOutputStream InputStream字节输入流FileInputStream Writer字符输出流FileWriter Reader字符输入流字节流与字符流的区别转换流InputStreamReaderOutputStreamWriter 文件复制 字符编码内存操作流(

Java基础回顾系列-第五天-高级编程之API类库

Java基础回顾系列-第五天-高级编程之API类库 Java基础类库StringBufferStringBuilderStringCharSequence接口AutoCloseable接口RuntimeSystemCleaner对象克隆 数字操作类Math数学计算类Random随机数生成类BigInteger/BigDecimal大数字操作类 日期操作类DateSimpleDateForma

Java基础回顾系列-第三天-Lambda表达式

Java基础回顾系列-第三天-Lambda表达式 Lambda表达式方法引用引用静态方法引用实例化对象的方法引用特定类型的方法引用构造方法 内建函数式接口Function基础接口DoubleToIntFunction 类型转换接口Consumer消费型函数式接口Supplier供给型函数式接口Predicate断言型函数式接口 Stream API 该篇博文需重点了解:内建函数式

Java基础回顾系列-第二天-面向对象编程

面向对象编程 Java类核心开发结构面向对象封装继承多态 抽象类abstract接口interface抽象类与接口的区别深入分析类与对象内存分析 继承extends重写(Override)与重载(Overload)重写(Override)重载(Overload)重写与重载之间的区别总结 this关键字static关键字static变量static方法static代码块 代码块String类特