Quorum 是一个源自以太坊的许可制分布式账本,专为联盟场景设计:参与者需要共享一致的账本,但不一定需要看到彼此的交易负载。其核心机制是将每个节点都验证的公共状态树与仅交易参与方在本地物化的私有状态树分离,并结合基于投票的共识(如 Raft 或 Istanbul BFT)而非工作量证明。本文解释这一心智模型,逐步演示部署私有合约并验证非参与方无法读取的可复现流程,并讨论决定 Quorum 是否适合的操作权衡。文档化的协议行为与建议以及您应在自己网络上运行的测量结果保持分离。
Quorum 是什么以及本指南涵盖的内容
Quorum 是以太坊的许可制实现。维护中的客户端谱系是 GoQuorum,它是 Go Ethereum(geth)的轻量级分支,保留了以太坊的账户模型、EVM、JSON-RPC 接口和 Solidity 工具链,同时改变了共识、对等节点准入和状态处理方式。该项目最初由 J.P. Morgan 发起,后转由 ConsenSys 管理;上游归档仓库为只读状态,因此请固定您打算运行的具体客户端版本和发行版,而不要假设上游会持续滚动更新。
Quorum 解决的实际问题不是“如何让以太坊更快”,而是“多个组织如何共享一个账本,而不将商业敏感负载广播给每个参与者”。这一框架驱动了下面的每个设计决策。本指南涵盖状态模型、共识家族、可运行的私有交易工作流、验证、故障排除以及您在承诺前应权衡的限制。
范围说明:本页解释机制和方法论。它不推荐特定的托管端点或托管供应商;如果您需要为以太坊兼容网络做出具体的 RPC 端点决策,请使用 RPC Assistant,而不要将本页视为供应商比较。
- 假设您熟悉以太坊账户、Gas 和 Solidity 合约。
- 假设您可以运行 Docker 或多个主机进程来搭建小型测试网络。
- 所有命令使用 RPC_URL 和 PRIVATE_KEY 等占位符;请替换为您自己的值。
公共状态、私有状态与隐私管理器
Quorum 节点维护两个状态树。公共状态树的行为类似以太坊:每个节点执行公共交易并验证区块头中记录的全局公共状态根。私有状态树保存私有交易的结果,仅存在于其隐私管理器是该交易接收方的节点上。区块验证经过修改,使区块头承诺公共状态根,这就是为什么所有节点可以在不持有相同私有数据的情况下就区块有效性达成一致。
私有交易由与节点并行运行的隐私管理器(历史上是 Tessera,早期部署中是 Constellation)中介。当您发送私有交易时,负载会加密到接收方的密钥并通过隐私管理器网络分发;链本身只接收加密负载的哈希。接收方节点检索负载、解密并在本地私有状态上执行。非接收方看到的是带有无法解析的负载哈希的交易,因此其私有状态不受影响。
这是需要牢记的心智模型:链是共享协调层,隐私管理器是承载机密内容的侧信道。几乎每个 Quorum 操作问题都可归结为这两层之间的不匹配——节点有区块但没有负载,或负载被传递给了错误的密钥。
共识选择及其编码的信任模型
Quorum 用基于投票的共识取代工作量证明。Raft 是一种崩溃容错算法:它假设节点会失败但不会主动撒谎,并通过领导者追加条目实现快速最终性。Istanbul BFT(以及后续 GoQuorum 版本中的 QBFT 继任者)是拜占庭容错的:它以额外的消息轮次为代价,容忍有限比例的恶意或分歧验证者。
这一选择是信任决策,而非性能旋钮。如果每个验证者都由您自己的组织或受法律协议和共享操作控制约束的交易对手运营,Raft 的假设是合理的,且协议更简单。如果验证者独立运营且可能 equivocate,则需要 BFT 家族。请明确记录假设,因为一个在互不信任的各方之间悄悄运行 Raft 的网络,其安全态势无人记录在案。
许可制是信任模型的另一半。点对点层经过修改,使节点仅连接到被允许的对等节点,账户级许可制可以限制谁可以部署或调用合约。将许可制配置视为生产代码:对其进行版本控制、审查变更,并在需要之前测试准入和撤销路径。
- Raft:崩溃容错,基于领导者的追加,适合单一运营方或紧密联盟网络。
- IBFT/QBFT:拜占庭容错,适合独立运营的验证者。
- 许可制:对等节点准入加上可选的账户/角色限制;测试撤销,而不仅仅是准入。
可复现测试网络的先决条件
在运行以下流程之前,确认您有一个可用的 Quorum 部署,至少四个节点、每个节点一个隐私管理器,以及您将用作 RPC 目标的节点上有一个有资金的账户。确切的引导工具因发行版而异——一些团队使用 Quorum Dev Quickstart 风格的 Compose 设置,其他团队使用自己的创世块和静态节点配置。该流程刻意与工具无关,以便在发行版变更后仍适用。
您还需要一种访问节点 JSON-RPC 接口的方式。对于本地测试网络,通常是第一个节点上的 http://127.0.0.1:8545;对于任何共享环境,请将端点置于正常的访问控制之后,切勿通过开放接口暴露未锁定账户。如果您正在评估如何大规模安全地暴露以太坊兼容 RPC,关于区块链节点托管 的指南是有用的补充。
开始前记录以下内容:参与节点的 RPC URL、非参与节点的 RPC URL、每个隐私管理器的公钥,以及有资金账户的地址。您将在最后比较两个节点,而该比较才是真正的测试。
部署和调用私有合约
以下工作流使用 web3.js 针对运行中的节点。关键细节是 privateFor(或在较新隐私管理器配置中的 privacyGroupId)字段:它指定其隐私管理器应接收负载的接收方。省略它,交易就是公共的,这是“我的私有数据可见”报告的最常见原因。
首先,确认节点可达并检查它期望的隐私管理器 API 版本。下面的 curl 调用是只读的健全性检查。
curl -s -X POST "$RPC_URL" \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
# Expected: a JSON result containing a hex block number, e.g. {"jsonrpc":"2.0","id":1,"result":"0x1a"}
# A connection error means the node is down or the URL/port is wrong;
# a JSON-RPC error usually means the method or params are malformed.私有部署脚本与预期输出
下面的脚本部署一个带有单个存储值的最小合约,并将其私密发送给一个交易对手。用您自己的值替换占位符。接收方公钥是交易对手节点的隐私管理器密钥,而不是以太坊账户地址——混淆这两者是最常见的第二大失败原因。
部署后,从参与节点和非参与节点分别读回该值。参与节点应返回存储的值;非参与节点应返回零值或无法解析合约的私有状态,因为它从未收到负载。
const Web3 = require('web3');
const web3 = new Web3(process.env.RPC_URL);
const abi = [{"inputs":[],"name":"value","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"v","type":"uint256"}],"name":"setValue","outputs":[],"stateMutability":"nonpayable","type":"function"}];
const bytecode = '0x...'; // compiled contract bytecode
async function main() {
const account = web3.eth.accounts.privateKeyToAccount(process.env.PRIVATE_KEY);
web3.eth.accounts.wallet.add(account);
const contract = new web3.eth.Contract(abi);
const deploy = contract.deploy({ data: bytecode });
const tx = {
from: account.address,
data: deploy.encodeABI(),
gas: 3000000,
privateFor: [process.env.RECIPIENT_PRIVACY_PUBLIC_KEY],
};
const receipt = await web3.eth.sendTransaction(tx);
console.log('contract address:', receipt.contractAddress);
console.log('transaction hash:', receipt.transactionHash);
}
main().catch((e) => { console.error(e); process.exit(1); });验证:正确结果的样子
验证分为三层,仅通过其中一层并不能证明隐私。首先,确认交易已打包并在公共链上有收据——每个节点都应同意交易存在。其次,确认参与节点可以读取私有状态:调用合约的视图函数并期望得到您设置的值。第三,确认非参与节点无法读取:相同的调用应返回零、回滚或以其他方式无法暴露该值。
将结果记录在表格中,使结果可审计而非轶事。不要填写您未观察到的数字;下表是模板,值必须来自您自己的运行。
- 交易哈希在所有节点上存在:是/否。
- 收据状态在所有节点上成功:是/否。
- 私有值在参与节点上可读:观察到的值。
- 私有值在非参与节点上可读:观察到的值或错误。
- 隐私管理器日志显示负载仅传递给预期接收方:是/否。
私有交易失败的故障排除
大多数失败属于少数几类。按顺序处理它们,因为后面的症状常常掩盖了早期原因。
如果交易已打包但预期接收方的私有状态为空,则负载从未到达。检查双方的隐私管理器日志中的传递和解密错误,确认接收方公钥与交易对手的实际隐私管理器密钥匹配,并确认隐私管理器可从发送方节点访问。一方密钥轮换而未更新另一方是典型原因。
如果交易在打包前被拒绝,首先检查 Gas 和 nonce,然后检查许可制。私有交易尽管负载机密,仍会在公共链上消耗 Gas,账户级许可制可能拒绝在另一节点上有效的发送方。如果只有部分节点拒绝,请比较它们的许可制配置而非共识配置。
如果共识停滞,区分崩溃的领导者和分区的验证者。在 Raft 中,停滞的领导者通常在选举后恢复;在 BFT 家族中,失去法定人数会产生明显的进展缺失而非静默分歧。在接触应用代码之前,检查对等节点数量和验证者活跃度。
承诺前应权衡的限制与取舍
Quorum 的隐私模型是参与者之间的机密性,而非对运营者的密码学保密。持有解密密钥的节点可以读取负载,隐私管理器是架构中的受信任组件。如果您的威胁模型包括基础设施运营者,仅靠 Quorum 无法解决。
生态系统已经整合。上游 GoQuorum 仓库已归档且只读,因此长期维护取决于您选择的发行版或供应商。规划版本固定、经过测试的升级路径和退出策略。公共以太坊工具兼容性是一个真正的优势,但它是对移动目标的兼容性,而非保证。
性能声明应视为依赖于工作负载。投票共识消除了工作量证明开销,但吞吐量受区块 Gas 限制、隐私管理器延迟以及每笔私有交易的接收方数量限制。在您自己的拓扑和合约组合上测量;不要将供应商页面上的每秒交易数作为规划输入。
最后,考虑您是否真的需要私有网络。如果机密性要求狭窄,具有应用层加密的以太坊兼容公共网络可能更易于运营。如果您在评估期间需要以太坊兼容网络的托管节点,专用节点选项和 RPC 定价页面描述了运营模式。
后续步骤与相关阅读
一旦验证流程通过,接下来的工作是操作性的而非概念性的:自动化隐私管理器健康检查,将三层验证添加到合约升级的 CI 管道中,并演练验证者密钥轮换和对等节点撤销。这些演练将演示网络与可投入生产的网络区分开来。
有关运行区块链基础设施的更广泛背景,节点托管指南涵盖了同样适用于 Quorum 节点的供应和监控模式。如果您正在将 Quorum 与公共网络部署进行比较,多链 RPC 端点指南解释了端点抽象如何跨网络工作,网络目录列出了 OnFinality 支持的链。当您准备为以太坊兼容网络选择具体端点时,RPC Assistant 会给出直接推荐而非冗长的比较。