跳转至

构建财团区块链

财团(通常由银行、电子商务网站、政府实体、医院等几个参与者组成的协会)可以使用区块链技术来解决许多问题,并使事情变得更快、更便宜。尽管他们知道区块链可以如何帮助他们,但区块链的以太坊实现并不特别适合所有情况。尽管区块链还有其他的实现(例如,Hyperledger)是专门为财团构建的,但正如我们在整本书中学到的以太坊一样,我们将看到如何黑掉以太坊来构建财团区块链。基本上,我们将利用平价来建立一个区块链财团。尽管有其他替代奇偶校验的方法,如 J.P. Morgan 的 quorum,我们将使用奇偶校验,因为在撰写本书时,它已经存在了一段时间,许多企业已经在使用它,而其他替代方法尚未被任何企业使用。但是对于你的要求,奇偶可能不是最好的解决方案;因此,在决定使用哪一个之前,也要调查所有其他的。

在本章中,我们将讨论以下主题:

  • 为什么以太坊不适合区块链财团?
  • 什么是奇偶校验节点,它有什么特点?
  • 什么是权威证明共识协议,奇偶校验支持哪些类型的 PoA?
  • Aura 共识协议是如何工作的?
  • 下载和安装奇偶校验
  • 利用平价建立区块链财团

什么是区块链财团?

为了理解什么是区块链财团,或者换句话说,什么样的区块链实现财团需要,让我们来看一个例子。银行希望建立一个区块链,使资金转移更容易、更快、更便宜。在这种情况下,以下是他们需要的东西:

  1. 速度:他们需要一个能够近乎实时地确认交易的区块链网络。目前,以太坊区块链网络封锁时间是 12 秒,客户通常要等几分钟才能确认交易。
  2. 被许可的:他们想要区块链被许可。许可本身意味着各种不同的事情。例如:许可可以包括获取加入网络的许可,可以包括获取能够创建块的许可,也可以获取能够发送特定事务的许可等等。
  3. 安全性:PoW 对于私有网络来说不够安全,因为参与者的数量有限;因此,没有足够的散列能力来保证它的安全。因此,需要一个协商一致的协议来保持区块链的安全性和不可改变性。
  4. 隐私:虽然网络是私有的,但是网络本身还是有隐私的需求。有两种隐私:
  5. 身份隐私:身份隐私是使身份不可追踪的行为。我们之前看到的获取身份隐私的解决方案是使用多个以太坊账号地址。但是,如果使用多个以太坊账户,那么智能合约将无法通过所有权验证,因为没有办法知道所有这些账户是否实际上属于同一个用户。
  6. 数据隐私:有时候,我们不希望数据对网络中的所有节点可见,而只是对特定的节点可见。

总的来说,在这一章中,我们将学习如何在以太坊中解决这些问题。

什么是权威证明共识?

PoA 是区块链的一种共识机制,其中共识是通过引用一系列验证者(当它们与物理实体相关联时称为授权机构)来实现的。验证者是一组被允许参与共识的账户/节点;他们验证交易和冻结。

与 power 或 PoS 不同,这里不涉及挖掘机制。PoA 协议有多种类型,它们根据实际工作方式而有所不同。Hyperledger 和 Ripple 基于 PoA。Hyperledger 基于 PBFT,而 ripple 使用迭代过程。

奇偶校验简介

奇偶校验是一个以太坊节点,从头开始编写,以实现正确性/可验证性、模块化、低占用空间和高性能。它是用 Rust 编程语言编写的,这是一种混合命令式/面向对象/函数式语言,强调效率。它是由奇偶技术公司专业开发的。在写这本书的时候,奇偶校验的最新版本是 1.7.0,我们将使用这个版本。我们将尽可能多地学习建立区块链财团所需的知识。要深入学习奇偶性,可以参考官方文档。

