Hyperledger Fabric1.4.4开发应用程序-应用程序设计元素

应用程序设计元素

本节详细介绍了Hyperledger Fabric中的客户端应用程序和智能合约开发的关键功能。对功能的深入了解将帮助您设计和实施高效的解决方案。

  • 合约名称
  • 链码名称空间
  • 交易环境
  • 交易处理程序
  • 背书政策
  • 连接配置文件
  • 连接选项
  • 钱包
  • 网关

合约名称

受众:架构师,应用程序和智能合约开发人员,管理员

链码是用于将代码部署到Hyperledger Fabric区块链网络的通用容器。在一个链码中定义了一个或多个相关的智能合约。每个智能合约都有一个在链码中唯一标识它的名称。应用程序使用其合同名称在实例化的链码中访问特定的智能合同。

在本主题中,我们将介绍:

  • 链码如何包含多个智能合约
  • 如何分配智能合约名称
  • 如何通过应用程序使用智能合约
  • 默认智能合约

链码

在“ 开发应用程序”主题中,我们可以看到Fabric SDK如何提供高级编程抽象,以帮助应用程序和智能合约开发人员专注于他们的业务问题,而不是如何与Fabric网络交互的底层细节。

智能合约是高级编程抽象的一个示例,可以在链码容器中定义智能合约。安装并实例化一个链码后,其中的所有智能合约都可用于相应的通道。

Hyperledger Fabric1.4.4开发应用程序-应用程序设计元素_第1张图片
合同链代码

可以在一个链码中定义多个智能合约。每个文件均由其链码中的名称唯一标识。

在上图中,链码A中定义了三个智能合约,而链码B中包含四个智能合约。了解如何使用链码名称完全限定特定的智能合约。

分类帐结构由一组已部署的智能合约定义。这是因为分类帐包含有关网络感兴趣的业务对象(例如PaperNet中的商业票据)的事实,并且这些业务对象通过智能合约中定义的交易功能在其生命周期(例如发行,购买,赎回)中移动。 。

在大多数情况下,一个链码中只会定义一个智能合约。但是,将相关智能合约保持在单个链码中是有意义的。例如,在不同的货币计价的可能有合同的商业票据EuroPaperContractDollarPaperContractYenPaperContract这可能需要保持在它们所部署的通道相互同步。

名称

链码中的每个智能合约均由其合约名称唯一标识。当构造类时,智能合约可以显式分配该名称,或者让Contract该类隐式分配默认名称。

检查papercontract.jschaincode 文件:

class CommercialPaperContract extends Contract {

