Hyperledger Fabric v1.4(LTS) 系列(5.5):Developing Applications-Application

Hyperledger Fabric v1.4(LTS) 系列(5.5):Developing Applications-Application# Application

Audience: Architects, Application and smart contract developers

An application can interact with a blockhain network by submitting transactions
to a ledger or querying ledger content. This topic covers the mechanics of how
an application does this; in our scenario, organizations access PaperNet using
applications which invoke issue, sell and redeem transactions
defined in a commercial paper smart contract. Even though MagnetoCorp’s
application to issue a commercial paper is basic, it covers all the major points
of understanding.

应用可以通过向账本提交交易或查询账本内容来与区块链网络交互。本节介绍这些动作的机制。

In this topic, we’re going to cover:

包括 基本流程、钱包、网关、通道、构造请求、提交交易、处理响应。

To help your understanding, we’ll make reference to the commercial paper sample
application provided with Hyperledger Fabric. You can download
it
and run it locally. It
is written in JavaScript, but the logic is quite language independent, so you’ll
be easily able to see what’s going on! (The sample will become available for
Java and GOLANG as well.)

我们以Fabric里的商票示例来说明。

Basic Flow

An application interacts with a blockchain network using the Fabric SDK. Here’s
a simplified diagram of how an application invokes a commercial paper smart
contract:

下图显示应用如何调用商票智能合约。