它比 go-ethereum 有更多的功能,例如 web3 dapp 浏览器,更高级的帐户管理等等。但是它的特别之处在于它支持 PoW 和授权证明 ( PoA )。奇偶校验目前支持 Aura 和 Tendermint PoA 协议。将来,它可能会支持更多的 PoA 协议。目前,奇偶校验建议使用 Aura 而不是 Tendermint,因为 Tendermint 仍在开发中。

对于许可的区块链,Aura 是比 PoW 更好的解决方案,因为它具有更好的阻塞时间,并在专用网络中提供更好的安全性。

了解光环的工作原理

让我们看看光环是如何工作的。Aura 要求在每个节点中指定相同的验证器列表。这是参与共识的客户地址列表。节点可以是也可以不是验证节点。即使是验证节点也需要有这个列表,以便它自己能够达成共识。

如果验证器列表将永远保持不变,则该列表可以作为 genesis 文件中的静态列表提供,或者在智能契约中提供,以便它可以动态更新,并且每个节点都知道它。在智能合约中,您可以配置关于谁可以添加新验证器的各种策略。

封锁时间可在源文件中配置。封锁时间由你决定。在专用网络中,低至三秒的阻塞时间就能很好地工作。在 Aura 中,每隔三秒钟,就会选择一个验证器,这个验证器负责创建、验证、签名和广播块。我们不需要了解太多实际的选择算法,因为它不会影响我们的 dapp 开发。但这是计算下一个验证器(UNIX_TIMESTAMP / BLOCK_TIME % NUMBER_OF_TOTAL_VALIDATORS)的公式。选择算法足够聪明,可以给每个人平等的机会,当其他节点收到一个块时,它们会检查它是否来自下一个有效的验证器;如果没有,他们会拒绝。与 PoW 不同,当验证器创建一个块时,它不会得到以太奖励。在 Aura 中,当没有事务时,由我们决定是否生成空块。

您一定想知道,如果下一个验证器节点由于某种原因无法创建和广播下一个块,会发生什么。为了理解这一点,我们举个例子:假设 A 是下一个块的验证器,这是第五个块,B 是第六个块的验证器。假设阻塞时间为 5 秒。如果 A 未能广播一个块,那么五秒钟后轮到 B 时,它将广播一个块。所以实际上没有什么严重的事情发生。数据块时间戳将揭示这些详细信息。

您可能还想知道,当两名矿工同时采矿时,网络是否有可能出现多个不同的区块链。是的,有很多方法可以做到这一点。让我们举一个例子,了解这种情况发生的一种方式,以及网络如何自动解决它。假设有五个验证器:A、B、C、D 和 e。假设 A 先被选中,它广播了一个块,但是这个块由于某种原因没有到达 D 和 E;所以他们会认为 A 没有广播这个区块。现在假设选择算法选择 B 来生成下一个块;然后,B 将在 A 的块之上生成下一个块,并向所有节点广播。d 和 E 将拒绝它,因为前面的块散列将不匹配。由此,D 和 E 将形成不同的链,A、B 和 C 将形成不同的链。A、B 和 C 将拒绝来自 D 和 E 的块,而 D 和 E 将拒绝来自 A、B 和 C 的块。这个问题在节点之间得到解决,因为 A、B 和 C 的区块链比 D 和 E 的区块链更准确;因此,D 和 E 将用 A、B 和 c 持有的区块链替换他们的区块链版本。这两个版本的区块链将具有不同的准确度分数,并且第一个区块链的分数将高于第二个。当 B 广播它的块时,它也将提供它的区块链的分数,并且随着它的分数更高,D 和 E 将已经用 B 的区块链替换了他们的区块链。冲突就是这样解决的。使用(U128_max * BLOCK_NUMBER_OF_LATEST_BLOCK - (UNIX_TIMESTAMP_OF_LATEST_BLOCK / BLOCK_TIME))计算区块链的连锁分数。链首先根据长度评分(块越多越好)。对于等长的链,选择最后一个块较旧的链。

你可以在https://github.com/paritytech/parity/wiki/Aura更深入地了解光环。

