您正在查看: Surou 发布的文章

IBFT共识概述

介绍

伊斯坦布尔拜占庭容错(IBFT)共识是受Castro-Liskov 99论文启发的。

了iBFT通过使用3相一致,从原来PBFT继承PRE-PREPARE,PREPARE和COMMIT。系统最多可以容忍验证器网络中的F故障节点N,其中N = 3F + 1。

执行

术语

  • Validator:阻止验证参与者。
  • Proposer:区块验证参与者,被选择在共识回合中提议区块。
  • Round:共识轮。一轮以提议者创建整体提议开始,以整体承诺或轮次更改结束。
  • Proposal:正在进行共识处理的新区块生成提案。
  • Sequence:投标的序号。序列号应大于所有先前的序列号。当前,每个建议的块高度是其关联的序列号。
  • Backlog:用于保存将来的共识消息的存储。
  • Round state:特定顺序和回合的共识消息,包括预准备消息,准备消息和提交消息。
  • Consensus proof:可以证明该区块已通过共识过程的区块的承诺签名。
  • Snapshot:验证者从上一个时期开始的投票状态。

共识

《伊斯坦布尔BFT共识协议》从回合开始,0验证者以循环方式从他们自己选择提议者。然后,提议者将提出一个新的整体提议,并将其与PRE-PREPARE消息一起广播。在收到PRE-PREPARE来自提议者的消息后,其他验证者将验证传入的提议并输入消息的状态PRE-PREPARED并广播PREPARE消息。此步骤是确保所有验证程序都在相同的序列和同一轮上工作。当验证器从其他验证器接收到ceil(2N/3)ofPREPARE消息时,验证器将切换到的状态PREPARED并进行广播COMMIT信息。此步骤是要通知其他验证者它接受建议的块,并将该块插入到链中。最后,验证等待ceil(2N/3)的COMMIT消息进入COMMITTED状态,再追加块链。

Istanbul BFT协议中的块是最终的,这意味着没有分叉,并且任何有效块都必须位于主链中的某个位置。为了防止故障节点生成与主链完全不同的链,每个验证器都会在将ceil(2N/3)接收到的COMMIT签名extraData插入到链中之前,将接收到的签名附加到标头中的字段。因此,所有块都是可自我验证的。但是,动态extraData会导致块哈希计算出现问题。由于来自不同验证器的同一块可以具有不同的COMMIT签名集,因此同一块也可以具有不同的块哈希。为了解决这个问题,我们通过排除COMMIT签名部分来计算块哈希。因此,我们仍然可以保持块/块哈希的一致性,并在块头中放入共识证明。

共识国家

Istanbul BFT是一种状态机复制算法。每个验证器维护一个状态机副本,以便达成块共识。IBFT共识中的各个州是,

  • NEW ROUND:提案人发送新的整体提案。验证程序等待PRE-PREPARE消息。
  • PRE-PREPARED:验证者已收到PRE-PREPARE消息并广播PREPARE消息。然后,它等待ceil(2N/3)的PREPARE或COMMIT消息。
  • PREPARED:验证器接收到ceil(2N/3)的PREPARE消息和广播COMMIT消息。然后,它等待ceil(2N/3)的COMMIT消息。
  • COMMITTED:验证器接收到ceil(2N/3)的COMMIT消息,并且能够将提出块插入blockchain。
  • FINAL COMMITTED:将一个新块成功插入到区块链中,并且验证器已准备好进行下一轮。
  • ROUND CHANGE:一个验证正在等待ceil(2N/3)的ROUND CHANGE同一提出全面数量的消息。
状态转换

  • NEW ROUND-> PRE-PREPARED:
    • 投标人从收集交易txpool。
    • 提议者生成一个整体提议并将其广播给验证者。然后进入PRE-PREPARED状态。
    • 每个验证器PRE-PREPARED在收到PRE-PREPARE具有以下条件的消息时都会进入:
      • 整体提案来自有效的提案者。
      • 块头有效。
      • 阻止提议的顺序和回合匹配验证者的状态。
    • 验证者将PREPARE消息广播到其他验证者。
  • PRE-PREPARED-> PREPARED:
    • 验证器接收ceil(2N/3)到有效PREPARE消息以进入PREPARED状态。有效消息符合以下条件:
      • 匹配顺序和舍入。
      • 匹配的块哈希。
      • 消息来自已知的验证器。
    • 验证器COMMIT在进入PREPARED状态时广播消息。
  • PREPARED-> COMMITTED:
    • 验证器接收ceil(2N/3)到有效COMMIT消息以进入COMMITTED状态。有效消息符合以下条件:
      • 匹配顺序和舍入。
      • 匹配的块哈希。
      • 消息来自已知的验证器。
  • COMMITTED-> FINAL COMMITTED:
    • 验证程序将ceil(2N/3)承诺签名附加到extraData并尝试将块插入到区块链中。
    • FINAL COMMITTED插入成功后,验证器进入状态。
  • FINAL COMMITTED-> NEW ROUND:
    • 验证者选择一个新的提议者,并开始一个新的回合计时器。
