HyperLedger链码学习笔记

[toc] # 主要内容 HyperLedger 1.4 版本链码开发学习
  • 深入理解HP架构
  • 了解HP基础概念
  • 入门链码开发

最终目的:能够下到HP底层代码

参考内容

HP 1.4官方文档:https://hyperledger-fabric.readthedocs.io/zh_CN/release-1.4/whatis.html#

优客学院 基础培训(1、2、3)学习总结

存在问题

npm install 问题

  • npm ERR! Error: EACCES: permission denied, access

sudo npm install –unsafe-perm=true –save-dev grunt

  • NPM Error:gyp: No Xcode or CLT version detected!

sudo rm -rf $(xcode-select -print-path)

xcode-select –install

票据链码 Commercial Paper (入门示例)

概念

链码

链码是一种,承载HP网络中代码的容器,链码安装在容器上,并可进行实例化。

智能合约可以在链码容器内被定义,当在某个通道上安装并实例化一个链码的后,链码容器中的所有只能合约都是可用的。

一般来说一个链码里推荐值定义一份智能合约。如果这些智能合约类似,也可以被定义在一起。

如下该合约在构造函数里显式的指定了合约名:

1
2
3
4
5
6
class CommercialPaperContract extends Contract {

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

如何调用一份实例化好的链码

1
2
3
4
5
6
7
8
9
10
11
//获取调用的智能合约所在的网络
const network = await gateway.getNetwork(`papernet`);

//在该网络里,指定链码以及链码上的智能合约
const contract = await network.getContract('papercontract', 'org.papernet.commercialpaper');

//定义在链码里的第一个合约会被视作默认合约,也可以通过不指定合约的方式调用。
//const contract = await network.getContract('papercontract');

//调用该合约通用事务提交接口(需要背书),具体方法为issue
const issueResponse = await contract.submitTransaction('issue', 'MagnetoCorp', '00001', '2020-05-31', '2020-11-30', '5000000');

链码命名空间

同一个链码下的所有智能合约,共享同一份命名空间和同一个世界状态,同时共享一个数据库。所以存在吧业务类型相似的合约放在一份链码中的场景。例如债券链码中含有美元债券合约和人民币债券合约。

处理器/拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CommercialPaperContract extends Contract {

...

async beforeTransaction(ctx) {
// Write the transaction ID as an informational to the console
console.info(ctx.stub.getTxID());
};

async afterTransaction(ctx, result) {
// This handler interacts with the ledger
ctx.stub.cpList.putState(...);
};

async unknownTransaction(ctx) {
// This handler throws an exception
throw new Error('Unknown transaction function');
};

}

连接配置文件和连接选项

连接配置文件和连接选项示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Bring key classes into scope, most importantly Fabric SDK network class
const fs = require('fs');
const yaml = require('js-yaml');
const { FileSystemWallet, Gateway } = require('fabric-network');
const CommercialPaper = require('../contract/lib/paper.js');

// A wallet stores a collection of identities for use
//const wallet = new FileSystemWallet('../user/isabella/wallet');
const wallet = new FileSystemWallet('../identity/user/isabella/wallet');


const userName = 'User1@org1.example.com';

// Load connection profile; will be used to locate a gateway
let connectionProfile = yaml.safeLoad(fs.readFileSync('../gateway/networkConnection.yaml', 'utf8'));

// Set connection options; identity and wallet
let connectionOptions = {
identity: userName,
//wallet 标识了将要被应用程序上的网关所使用的钱包,钱包是由应用程序指定的
wallet: wallet,
discovery: { enabled:false, asLocalhost: true }
};

// Connect to gateway using application specified parameters
console.log('Connect to Fabric gateway.');

await gateway.connect(connectionProfile, connectionOptions);

// Access PaperNet network
console.log('Use network channel: mychannel.');

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

连接配置文件:

目的:简化应用程序和网络的交互

主要表现为,在与一个组织相关的配置文件里,定义了这个组织有关这个网络的所有网络组建,如peer,ca,order,以及这些组建的一些策略。


连接选项
命令参考官方文档 https://hyperledger-fabric.readthedocs.io/zh_CN/release-1.4/developapps/connectionoptions.html

钱包

一个钱包定义了一组用户身份,,应用程序会从这些身份中选择一个用户来使用,MSP定义了钱包中的身份,是什么身份,对应着这个MSP关联的CA发的证书。身份对应着通道资源的访问权限。

钱包有四种类型:文件系统(使用FileSystemWallet类去管理)、内存、HSM、CouchDB

网关

网关代表应用程序和区块链网络的交互,使其能够专注应用逻辑。应用程序连接到网关,

await gateway.connect(connectionProfile, connectionOptions);

网关包括静态网关和动态网关。动态网关是fabric的默认配置。动态网关配置下,随着网络的改变,服务发现会确保对于应用程序可见网络拓扑的准确性。