    constructor() {
        // Unique name when multiple contracts per chaincode file
        super('org.papernet.commercialpaper');
    }

查看CommercialPaperContract构造函数如何将合同名称指定为 org.papernet.commercialpaper。结果是,在papercontract 链码中,此智能合约现在与合约名称相关联 org.papernet.commercialpaper

如果未指定显式合同名称,则将分配默认名称-类的名称。在我们的示例中,默认合同名称为 CommercialPaperContract

仔细选择您的名字。不仅每个智能合约都必须具有唯一的名称,一个精心选择的名字很有启发性。具体来说,建议使用显式的DNS样式命名约定,以帮助组织清晰且有意义的名称。org.papernet.commercialpaper表示PaperNet网络已经定义了标准的商业票据智能合约。

合同名称还有助于消除给定链码中具有相同名称的不同智能合同交易功能的歧义。当智能合约紧密相关时,就会发生这种情况。它们的交易名称将趋于相同。我们可以看到,交易是通过链代码和智能合约名称的组合在渠道内唯一定义的。

合同名称在链码文件中必须唯一。某些代码编辑器将在部署之前检测相同类名的多个定义。无论是否显式或隐式指定具有相同协定名称的多个类,链码都将返回错误。

应用

将链码安装到对等方并在通道上实例化后,应用程序即可访问其中的智能合约:

const network = await gateway.getNetwork(`papernet`);

const contract = await network.getContract('papercontract', 'org.papernet.commercialpaper');

const issueResponse = await contract.submitTransaction('issue', 'MagnetoCorp', '00001', '2020-05-31', '2020-11-30', '5000000');

查看应用程序如何通过该contract.getContract()方法访问智能合约 。该papercontractchaincode名 org.papernet.commercialpaper返回一个contract可用于提交交易与发行商业票据参考 contract.submitTransaction()API。

违约合同

链码中定义的第一个智能合约称为默认 智能合约。默认值很有用,因为链码通常会在其中定义一个智能合约。默认值允许应用程序直接访问这些交易,而无需指定合同名称。

Hyperledger Fabric1.4.4开发应用程序-应用程序设计元素_第2张图片
违约

默认智能合约是链码中定义的第一个合约。

在此图中,CommercialPaperContract是默认的智能合约。即使我们有两个智能合约,默认的智能合约也使我们 前面的示例更容易编写:

const network = await gateway.getNetwork(`papernet`);

const contract = await network.getContract('papercontract');

const issueResponse = await contract.submitTransaction('issue', 'MagnetoCorp', '00001', '2020-05-31', '2020-11-30', '5000000');

之所以可行,papercontract是因为默认的智能合约是, CommercialPaperContract并且它具有issue交易记录。请注意,只能通过显式寻址来调用issue事务中的 事务BondContract。同样,即使cancel交易是独一无二的,因为 BondContract不是默认的智能合同,也必须明确处理。

在大多数情况下,链码将仅包含一个智能合约,因此,对链码进行仔细的命名可以减少开发人员将链码作为概念来考虑的需求。在上面的示例代码中,感觉就像papercontract是一个智能合约。

总之,合同名称是一种简单的机制,可以识别给定链码中的各个智能合约。合同名称使应用程序可以轻松找到特定的智能合同并使用它来访问分类账。

链码名称空间

受众:架构师,应用程序和智能合约开发人员,管理员

链码名称空间允许它保持其世界状态与其他链码分离。具体来说,具有相同链码的智能合约共享对同一世界状态的直接访问,而具有不同链码的智能合约不能直接访问彼此的世界状态。如果智能合约需要访问另一个链码世界状态,则可以通过执行链码到链码的调用来做到这一点。最后,区块链可以包含与不同世界状态相关的交易。

在本主题中,我们将介绍:

  • 命名空间的重要性
  • 什么是Chaincode命名空间
  • 频道和名称空间
  • 如何使用链码名称空间
  • 如何通过智能合约访问世界状态
  • Chaincode名称空间的设计注意事项

动机

命名空间是一个常见的概念。据我们了解,公园街,纽约公园街,西雅图是即使它们具有相同的名称不同的街道。这个城市形成了公园街的命名空间,同时提供了自由和清晰。

在计算机系统中是相同的。命名空间允许不同的用户对共享系统的不同部分进行编程和操作,而不会互相干扰。许多编程语言都有名称空间,因此程序可以自由分配唯一的标识符,例如变量名,而不必担心其他程序会这样做。我们将看到Hyperledger Fabric使用名称空间来帮助智能合约将其分类帐世界状态与其他智能合约分开。

情境

让我们使用下图检查分类帐世界状态如何组织有关业务对象的事实,这些事实对组织中的组织很重要。无论这些对象是商业票据,债券还是车辆登记证,以及它们在其生命周期中的任何位置,都将其维护为分类帐世界状态数据库中的状态。智能合约通过与分类帐(世界状态和区块链)进行交互来管理这些业务对象,在大多数情况下,这将涉及查询或更新分类帐世界状态。

了解分类账世界状态是根据访问智能账本的智能合约的链码进行分区的,这一点至关重要,而这种分区或命名间隔是架构师,管理员和程序员的重要设计考虑因素。

Hyperledger Fabric1.4.4开发应用程序-应用程序设计元素_第3张图片
chaincodens.scenario

分类账世界状态根据访问它的链码分为不同的名称空间。在给定通道内,相同链代码中的智能合约共享相同的世界状态,而不同链代码中的智能合约无法直接访问彼此的世界状态。同样,区块链可以包含与不同链码世界状态相关的交易。

在我们的示例中,我们可以看到在两个不同的链码中定义了四个智能合约,每个合约都在自己的链码容器中。该euroPaperyenPaper智能合同中规定paperschaincode。euroBondyenBond智能合约的情况相似-它们在bonds链码中定义。这种设计可帮助应用程序程序员了解他们使用的是欧元还是日元定价的商业票据或债券,并且由于每种金融产品的规则对于不同的货币并没有真正改变,因此有必要使用相同的链码来管理其部署。

该图还显示了此部署选择的后果。数据库管理系统(DBMS)为papers和和bonds链码以及其中包含的智能合约创建不同的世界状态数据库。并分别保存在不同的数据库中;数据彼此隔离,因此单个世界状态查询(例如)无法访问两个世界状态。据说世界状态根据其链码进行了命名World state A``world state B

请参阅如何包含两个商业文件清单 和。状态和是分别由和合约管理的每份论文的实例。因为它们共享相同的链码名称空间,所以它们的键()在链码名称空间内必须是唯一的,有点像街道名称在城镇中是唯一的。注意,有可能在链代码中编写智能合约,从而对所有商业票据(无论是欧元还是日元)进行汇总计算,因为它们共享相同的名称空间。债券的情况与此类似–它们被保存在 其中,并映射到一个单独的数据库,并且其键必须唯一。world state A``paperListEuro``paperListYen``PAP11``PAP21``euroPaper``yenPaper``PAPxyz``papers``papers``world state B``bonds

同样重要的是,命名空间意味着euroPaperyenPaper直接无法访问,并且和不能直接访问。这种隔离非常有用,因为商业票据和债券是非常不同的金融工具。它们具有不同的属性,并遵循不同的规则。这也意味着和 可能具有相同的键,因为它们位于不同的命名空间中。这很有帮助;它为命名提供了很大的自由度。使用这种自由来有意义地命名不同的业务对象。world state B``euroBond``yenBond``world state A``papers``bonds

最重要的是,我们可以看到区块链与在特定通道中运行的对等实体相关联,并且它包含影响和的交易。那是因为区块链是对等体中最基本的数据结构。可以始终从此区块链重新创建世界状态集,因为它们是区块链交易的累积结果。世界国家有助于简化智能合约并提高其效率,因为它们通常仅需要一个国家的当前值。通过名称空间将世界状态分开可以帮助智能合约将其逻辑与其他智能合约隔离,而不必担心对应于不同世界状态的交易。例如,合同无需担心world state A``world state B``bonds``paper 交易,因为它看不到它们产生的世界状态。

还值得注意的是,对等方,chaincode容器和DBMS在逻辑上都是不同的进程。对等方及其所有chaincode容器始终在物理上独立的操作系统进程中,但是可以根据其类型将DBMS配置为嵌入或独立 。对于LevelDB,DBMS完全包含在同级中,但是对于CouchDB,它是一个单独的操作系统进程。

重要的是要记住,在此示例中,名称空间的选择是业务要求的结果,该业务要求共享不同货币的商业票据,但将它们与债券分开。考虑如何修改名称空间结构以满足业务需求,以使每个金融资产类别保持独立,或共享所有商业票据和债券?

频道

如果对等方加入了多个渠道,则会为每个渠道创建并管理一个新的区块链。而且,每次在新的通道中实例化一个链码时,都会为其创建一个新的世界状态数据库。这意味着通道还与世界状态的链码一起形成一种命名空间。

但是,相同的对等和链码容器过程可以同时加入多个渠道–与区块链和世界状态数据库不同,这些过程不会随着加入的渠道数量而增加。

例如,如果papersbonds链码在新的通道上实例化,将创建一个完全独立的区块链,并创建两个新的世界状态数据库。但是,对等和链码容器不会增加;每个都将连接到多个通道。

用法

让我们使用商业论文示例来说明应用程序如何使用带有名称空间的智能合约。值得注意的是,应用程序与对等方进行通信,并且对等方将请求路由到适当的链码容器,然后容器可以访问DBMS。该路由由图中所示的对等核心组件完成。

这是使用商业票据和债券的应用程序代码,以欧元和日元定价。该代码是不言自明的:

const euroPaper = network.getContract(papers, euroPaper);
paper1 = euroPaper.submit(issue, PAP11);

const yenPaper = network.getContract(papers, yenPaper);
paper2 = yenPaper.submit(redeem, PAP21);

const euroBond = network.getContract(bonds, euroBond);
bond1 = euroBond.submit(buy, BON31);

const yenBond = network.getContract(bonds, yenBond);
bond2 = yenBond.submit(sell, BON41);

查看应用程序如何:

  • 使用 指定链码的API 访问euroPaperyenPaper合同。参见交互点1a2agetContract()``papers
  • 使用指定链码的API 访问euroBondyenBond合同。参见交互点3a4agetContract()``bonds
  • 使用合同将issue交易提交到网络以获取商业票据。参见相互作用点1a。结果产生了以国家为代表的商业票据; 相互作用点1b。该操作在交互点1c被捕获为区块链中的事务。PAP11``euroPaper``PAP11``world state A
  • 使用合同将redeem交易提交到网络以获取商业票据。参见交互点2a。结果产生了以国家为代表的商业票据; 交互点2b。该操作在交互点2c被捕获为区块链中的交易。PAP21``yenPaper``PAP21``world state A
  • 使用 合同将buy交易提交到网络以进行担保。参见相互作用点3a。这导致产生由状态表示的键的在; 相互作用点3b。该操作在交互点3c被捕获为区块链中的交易。BON31``euroBond``BON31``world state B
  • 使用 合同将sell交易提交到网络以进行担保。参见相互作用点4a。这导致产生由状态表示的键的在; 相互作用点 4b。该操作在交互点4c被捕获为区块链中的交易。BON41``yenBond``BON41``world state B

了解智能合约如何与世界状态交互:

  • euroPaperyenPaper合同可以直接访问,但不能直接访问。物理地存储在与链码相对应的数据库管理系统(DBMS)中的数据库中。world state A``world state B``World state A``papers``papers
  • euroBondyenBond合同可以直接访问,但不能直接访问。物理地存储在与链码相对应的数据库管理系统(DBMS)中的数据库中。world state B``world state A``World state B``bonds``bonds

了解区块链如何捕获世界所有州的交易:

  • 互动1C2C对应于交易创建和更新商业票据PAP11PAP21分别。这些都包含在中。world state A
  • 互动3c4c对应于更新债券BON31和的交易 BON41。这些都包含在中。world state B
  • 如果或由于某种原因被销毁,则可以通过重播区块链中的所有交易来重新创建它们。world state A``world state B

跨链码访问

正如我们在示例场景中看到的,euroPaper并且yenPaper 不能直接访问。这是因为我们已经设计了链代码和智能合约,以使这些链代码和世界状态彼此分开保存。但是,让我们假设需要访问。world state B``euroPaper``world state B

为什么会发生这种情况?想象一下,当发行商业票据时,智能合约想要根据具有相似到期日的债券当前收益对票据定价。在这种情况下, euroPaper合同必须能够查询中的债券价格。查看下图,以了解如何构建此交互。world state B

Hyperledger Fabric1.4.4开发应用程序-应用程序设计元素_第4张图片
chaincodens.scenario

链码和智能合约如何通过其链码间接访问另一个世界国家。

注意如何:

  • 该应用程序issueeuroPaper智能合约中提交要发行的交易PAP11。参见互动1a
  • issue事务中的euroPaper智能合同要求的query 事务中的euroBond智能合同。参见相互作用点1b
  • queryeuroBond能检索信息。参见相互作用点1cworld state B
  • 当控制权返回issue交易时,它可以使用响应中的信息对纸张定价并更新信息。参见相互作用点1dworld state A
  • 发行以日元计价的商业票据的控制流程相同。参见交互点2a2b2c2d

使用invokeChaincode() API在链代码之间传递控制。该API将控制权从一个链码传递到另一个链码。

尽管在示例中我们仅讨论了查询事务,但是可以调用智能合约来更新被调用的链码的世界状态。请参阅以下注意事项。

注意事项

  • 通常,每个链码中都将包含一个智能合约。
  • 如果多个智能合约关系密切,则仅应将它们部署在同一链码中。通常,仅当它们共享相同的世界状态时才需要这样做。
  • 链码名称空间提供了不同世界状态之间的隔离。通常,将不相关的数据相互隔离是有意义的。请注意,您不能选择链码名称空间。它由Hyperledger Fabric分配,并直接映射到链码的名称。
  • 为了使使用invokeChaincode()API的链码与链码交互,两个链码必须安装在同一对等体上。
    • 对于仅需要查询被调用链码的世界状态的交互,调用可以在与调用方链码不同的通道中进行。
    • 对于需要更新被调用链码的世界状态的交互,调用必须与调用者链码在同一通道中。

你可能感兴趣的:(Hyperledger Fabric1.4.4开发应用程序-应用程序设计元素)