回合变更流程
  • 可以触发ROUND CHANGE以下三个条件:
    • 轮换计时器到期。
    • 无效的PREPREPARE讯息。
    • 块插入失败。
  • 当验证者注意到上述条件之一适用时,它将广播ROUND CHANGE消息以及建议的轮回编号,并等待ROUND CHANGE来自其他验证者的消息。根据以下条件选择建议的轮数:
    • 如果验证已收到ROUND CHANGE来自同行的消息,它选择具有最大回合数F + 1的ROUND CHANGE消息。
    • 否则,它将选择1 + current round number为建议的轮数。
  • 验证器每当收到相同提议轮数上的消息时,就会将接收F + 1到的ROUND CHANGE消息与自己的消息进行比较。如果接收到的ROUND CHANGE消息更大,则验证器将使用接收到的号码再次广播消息。
  • 当接收ceil(2N/3)的ROUND CHANGE在同提出的圆数量的消息,所述验证器退出轮变化循环,计算出新的提议,然后进入NEW ROUND状态。
  • 验证器跳出舍入循环的另一个条件是它通过对等同步接收到已验证的块。
提案人选择

目前,我们支持两种政策:轮循和粘性提议者。

  • 轮询:轮询是默认的提议者选择策略。在此设置中,提议者将在每个区块和每个回合中更改。
  • 粘性提议者:在粘性提议者设置中,仅在发生回合更改时提议者才会更改。
验证人名单投票

Istanbul BFT使用与Clique类似的验证者投票机制,并从Clique EIP复制大部分内容。每个时代的交易都会重置验证者投票,这意味着将添加或删除验证者的所有待处理投票都将重置。

对于所有交易块:

  • 提议者可以投一票以提议更改验证者列表。
  • 每个目标受益人的最新提议仅由单个验证者保存。
  • 随着链条的进行,将实时计票(允许并发提案)。
  • 达成多数共识的提案VALIDATOR_LIMIT立即生效。
  • 无效的建议书不会因为客户实施的简化而受到惩罚。
  • 提案生效后,必须放弃该提案的所有未决票(赞成和反对)。
未来的消息和积压

在异步网络环境中,可能会收到将来无法在当前状态下处理的消息。例如,验证程序可以COMMIT在上接收消息NEW ROUND。我们称这种消息为“未来消息”。当验证器收到将来的消息时,它将把消息放入待办事项中,并尝试在以后尽可能的处理。

常数

Istanbul BFT定义以下常量

  • EPOCH_LENGTH:默认:30000个块。检查点并重置未决投票的块数。
  • REQUEST_TIMEOUT:在以毫秒为单位触发一轮变更之前,每个共识轮都超时。
  • BLOCK_PERIOD:两个连续块之间的最小时间戳差异(以秒为单位)。
  • PROPOSER_POLICY:投标者选择策略,默认为轮询。
  • ISTANBUL_DIGEST:固定幻数0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365的mixDigest在伊斯坦布尔块识别块标题。
  • DEFAULT_DIFFICULTY:默认阻止难度,设置为0x0000000000000001。
  • EXTRA_VANITY:为提议者虚荣保留的固定数量的额外数据前缀字节。
    • 建议的32字节数,以保留当前的额外数据余量。
  • NONCE_AUTH:不可思议的随机数0xffffffffffffffff,可在添加验证器时进行投票。
  • NONCE_DROP:不可思议的随机数,0x0000000000000000用于对删除验证程序进行投票。
  • UNCLE_HASH:总是Keccak256(RLP([]))像叔叔在PoW之外毫无意义。
  • PREPREPARE_MSG_CODE:固定号码0。消息的消息代码PREPREPARE。
  • PREPARE_MSG_CODE:固定号码1。消息的消息代码PREPARE。
  • COMMIT_MSG_CODE:固定号码2。消息的消息代码COMMIT。
  • ROUND_CHANGE_MSG_CODE:固定号码3。用于消息的代码ROUND CHANGE的消息
  • VALIDATOR_LIMIT:通过授权或取消授权提议的验证者数量。
    • 必须floor(N / 2) + 1在链上执行多数共识。
