受众:架构师,应用程序和智能合约开发人员
应用程序可以通过将交易提交到分类账或查询分类账内容来与区块链网络进行交互。本主题涵盖了应用程序如何执行此操作的机制。在我们的方案中,组织使用调用商业票据智能合约中定义的发行,购买和赎回交易的应用程序访问PaperNet 。尽管MagnetoCorp发行商业票据的申请是基本的,但它涵盖了所有主要的理解要点。
在本主题中,我们将介绍:
为了帮助您理解,我们将参考Hyperledger Fabric随附的商业纸样应用程序。您可以下载它并在本地运行它。它是用JavaScript和Java编写的,但是逻辑是完全独立于语言的,因此您可以轻松地看到发生了什么!(该示例也将适用于Go。)
基本流程
应用程序使用Fabric SDK与区块链网络进行交互。这是应用程序如何调用商业票据智能合约的简化图:
PaperNet应用程序调用商业票据智能合约以提交发行交易请求。
申请必须遵循六个基本步骤才能提交交易:
- 从钱包中选择一个身份
- 连接到网关
- 访问所需的网络
- 构建智能合约的交易请求
- 将交易提交到网络
- 处理回应
您将看到典型的应用程序如何使用Fabric SDK执行这六个步骤。您将在issue.js
文件中找到应用程序代码。 在浏览器中查看它,如果已下载,则在您喜欢的编辑器中将其打开。花一些时间查看应用程序的整体结构;即使有注释和空格,也只有100行代码!
钱包
在的顶部issue.js
,您将看到两个Fabric类进入了作用域:
const { FileSystemWallet, Gateway } = require('fabric-network');
您可以fabric-network
在node SDK文档中阅读有关这些类的 信息,但是现在,让我们看看如何使用它们将MagnetoCorp的应用程序连接到PaperNet。该应用程序使用Fabric Wallet类,如下所示:
const wallet = new FileSystemWallet('../identity/user/isabella/wallet');
查看如何在本地文件系统中wallet
找到钱包。从钱包中检索到的身份显然适用于正在使用该issue
应用程序的名为Isabella的用户。钱包包含一组身份(X.509数字证书),可用于访问PaperNet或任何其他Fabric网络。如果您运行本教程,并查看此目录,则将看到Isabella的身份凭证。
想象一下一个钱包,里面装有政府身份证,驾驶执照或ATM卡的数字等效物。其中的X.509数字证书将使持有者与组织相关联,从而使他们具有网络通道中的权利。例如,Isabella
可能是MagnetoCorp的管理员,这可能给她比Balaji
来自DigiBank 的其他用户更多的特权。此外,智能合约可以使用交易上下文在智能合约处理期间检索此身份。
还要注意,钱包不持有任何形式的现金或代币-它们持有身份。
网关
第二个关键类是结构网关。最重要的是, 网关标识一个或多个提供对网络访问权限的对等点-在我们的示例中为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'));
目前,我们仅对个人资料的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秒以了解事务是否已提交。并指定SDK可以在单个MagnetoCorp对等方确认交易后通知应用程序,而相反,这要求MagnetoCorp和DigiBank的所有对等方确认交易。strategy: EventStrategies.MSPID_SCOPE_ANYFORTX``strategy: EventStrategies.NETWORK_SCOPE_ALLFORTX
如果您愿意,请阅读更多有关连接选项如何允许应用程序指定面向目标的行为的信息,而不必担心如何实现。
网络渠道
在网关上定义的同龄人connectionProfile.yaml
提供 issue.js
与接入PaperNet。因为这些对等方可以加入多个网络通道,所以网关实际上为应用程序提供了对多个网络通道的访问权限!
查看应用程序如何选择特定频道:
const network = await gateway.getNetwork('PaperNet');
从那时起,network
将提供对PaperNet的访问。此外,如果应用程序要同时访问另一个网络BondNet
,则很容易:
const network2 = await gateway.getNetwork('BondNet');
现在我们的应用程序可以访问到第二网络,BondNet
同时有PaperNet
!
我们可以在这里看到Hyperledger面料的强大的功能-应用程序可以参加一个在网络的网络,通过连接到多个网关同行,每一个连接到多个网络渠道。根据中提供的钱包身份,应用程序将在不同渠道中拥有不同的权利gateway.connect()
。
构造要求
该应用程序现在准备发布商业票据。为此,它将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!
提交交易
提交交易是对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包含用于侦听事务提交的过程。需要侦听提交,因为没有提交,您将不知道您的交易是否已成功排序,验证并提交到分类账。
现在让我们将注意力转移到应用程序如何处理响应上!
流程响应
回想一下发行交易papercontract.js
如何返回商业票据响应:
return paper.toBuffer();
您会注意到一个小怪癖–新的新数据paper
需要在返回到应用程序之前转换为缓冲区。请注意,如何issue.js
使用类方法CommercialPaper.fromBuffer()
为响应缓冲纸补充水分,作为商业论文:
let paper = CommercialPaper.fromBuffer(issueResponse);
这允许paper
在描述性完成消息中以自然的方式使用:
console.log(`${paper.issuer} commercial paper : ${paper.paperNumber} successfully issued for value ${paper.faceValue}`);
了解paper
在应用程序合约和智能合约中如何使用相同的类–如果您像这样构造代码,它将真正帮助提高可读性和重用性。
与交易建议一样,智能合约完成后,应用程序似乎很快就会收到控制权,但事实并非如此。在幕后,SDK管理整个共识过程,并根据strategy
connectionOption 通知应用程序完成。如果您对SDK的幕后操作感兴趣,请阅读详细的 交易流程。
而已!在本主题中,您已经了解了如何通过检查MagnetoCorp的应用程序如何在PaperNet中发布新的商业论文来从示例应用程序中调用智能合约。现在,检查关键分类账和智能合约数据结构是根据其背后的体系结构主题设计的。