[外链图片转存失败(img-fyAmcTL3-1564061764799)(https://hyperledger-fabric.readthedocs.io/en/release-1.4/_images/develop.diagram.3.png)] A PaperNet application invokes
the commercial paper smart contract to submit an issue transaction request.

An application has to follow six basic steps to submit a transaction:

  • Select an identity from a wallet
  • Connect to a gateway
  • Access the desired network
  • Construct a transaction request for a smart contract
  • Submit the transaction to the network
  • Process the response

应用通过六步提交交易。

You’re going to see how a typical application performs these six steps using the
Fabric SDK. You’ll find the application code in the issue.js file. View
it

in your browser, or open it in your favourite editor if you’ve downloaded it.
Spend a few moments looking at the overall structure of the application; even
with comments and spacing, it’s only 100 lines of code!
可以通过issue.js 中的代码看到典型的应用执行这六步的过程,只有100多行代码。

Wallet

Towards the top of issue.js, you’ll see two Fabric classes are brought
into scope:
issue.js头部引入两个类,FileSystemWallet, Gateway。

const { FileSystemWallet, Gateway } = require('fabric-network');

You can read about the fabric-network classes in the
node SDK documentation, but for
now, let’s see how they are used to connect MagnetoCorp’s application to
PaperNet. The application uses the Fabric Wallet class as follows:
在node的文档中有fabric-network的文档,现在看应用如何连接到PaperNet。应用先使用Wallet类。

const wallet = new FileSystemWallet('../identity/user/isabella/wallet');

See how wallet locates a wallet in the local filesystem. The
identity retrieved from the wallet is clearly for a user called Isabella, who is
using the issue application. The wallet holds a set of identities – X.509
digital certificates – which can be used to access PaperNet or any other Fabric
network. If you run the tutorial, and look in this directory, you’ll see the
identity credentials for Isabella.
wallet类在本地文件系统定位钱包,从钱包中查询到一个用户lsabella,该用户在使用issue应用。钱包里有多个X.509证书。

Think of a wallet holding the digital equivalents of your
government ID, driving license or ATM card. The X.509 digital certificates
within it will associate the holder with a organization, thereby entitling them
to rights in a network channel. For example, Isabella might be an
administrator in MagnetoCorp, and this could give her more privileges than a
different user – Balaji from DigiBank. Moreover, a smart contract can
retrieve this identity during smart contract processing using the transaction
context
.
钱包里保存了你的多种身份证明,钱包中的X.509证书把持有者和组织关联起来,声明其在网络通道中的权利。

Note also that wallets don’t hold any form of cash or tokens – they hold identities.

Gateway

The second key class is a Fabric Gateway. Most importantly, a gateway identifies one or more peers that provide access to a network – in our case, PaperNet. See how issue.js connects to its gateway:

Gateway,和传统网络中的Gateway定义相通。允许一个或多个节点访问网络。

await gateway.connect(connectionProfile, connectionOptions);

gateway.connect() has two important parameters:

  • connectionProfile: the file system location of a connection profile that identifies a set of peers as a gateway to PaperNet

  • connectionOptions: a set of options used to control how issue.js interacts with PaperNet

连接gateway时有两个重要参数,connectionProfile指定用来认证节点的文件。

See how the client application uses a gateway to insulate itself from the network topology, which might change. The gateway takes care of sending the transaction proposal to the right peer nodes in the network using the connection profile and connection options.

网关隔离应用与可变的网络拓扑。网关负责发送交易提案到网络中正确的节点。

Spend a few moments examining the connection profile ./gateway/connectionProfile.yaml. It uses YAML, making it easy to read.

It was loaded and converted into a JSON object:

let connectionProfile = yaml.safeLoad(file.readFileSync('./gateway/connectionProfile.yaml', 'utf8'));

Right now, we’re only interested in the channels: and peers: sections of the profile: (We’ve modified the details slightly to better explain what’s happening.)

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

See how channel: identifies the PaperNet: network channel, and two of its peers. MagnetoCorp has peer1.magenetocorp.com and DigiBank has peer2.digibank.com, and both have the role of endorsing peers. Link to these peers via the peers: key, which contains details about how to connect to them, including their respective network addresses.

这里channel定义了PaperNet及其两个节点。peers定义了这两个节点的连接信息。

The connection profile contains a lot of information – not just peers – but network channels, network orderers, organizations, and CAs, so don’t worry if you don’t understand all of it!

Let’s now turn our attention to the connectionOptions object:

let connectionOptions = {
  identity: userName,
  wallet: wallet
}

See how it specifies that identity, userName, and wallet, wallet, should be used to connect to a gateway. These were assigned values earlier in the code.

连接gateway时要用到userName和wallet。

There are other connection options which an application could use to instruct the SDK to act intelligently on its behalf. For example:

let connectionOptions = {
  identity: userName,
  wallet: wallet,
  eventHandlerOptions: {
    commitTimeout: 100,
    strategy: EventStrategies.MSPID_SCOPE_ANYFORTX
  },
}

Here, commitTimeout tells the SDK to wait 100 seconds to hear whether a transaction has been committed. And strategy: EventStrategies.MSPID_SCOPE_ANYFORTX specifies that the SDK can notify an application after a single MagnetoCorp peer has confirmed the transaction, in contrast to strategy: EventStrategies.NETWORK_SCOPE_ALLFORTX which requires that all peers from MagnetoCorp and DigiBank to confirm the transaction.

connectionOptions里的commitTimeout用来定义等待交易提交的超时时间。strategy可以定义不同的提交状态通知策略。

译注
类似于阿里的分布式事务中的三步提交方法的各个阶段。

If you’d like to, read more about how connection options allow applications to specify goal-oriented behaviour without having to worry about how it is achieved.

Network channel

The peers defined in the gateway connectionProfile.yaml provide issue.js with access to PaperNet. Because these peers can be joined to multiple network channels, the gateway actually provides the application with access to multiple network channels!

因为节点可能属于多个通道,所以gateway实际是提供给应用访问多个通道的能力的,所以连接时要指定通道。

See how the application selects a particular channel:

const network = await gateway.getNetwork('PaperNet');

From this point onwards, network will provide access to PaperNet. Moreover, if the application wanted to access another network, BondNet, at the same time, it is easy:

const network2 = await gateway.getNetwork('BondNet');

Now our application has access to a second network, BondNet, simultaneously with PaperNet!

We can see here a powerful feature of Hyperledger Fabric – applications can participate in a network of networks, by connecting to multiple gateway peers, each of which is joined to multiple network channels. Applications will have different rights in different channels according to their wallet identity provided in gateway.connect().

这里可以看到,通过连接到多个网关节点,应用可以在多个网络间协作。

Construct request

The application is now ready to issue a commercial paper. To do this, it’s going to use CommercialPaperContract and again, its fairly straightforward to access this smart contract:
现在准备用CommercialPaperContract合约来issue一个商票。

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

Note how the application provides a name – papercontract – and an explicit contract name: org.papernet.commercialpaper! We see how a contract name picks out one contract from the papercontract.js chaincode file that contains many contracts. In PaperNet, papercontract.js was installed and instantiated with the name papercontract, and if you’re interested, read how to install and instantiate a chaincode containing multiple smart contracts.
应用提供了一个名称papercontract和一个明确的合约名称org.papernet.commercialpaper。链码文件中有多个合约可供选择。

If our application simultaneously required access to another contract in PaperNet or BondNet this would be easy:

const euroContract = await network.getContract('EuroCommercialPaperContract');

const bondContract = await network2.getContract('BondContract');

In these examples, note how we didn’t use a qualifying contract name – we have only one smart contract per file, and getContract() will use the first contract it finds.

Recall the transaction MagnetoCorp uses to issue its first commercial paper:

Txn = issue
Issuer = MagnetoCorp
Paper = 00001
Issue time = 31 May 2020 09:00:00 EST
Maturity date = 30 November 2020
Face value = 5M USD

Let’s now submit this transaction to PaperNet!

Submit transaction

Submitting a transaction is a single method call to the SDK:
提交交易。

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

See how the submitTransaction() parameters match those of the transaction request. It’s these values that will be passed to the issue() method in the smart contract, and used to create a new commercial paper. Recall its signature:

async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) {...}

It might appear that a smart contract receives control shortly after the application issues submitTransaction(), but that’s not the case. Under the covers, the SDK uses the connectionOptions and connectionProfile details to send the transaction proposal to the right peers in the network, where it can get the required endorsements. But the application doesn’t need to worry about any of this – it just issues submitTransaction and the SDK takes care of it all!
看起来智能合约在应用提交交易后即获得控制权,实际上在这个表面之下,SDK按照连接参数把交易发给正确的节点并背书。但应用不用管这些。

Note that the submitTransaction API includes a process for listening for transaction commits. Listening for commits is required because without it, you will not know whether your transaction has successfully been orderered, validated, and committed to the ledger.
submitTransaction API包括了监听交易提交的处理过程。

Let’s now turn our attention to how the application handles the response!

Process response

Recall from papercontract.js how the issue transaction returns a commercial paper response:
我们看看issue获得的返回值。

return paper.toBuffer();

You’ll notice a slight quirk – the new paper needs to be converted to a buffer before it is returned to the application. Notice how issue.js uses the class method CommercialPaper.fromBuffer() to rehydrate the response buffer as a commercial paper:
返回前票据要转换为缓存,CommercialPaper.fromBuffer() 再把响应缓存转为商票。

let paper = CommercialPaper.fromBuffer(issueResponse);

This allows paper to be used in a natural way in a descriptive completion message:

console.log(`${paper.issuer} commercial paper : ${paper.paperNumber} successfully issued for value ${paper.faceValue}`);

See how the same paper class has been used in both the application and smart contract – if you structure your code like this, it’ll really help readability and reuse.

As with the transaction proposal, it might appear that the application receives control soon after the smart contract completes, but that’s not the case. Under the covers, the SDK manages the entire consensus process, and notifies the application when it is complete according to the strategy connectionOption. If you’re interested in what the SDK does under the covers, read the detailed transaction flow.
和上边提交交易后合约获得控制权一样,合约完成后看起来应用立即获得了控制权。在这之下,还有SDK做了很多事情。

That’s it! In this topic you’ve understood how to call a smart contract from a sample application by examining how MagnetoCorp’s application issues a new commercial paper in PaperNet. Now examine the key ledger and smart contract data structures are designed by in the architecture topic behind them.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值