块头

Istanbul BFT不会添加新的块标题字段。相反,它遵循Clique重新使用ethash标头字段的方式,如下所示:

  • nonce:有关受益人字段定义的帐户的提案人提案。

    • 应NONCE_DROP提议取消授权受益人为现有验证人。
    • 应该是NONCE_AUTH提议授权受益人为新的验证人。
    • 必须用零填充,NONCE_DROP或NONCE_AUTH
  • mixHash:固定0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365用于识别伊斯坦布尔街区的魔幻数字。

  • ommersHash:必须如此,UNCLE_HASH因为叔叔在PoW之外毫无意义。

  • timestamp:必须至少是父时间戳+ BLOCK_PERIOD

  • difficulty:必须填充0x0000000000000001。

  • extraData:签名人虚荣和RLP编码的Istanbul额外数据的组合字段,其中Istanbul额外数据包含验证者列表,提议者印章和提交印章。伊斯坦布尔的额外数据定义如下:

    type IstanbulExtra struct {
          Validators    []common.Address  //Validator addresses
          Seal          []byte            //Proposer seal 65 bytes
          CommittedSeal [][]byte          //Committed seal, 65 * len(Validators) bytes
    }

    因此,extraData形式为EXTRA_VANITY | ISTANBUL_EXTRAwhere|代表固定索引,以分隔虚荣和伊斯坦布尔额外数据(不是分隔符的实际字符)。

  • 前EXTRA_VANITY字节(固定)可以包含任意提议者虚荣数据。

  • ISTANBUL_EXTRA字节是根据所计算的RLP编码的Istanbul额外数据RLP(IstanbulExtra),其中RLP()RLP编码函数IstanbulExtra是Istanbul的额外数据。

    • Validators:验证者列表,必须按升序排列。
    • Seal:标头的提议者签名盖章。
    • CommittedSeal:承诺签名盖章清单作为共识证明。

散列哈希,提议者印章和承诺印章
ethash由于以下原因,Istanbul区块哈希计算与区块哈希计算有所不同:

  1. 提议者需要盖上提议者的印章,extraData以证明该区块已被选定的提议者签名。
  2. 验证者需要放入ceil(2N/3)已提交的印章作为共识证明,extraData以证明该区块已通过共识。

ethash除了需要处理之外,该计算仍然类似于块哈希计算extraData。我们计算字段如下:

投标人印章计算

到提议者印章计算时,提交的印章仍然是未知的,因此我们计算出那些未知数为空的印章。计算如下:

  • Proposer seal: SignECDSA(Keccak256(RLP(Header)), PrivateKey)
  • PrivateKey:提议者的私钥。
  • Header:与ethash标头相同,只是不同而已extraData。
  • extraData:vanity | RLP(IstanbulExtra),其中在IstanbulExtra,CommittedSeal并且Seal是空的阵列。
区块哈希计算

在计算块哈希时,我们需要排除提交的密封,因为该数据在不同的验证器之间是动态的。因此,我们CommittedSeal在计算哈希值时会创建一个空数组。计算公式为:

  • Header:与ethash标头相同,只是不同而已extraData。
  • extraData:vanity | RLP(IstanbulExtra),其中在IstanbulExtra,CommittedSeal是一个空数组。
共识证明

在将区块插入区块链之前,每个验证者都需要ceil(2N/3)从其他验证者那里收集已提交的印章,以构成共识证明。一旦接收到足够的承诺密封,这将填补CommittedSeal中IstanbulExtra,重新计算extraData,然后再插入块成blockchain。请注意,由于提交的密封可能因不同的来源而有所不同,因此如上一节所述,我们在计算块哈希值时会排除该部分。

承诺印章计算:

提交的印章是由每个验证者对哈希值COMMIT_MSG_CODE及其私钥的消息代码签名而计算的。计算如下:

  • Committed seal:SignECDSA(Keccak256(CONCAT(Hash, COMMIT_MSG_CODE)), PrivateKey)。
  • CONCAT(Hash, COMMIT_MSG_CODE):连接块哈希和COMMIT_MSG_CODE字节。
  • PrivateKey:签署验证者的私钥。

出处

GoQuorum中的Istanbul BFT实施基于EIP 650。自从打开EIP以来,它已进行了更新,以通过引入锁定来解决安全问题。

原文:https://docs.goquorum.consensys.net/en/stable/Concepts/Consensus/IBFT/

开源以太坊浏览器

1.blockscout

开源地址:https://github.com/poanetwork/blockscout

BlockScout是一个Elixir应用程序,允许用户搜索交易,查看帐户和余额,并验证整个以太坊网络上的智能合约,包括所有的叉子和侧链。

目前可用的块探测器(即Etherscan和Etherchain)是封闭系统,不能独立验证。随着以太坊侧链在私人和公共场合的不断扩散,需要透明的工具来分析和验证交易。

2.EthVM

开源地址:https://github.com/EthVM/EthVM

EthVM是一个开源的区块链浏览器,主要关注以太坊(虽然其他网络将受到支持)在MIT许可下,并以不同语言(即TypeScript,Kotlin和Solidity)的混合编写。

您可以使用EthVM作为工具来探索自定义专用网络或现有公用网络,或者作为ETL(提取,转换,加载)平台来对数据执行不同的分析。

3.etherparty/explorer

开源地址:https://github.com/etherparty/explorer

轻盈的以太坊块探险家

4.carsenk/explorer

开源地址:https://github.com/carsenk/explorer

以太坊Block Explorer基于etherparty/explorer

5.etherchain-light

开源地址:https://github.com/gobitfly/etherchain-light

Etherchain Light是一个使用NodeJS,Express和Parity构建的以太坊区块链资源管理器。它不需要外部数据库,并从后端以太坊节点即时检索所有信息。

6.toy-block-explorer

开源地址:https://github.com/curvegrid/toy-block-explorer

用Go编写的区块链资源管理器,用于了解如何构建与以太坊区块链一起使用的服务器端应用程序。

7.mini-eth-browser

开源地址:https://github.com/ismaelbej/mini-eth-browser

一个简单的以太坊块和事务探索器。由于它不使用数据库,因此某些操作很慢。

8.eth-explorer

开源地址:https://github.com/ethnamed/eth-explorer

简单的Nodejs以太坊资源管理器

9.Clixplorer

开源地址:https://github.com/Magicking/Clixplorer

10.ethereumproject / explorer

开源地址:https://github.com/ethereumproject/explorer

11. 模仿etherscan

https://github.com/bing-chou/etherscan-explorer

参考

https://www.cnblogs.com/huangenai/p/10075876.html

使用web3.js监听以太坊智能合约event

var Web3 = require("web3")

var web3;

if (typeof web3 !== 'undefined') {
    web3 = new Web3(web3.currentProvider);
} else {
    web3 = new Web3(new Web3.providers.WebsocketProvider("ws://172.17.116.158:8546"));
}

var contractAbi = [{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"address","name":"proposer","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"LogCreateProposal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"LogPassProposal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"LogRejectProposal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"val","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"LogSetUnpassed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"bool","name":"auth","type":"bool"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"LogVote","type":"event"},{"inputs":[],"name":"MaxValidators","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MinimalStakingCoin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROPOSAL_ADDR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ProposalAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PunishContractAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"StakingLockPeriod","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ValidatorContractAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WithdrawProfitPeriod","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"miner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pass","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalLastingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"proposals","outputs":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"string","name":"details","type":"string"},{"internalType":"uint256","name":"createTime","type":"uint256"},{"internalType":"uint16","name":"agree","type":"uint16"},{"internalType":"uint16","name":"reject","type":"uint16"},{"internalType":"bool","name":"resultExist","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"val","type":"address"},{"internalType":"address","name":"punish","type":"address"},{"internalType":"address","name":"proposal","type":"address"}],"name":"setContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"miner_","type":"address"}],"name":"setMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"votes","outputs":[{"internalType":"address","name":"voter","type":"address"},{"internalType":"uint256","name":"voteTime","type":"uint256"},{"internalType":"bool","name":"auth","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"vals","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"string","name":"details","type":"string"}],"name":"createProposal","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bool","name":"auth","type":"bool"}],"name":"voteProposal","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"val","type":"address"}],"name":"setUnpassed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}];