运行奇偶校验

奇偶校验需要 Rust 版本 1.16.0 来构建。建议通过 rustup 安装 Rust。

安装铁锈

如果你还没有 rustup,可以这样安装。

Linux 操作系统

在基于 Linux 的操作系统上,运行以下命令:

curl https://sh.rustup.rs -sSf | sh

奇偶校验还要求安装gccg++libssl-dev / openssllibudev-devpkg-config软件包。

x 是什么

在 OS X 上,运行以下命令:

curl https://sh.rustup.rs -sSf | sh

对等也需要铿锵。Clang 自带 Xcode 命令行工具,也可以用自制软件安装。

Windows 操作系统

请确保您安装了支持 C++的 Visual Studio 2015。接下来,从https://static . rust-lang . org/rustup/dist/x86 _ 64-PC-windows-msvc/rust up-init . exe下载并运行 rust up 安装程序,启动“VS2015 x64 原生工具命令提示符”,使用以下命令安装并设置msvc工具链:

rustup default stable-x86_64-pc-windows-msvc

下载、安装和运行奇偶校验

现在,一旦您在操作系统上安装了 rust,您就可以运行这个简单的一行命令来安装奇偶校验:

cargo install --git https://github.com/paritytech/parity.git parity

要检查是否安装了奇偶校验,请运行以下命令:

parity --help

如果奇偶校验安装成功,您将看到子命令和选项列表。

创建专用网络

现在是时候成立我们的区块链财团了。我们将创建两个使用 Aura for consensus 相互连接的验证节点。我们将在同一台计算机上设置两者。

创建帐户

首先,打开两个 shell 窗口。第一个用于第一个验证器,第二个用于第二个验证器。第一个节点将包含两个帐户,第二个节点将包含一个帐户。第一个节点的第二个帐户将被分配给某个初始以太,这样网络将有一些以太。

在第一个 shell 中,运行该命令两次:

parity account new -d ./validator0 

两次都会要求你输入密码。现在只需为两个帐户输入相同的密码。

在第二个 shell 中,只运行一次该命令:

parity account new  -d ./validator1 

和之前一样,输入密码。

创建规范文件

每个网络的节点共享一个公共规范文件。这个文件告诉节点关于 genesis 块的信息,验证者是谁,等等。我们将创建一个智能契约,它将包含验证器列表。有两种类型的验证器契约:非报告契约和报告契约。我们只需要提供一个。

不同之处在于,非报告契约仅返回验证器列表,而报告契约可以对良性行为(良性不当行为可能只是没有从指定的验证器接收块)和恶意不当行为(恶意不当行为将为同一步骤释放两个不同的块)采取行动。

非报告合同至少应具有以下接口:

{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"","type":"address[]"}],"payable":false,"type":"function"}

将在每个块上调用getValidators函数来确定当前列表。然后,交换规则由实现该方法的协定来确定。

报告合同至少应具有以下接口:

[ 
    {"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"","type":"address[]"}],"payable":false,"type":"function"}, 
    {"constant":false,"inputs":[{"name":"validator","type":"address"}],"name":"reportMalicious","outputs":[],"payable":false,"type":"function"}, 
    {"constant":false,"inputs":[{"name":"validator","type":"address"}],"name":"reportBenign","outputs":[],"payable":false,"type":"function"} 
]

当存在良性或恶意行为时,共识引擎分别调用reportBenignreportMalicious函数。

让我们创建一个报告契约。下面是一个基本的例子:

contract ReportingContract { 
   address[] public validators = [0x831647ec69be4ca44ea4bd1b9909debfbaaef55c, 0x12a6bda0d5f58538167b2efce5519e316863f9fd]; 
   mapping(address => uint) indices; 
   address public disliked; 

   function ReportingContract() { 
       for (uint i = 0; i < validators.length; i++) { 
           indices[validators[i]] = i; 
       } 
   } 

   // Called on every block to update node validator list. 
    function getValidators() constant returns (address[]) { 
      return validators; 
   } 

   // Expand the list of validators. 
   function addValidator(address validator) { 
      validators.push(validator); 
   } 

   // Remove a validator from the list. 
   function reportMalicious(address validator) { 
      validators[indices[validator]] = validators[validators.length-1]; 
      delete indices[validator]; 
      delete validators[validators.length-1]; 
      validators.length--; 
   } 

   function reportBenign(address validator) { 
       disliked = validator; 
   } 
}

这段代码是不言自明的。确保在 validators 数组中用 validator 1 和 validator 2 节点的第一个地址替换这些地址,因为我们将使用这些地址进行验证。现在用你觉得舒服的任何东西来编译前面的契约。

现在让我们创建规范文件。创建一个名为spec.json的文件,并将以下代码放入其中:

{ 
    "name": "ethereum", 
    "engine": { 
        "authorityRound": { 
            "params": { 
               "gasLimitBoundDivisor": "0x400", 
               "stepDuration": "5", 
               "validators" : { 
               "contract": "0x0000000000000000000000000000000000000005" 
                } 
            } 
        } 
    }, 
    "params": { 
        "maximumExtraDataSize": "0x20", 
        "minGasLimit": "0x1388", 
        "networkID" : "0x2323" 
    }, 
    "genesis": { 
      "seal": { 
       "authorityRound": { 
         "step": "0x0", 
          "signature": "0x00000000000000000000000000000000000000000
             000000000000000000000000000000000000000000000000000000
                00000000000000000000000000000000000" 
            } 
        }, 
        "difficulty": "0x20000", 
        "gasLimit": "0x5B8D80" 
    }, 
    "accounts": { 
        "0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, 
        "0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, 
        "0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, 
        "0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, 
        "0x0000000000000000000000000000000000000005": { "balance": "1", "constructor" : "0x606060405260406040519081016040528073831647" }, 
        "0x004ec07d2329997267Ec62b4166639513386F32E": { "balance": "10000000000000000000000" } 
    } 
}

以下是上述文件的工作原理:

  • engine属性用于设置共识协议和协议特定的参数。这里发动机是authorityRound,是光环。gasLimitBoundDivisor决定气体极限调节,具有通常的ethereum值。在validators属性中,我们有一个contract属性,是上报合同的地址。stepDuration是以秒为单位的阻塞时间。
  • params属性中,只有网络 ID 是重要的;其他是所有链条的标准。
  • genesis有一些authorityRound共识的标准值。
  • accounts用于列出网络中存在的初始账户和合同。前四个是标准以太坊内置合约;这些应包括在内,以便使用可靠的合同写作语言。第五个是举报合同。确保用constructor参数中的字节码替换字节码。最后一个帐户是我们在 validator 1 shell 中生成的第二个帐户。它用于向网络提供以太网。用你的地址替换这个地址。

在我们继续之前,创建另一个名为node.pwds的文件。在该文件中,放置您创建的帐户的密码。验证者将使用该文件来解锁帐户以签署块。

启动节点

现在,我们已经具备了启动验证节点的所有基本要求。在第一个 shell 中,运行以下命令启动第一个验证节点:

parity  --chain spec.json -d ./validator0 --force-sealing --engine-signer "0x831647ec69be4ca44ea4bd1b9909debfbaaef55c" --port 30300 --jsonrpc-port 8540 --ui-port 8180 --dapps-port 8080 --ws-port 8546 --jsonrpc-apis web3,eth,net,personal,parity,parity_set,traces,rpc,parity_accounts --password "node.pwds"

以下是上述命令的工作方式:

  • --chain用于指定规范文件的路径。
  • -d用于指定数据目录。
  • --force-sealing确保即使没有事务也能生成块。
  • --engine-signer用于指定节点签名块的地址,即验证器的地址。如果恶意授权是可能的,则建议--force-sealing;这将确保正确的链是最长的。确保将地址更改为您生成的地址,也就是在这个 shell 上生成的第一个地址。
  • --password用于指定密码文件。

在第二个 shell 中,运行以下命令启动第二个验证节点:

parity  --chain spec.json -d ./validator1 --force-sealing --engine-signer "0x12a6bda0d5f58538167b2efce5519e316863f9fd" --port 30301 --jsonrpc-port 8541 --ui-port 8181 --dapps-port 8081 --ws-port 8547 --jsonrpc-apis web3,eth,net,personal,parity,parity_set,traces,rpc,parity_accounts --password "/Users/narayanprusty/Desktop/node.pwds" 

在这里,确保将地址更改为您自己生成的地址,也就是在这个 shell 上生成的地址。

连接节点

最后,我们需要连接两个节点。打开一个新的 shell 窗口,并运行以下命令来查找连接到第二个节点的 URL:

curl --data '{"jsonrpc":"2.0","method":"parity_enode","params":[],"id":0}' -H "Content-Type: application/json" -X POST localhost:8541

您将得到这样的输出:

{"jsonrpc":"2.0","result":"enode://7bac3c8cf914903904a408ecd71635966331990c5c9f7c7a291b531d5912ac3b52e8b174994b93cab1bf14118c2f24a16f75c49e83b93e0864eb099996ec1af9@[::0.0.1.0]:30301","id":0}

现在运行这个命令,将enode URL 中的编码 URL 和 IP 地址替换为 127.0.0.1:

curl --data '{"jsonrpc":"2.0","method":"parity_addReservedPeer","params":["enode://7ba..."],"id":0}' -H "Content-Type: application/json" -X POST localhost:8540

您应该得到以下输出:

{"jsonrpc":"2.0","result":true,"id":0}

节点应该在控制台中指示 0/1/25 对等体,这意味着它们相互连接。这是一张参考图片:

许可和隐私

我们看到了奇偶校验如何解决速度和安全性问题。奇偶校验目前不提供任何特定于许可和隐私的东西。让我们看看如何在奇偶校验中实现这一点:

  1. 许可:通过配置每个节点的服务器只允许来自特定 IP 地址的连接,奇偶校验网络可以实施许可来决定谁可以加入,谁不可以加入。即使 IP 地址没有被阻止,要连接到网络中的一个节点,一个新节点将需要一个 enode 地址,这是我们前面看到的,这是不可猜测的。所以默认情况下,有一个基本的保护。但是没有任何强制措施。网络中的每个节点都必须在它的末端关注这一点。对于谁可以创建块和谁不可以创建块的类似许可可以通过智能合约来完成。最后,节点可以发送哪种类型的事务目前是不可配置的。

  2. 身份隐私:有一种技术可以通过仍然启用所有权检查来实现身份隐私。在设置所有权时,所有者需要指定非确定性非对称加密的公钥。每当它希望所有权检查通过时,它将提供加密形式的通用文本,该文本将由合同解密,并查看该帐户是否是所有者。合同应该确保相同的加密数据不会被检查两次。

  3. 数据隐私:如果您使用区块链只是为了存储数据,您可以使用对称加密来加密数据,并与您希望看到数据的人存储和共享密钥。但是对加密数据的操作是不可能的。如果你需要对输入数据进行操作,同时又能获得隐私,那么双方必须建立一个完全不同的区块链网络。

摘要

总的来说,在这一章中,我们学习了如何使用奇偶校验,aura 如何工作,以及一些在奇偶校验中实现许可和隐私的技巧。现在,您必须有足够的信心,至少为使用区块链的财团建立一个概念验证。现在,您可以继续探索其他解决方案,如 Hyperledger 1.0 和区块链建筑联合会的 quorum。目前,以太坊官方正在致力于制作更适合财团的;因此,密切关注各种区块链信息来源,了解市场上出现的任何新情况。


我们一直在努力

apachecn/AiLearning

【布客】中文翻译组