应用程序开发 - 应用程序
应用程序可以通过将交易提交到账本或查询账本内容来与区块链网络进行交互。本主题涵盖了应用程序如何执行此操作的机制。在我们的方案中,组织使用调用商业票据智能合约中定义的发行,购买和赎回交易的应用程序访问 PaperNet。尽管 MagnetoCorp 发行商业票据的申请是基本的,但它涵盖了所有主要的理解要点。
在本主题中,我们将介绍:
- 调用智能合约的应用程序流程
- 应用程序如何使用钱包和身份
- 应用程序如何使用网关进行连接
- 如何访问特定的网络
- 如何构造交易请求
- 如何提交交易
- 如何处理交易响应
为了帮助你理解,我们将参考 Hyperledger Fabric 随附的商业票据应用程序。你可以 下载它 并 在本地运行它。它是用 JavaScript 和 Java 编写的,但是逻辑是完全独立于语言的,因此你可以轻松地看到发生了什么!(该示例也将适用于 Go。)
1. 基本流程
应用程序使用 Fabric SDK 与区块链网络进行交互。这是应用程序如何调用商业票据智能合约的简化图:
PaperNet 应用程序调用商业票据智能合约以提交发行交易请求。
应用程序必须遵循六个基本步骤才能提交交易:
- 从钱包中选择一个身份
- 连接到网关
- 访问所需的网络
- 构建智能合约的交易请求
- 将交易提交到网络
- 处理回应
你将看到典型的应用程序如何使用 Fabric SDK 执行这六个步骤。你可以在 issue.js 文件中找到应用程序代码。在浏览器中 查看它,如果已下载,则在你喜欢的编辑器中将其打开。花一些时间查看应用程序的整体结构;即使有注释和空格,也只有 100 行代码!
2. 钱包
在 issue.js 的顶部,你将看到两个 Fabric 类被引入范围:
const { FileSystemWallet, Gateway } = require('fabric-network');
你可以在 node SDK 文档 中了解 fabric-network
,但是现在,让我们看看如何将它们用于将 MagnetoCorp 的应用程序连接到 PaperNet。该应用程序使用 Fabric Wallet 类,如下所示:
const wallet = new FileSystemWallet('../identity/user/isabella/wallet');
查看 wallet
如何在本地文件系统中找到 钱包。从钱包中检索到的身份显然适用于使用发行应用程序的名为 Isabella 的用户。钱包包含一组身份 (X.509 数字证书),可用于访问 PaperNet 或任何其他 Fabric 网络。如果你运行本教程,并查看此目录,则将看到 Isabella 的身份凭证。
想象一下一个 钱包,里面装有政府身份证,驾驶执照或 ATM 卡的数字等效物。其中的 X.509 数字证书将使持有者与组织相关联,从而使他们具有网络通道中的权利。例如,Isabella 可能是 MagnetoCorp 的管理员,这可能赋予她比其他用户 (DigiBank 的 Balaji) 更多的特权。此外,智能合约可以使用 交易上下文 在智能合约处理期间检索此身份。
另请注意,钱包不持有任何形式的现金或代币 - 它们持有身份。
3. 网关
第二个关键类是 Fabric 网关。最重要的是,网关 标识一个或多个提供对网络访问权限的对端节点 - 在我们的示例中为 PaperNet。查看 issue.js 如何连接到其网关:
await gateway.connect(connectionProfile, connectionOptions);
gateway.connect()
有两个重要参数:
- connectionProfile:连接配置文件 的文件系统位置,该连接配置文件将一组对端节点标识为通往 PaperNet 的网关
- connectionOptions:一组用于控制 issue.js 与 PaperNet 交互方式的选项
了解客户端应用程序如何使用网关将自身与网络拓扑隔离,这可能会发生变化。网关负责使用 连接配置文件 和 连接选项 将交易提案发送到网络中正确的对端节点。
花一些时间检查连接配置 文件 ./gateway/connectionProfile.yaml
。它使用 YAML,使其易于阅读。
它已加载并转换为 JSON 对象:
let connectionProfile = yaml.safeLoad(file.readFileSync('./gateway/connectionProfile.yaml', 'utf8'));
目前,我们只对 profile 部分的 channels:
和 peers:
感兴趣:(我们对详细信息进行了一些修改,以更好地说明正在发生的事情。)
channels:
papernet:
peers:
peer1.magnetocorp.com:
endorsingPeer: true
eventSource: true
peer2.digibank.com:
endorsingPeer: true
eventSource: true
peers:
peer1.magnetocorp.com:
url: grpcs://localhost:7051
grpcOptions:
ssl-target-name-override: peer1.magnetocorp.com
request-timeout: 120
tlsCACerts:
path: certificates/magnetocorp/magnetocorp.com-cert.pem
peer2.digibank.com:
url: grpcs://localhost:8051
grpcOptions:
ssl-target-name-override: peer1.digibank.com
tlsCACerts:
path: certificates/digibank/digibank.com-cert.pem
查看 channel:
如何识别 PaperNet:
网络通道及其两个对端节点。 MagnetoCorp 拥有 peer1.magenetocorp.com
,而 DigiBank 拥有 peer2.digibank.com
,并且两者都具有背书对端节点的作用。通过 peers:
键链接到这些对端节点,其中包含有关如何连接到它们的详细信息,包括它们各自的网络地址。
连接配置文件包含很多信息 - 不仅包括对端节点信息 - 而且还包含网络通道,网络交易排序器,组织和 CA,因此,如果你不了解所有信息,请不要担心!
现在,我们将注意力转向 connectionOptions
对象:
let connectionOptions = {
identity: userName,
wallet: wallet
}
了解如何指定身份 (userName
) 以及钱包 (wallet
) 用于连接到网关。这些是在代码的前面分配的值。
应用程序还可以使用其他 连接选项 来指示 SDK 代表其智能操作。例如:
let connectionOptions = {
identity: userName,
wallet: wallet,
eventHandlerOptions: {
commitTimeout: 100,
strategy: EventStrategies.MSPID_SCOPE_ANYFORTX
},
}
在这里,commitTimeout
告诉 SDK 等待 100 秒,以了解交易是否已提交。strategy:EventStrategies.MSPID_SCOPE_ANYFORTX
指定 SDK 可以在单个 MagnetoCorp 对端节点确认交易后通知应用程序,而strategy:EventStrategies.NETWORK_SCOPE_ALLFORTX
则要求 MagnetoCorp 和 DigiBank 的所有对端节点确认交易。
如果你愿意,请 阅读更多 有关连接选项如何允许应用程序指定面向目标的行为的信息,而不必担心如何实现。
4. 网络通道
网关 connectionProfile.yaml
中定义的对端节点使 issue.js 可以访问 PaperNet。因为这些对端节点可以加入多个网络通道,所以网关实际上为应用程序提供了对多个网络通道的访问权限!
查看应用程序如何选择特定通道:
const network = await gateway.getNetwork('PaperNet');
从此时起,network
将提供对 PaperNet 的访问。此外,如果应用程序同时希望访问另一个网络,BondNet
,则很容易:
const network2 = await gateway.getNetwork('BondNet');
现在,我们的应用程序可以与 PaperNet
同时访问第二个网络 BondNet
!
我们在这里可以看到 Hyperledger Fabric 的强大功能 - 应用程序可以通过连接到多个网关对端节点来参与网络中的网络,每个网关对端节点都连接到多个网络通道。根据 gateway.connect()
中提供的钱包身份,应用程序将在不同的通道中具有不同的权限。
5. 构造请求
该应用程序现在准备发行商业票据。为此,它将使用 CommercialPaperContract,并且再次使用它非常简单地访问此智能合约:
const contract = await network.getContract('papercontract', 'org.papernet.commercialpaper');
请注意,该应用程序如何提供名称 – papercontract
– 和明确的合约名称:org.papernet.commercialpaper
!我们将看到 合约名称 如何从包含许多合约的 papercontract.js
链码文件中挑选出一个合约。在 PaperNet 中,papercontract.js
的安装和实例化名为 papercontract
,如果你感兴趣的话,请阅读如何安装和实例化包含多个智能合约的链码。
如果我们的应用程序同时需要访问 PaperNet 或 BondNet 中的另一个合约,这将很容易:
const euroContract = await network.getContract('EuroCommercialPaperContract');
const bondContract = await network2.getContract('BondContract');
在这些示例中,请注意我们如何不使用带限定符的合约名称 - 每个文件只有一个智能合约,而 getContract()
将使用找到的第一个合约。
回顾一下 MagnetoCorp 发行第一张商业票据所使用的交易:
Txn = issue
Issuer = MagnetoCorp
Paper = 00001
Issue time = 31 May 2020 09:00:00 EST
Maturity date = 30 November 2020
Face value = 5M USD
现在,我们将此交易提交给 PaperNet!
6. 提交交易
提交交易是对 SDK 的单一方法调用:
const issueResponse = await contract.submitTransaction('issue', 'MagnetoCorp', '00001', '2020-05-31', '2020-11-30', '5000000');
查看 submitTransaction()
参数如何与交易请求的参数匹配。这些值将传递给智能合约中的 issue()
方法,并用于创建新的商业票据。回顾其签名:
async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) {...}
在应用程序发出 submitTransaction()
之后,智能合约可能会立即获得控制权,但事实并非如此。在幕后,SDK使用 connectionOptions
和 connectionProfile
详细信息将交易提案发送到网络中的正确对端节点,在该对端节点可以获取所需的背书。但是应用程序无需担心任何这些 – 只需发出 SubmitTransaction
,SDK 就可以解决一切!
请注意,submitTransaction
API 包括用于侦听交易提交的过程。需要侦听提交,因为没有提交,你将不知道你的交易是否已成功排序,验证并提交到账本。
现在,我们将注意力转移到应用程序如何处理响应上!
7. 处理响应
回想一下 papercontract.js
,发行交易如何返回商业票据响应:`
return paper.toBuffer();
你会注意到一个小怪癖 - 新票据需要先转换为缓冲区,然后才能返回到应用程序中。请注意 issue.js
如何使用类方法 CommercialPaper.fromBuffer()
来将响应缓冲区重新反序列化为商业票据:
let paper = CommercialPaper.fromBuffer(issueResponse);
这允许在描述性完成消息中以自然方式使用票据:
console.log(`${paper.issuer} commercial paper : ${paper.paperNumber} successfully issued for value ${paper.faceValue}`);
了解在应用程序和智能合约中如何使用相同的 paper
类 - 如果你这样构造代码,它将真正有助于提高可读性和重用性。
与交易提案一样,智能合约完成后,应用程序似乎很快就会收到控制权,但事实并非如此。在后台,SDK 管理整个共识过程,并根据策略 connectionOption 通知应用程序完成。如果你对 SDK 的基本功能感兴趣,请阅读详细的 交易流程。
就是这样!在本主题中,你已通过研究 MagnetoCorp 的应用程序如何在 PaperNet 中发布新的商业票据来理解如何从示例应用程序中调用智能合约。现在,检查关键账本和智能合约数据结构是根据其背后的 体系结构主题 设计的。
Reference
- Docs » Developing Applications » Application, https://hyperledger-fabric.readthedocs.io/en/release-1.4/developapps/application.html
- Docs » Getting Started » Install Samples, Binaries and Docker Images, https://hyperledger-fabric.readthedocs.io/en/release-1.4/install.html
- Docs » Tutorials » Commercial paper tutorial, https://hyperledger-fabric.readthedocs.io/en/release-1.4/tutorial/commercial_paper.html
- https://fabric-sdk-node.github.io/master/module-fabric-network.html
- Docs » Developing Applications » Application design elements » Wallet, https://hyperledger-fabric.readthedocs.io/en/release-1.4/developapps/wallet.html
- Docs » Developing Applications » Application design elements » Gateway, https://hyperledger-fabric.readthedocs.io/en/release-1.4/developapps/gateway.html
- Docs » Developing Applications » Application design elements » Connection Profile, https://hyperledger-fabric.readthedocs.io/en/release-1.4/developapps/connectionprofile.html
- Docs » Developing Applications » Application design elements » Connection Profile, https://hyperledger-fabric.readthedocs.io/en/release-1.4/developapps/connectionprofile.html
- Docs » Developing Applications » Application design elements » Connection Options, https://hyperledger-fabric.readthedocs.io/en/release-1.4/developapps/connectionoptions.html
- https://github.com/hyperledger/fabric-samples/blob/master/commercial-paper/organization/magnetocorp/gateway/networkConnection.yaml
- http://yaml.org/spec/1.2/spec.html#Preview
- Docs » Developing Applications » Application design elements » Contract names, https://hyperledger-fabric.readthedocs.io/en/release-1.4/developapps/contractname.html
- Docs » Developing Applications » Process and Data Design, https://hyperledger-fabric.readthedocs.io/en/release-1.4/developapps/architecture.html
项目源代码
项目源代码会逐步上传到 Github,地址为 https://github.com/windstamp。
Contributor
- Windstamp, https://github.com/windstamp