var contractaAddress = "0x000000000000000000000000000000000000F002";

MyContract = new web3.eth.Contract(contractAbi, contractaAddress);
                //console.log(MyContract.events.orderlog);

var myEvent = MyContract.events.LogCreateProposal({
        filter:{},
        fromBlock: 0
}, function(error, event){})
        .on('data', function(event){
        console.log(event); // same results as the optional callback above
})
        .on('changed', function(event){
                    // remove event from local database
        })        
    .on('error', console.error);

运行

npm init -y
npm install web3 --save
node map_event.js

测试数据

{
  address: '0x000000000000000000000000000000000000F002',
  blockNumber: 64274,
  transactionHash: '0x950203bc5d391a6b8180c5be6d290403f39fe81a8666e40b74cc3b9b094ce1a6',
  transactionIndex: 0,
  blockHash: '0x9abb16d015c49268c04909bcea414994d9bc0867dc8648b5e3dd33071d86daf5',
  logIndex: 0,
  removed: false,
  id: 'log_14a4176e',
  returnValues: Result {
    '0': '0x88437e94b8ffc61e30087ba66182c8f291e4af36d289ae299f676f014fdba411',
    '1': '0xc65dD4299C682f335d6e15e2B5774D015E01E479',
    '2': '0xc65dD4299C682f335d6e15e2B5774D015E01E479',
    '3': '1614340623',
    id: '0x88437e94b8ffc61e30087ba66182c8f291e4af36d289ae299f676f014fdba411',
    proposer: '0xc65dD4299C682f335d6e15e2B5774D015E01E479',
    dst: '0xc65dD4299C682f335d6e15e2B5774D015E01E479',
    time: '1614340623'
  },
  event: 'LogCreateProposal',
  signature: '0xc10f2f4d53a0e342536c6af3cce9c6ee25c32dbb323521ce0e1d4494a3e362e8',
  raw: {
    data: '0x000000000000000000000000000000000000000000000000000000006038e20f',
    topics: [
      '0xc10f2f4d53a0e342536c6af3cce9c6ee25c32dbb323521ce0e1d4494a3e362e8',
      '0x88437e94b8ffc61e30087ba66182c8f291e4af36d289ae299f676f014fdba411',
      '0x000000000000000000000000c65dd4299c682f335d6e15e2b5774d015e01e479',
      '0x000000000000000000000000c65dd4299c682f335d6e15e2b5774d015e01e479'
    ]
  }

参考

https://www.cnblogs.com/tokenpai/p/10334952.html

基于以太坊支持数据隐私

官网:https://consensys.net/
开源地址: https://github.com/ConsenSys/quorum

详细介绍:https://rdc.hundsun.com/portal/article/892.html

Quorum是一个基于以太坊的分布式账本协议,具有交易/合同隐私和新的共识机制。

Quorum是go-ethereum的一个分支,并根据go-ethereum发行版进行了更新。

以太坊的主要增强功能:

  • 隐私-Quorum通过公共/私有状态分离来支持私有交易和私有合同,并利用对等加密消息交换(请参阅Constellation和Tessera)将私有数据定向传输到网络参与者

  • 替代共识机制-Quorum不需要在许可的网络中使用POW / POS,而是提供了多个更适合联盟链的共识机制:

    • 基于筏的共识-一种共识模型,可加快区块时间,完成交易并按需创建区块
    • Istanbul BFT-由AMIS启发,具有PBFT的交易最终性的共识算法。
    • Clique POA共识-与Go Ethereum捆绑在一起的默认POA共识算法。
  • 对等权限-节点/对等权限,确保只有已知方才能加入网络

  • 帐户管理-Quorum引入了帐户插件,该插件使Quorum或clef可以通过包括外部库在内的其他帐户管理方法进行扩展。

  • 可插拔架构-允许将其他功能作为插件添加到核心geth,从而提供可扩展性,灵活性和Quorum功能的独特隔离。

  • 更高的性能-Quorum提供的性能吞吐量比公共场所高得多

IBFT共识概述: https://docs.goquorum.consensys.net/en/stable/Concepts/Consensus/IBFT/
https://www.jianshu.com/p/43354a82e176