系统智能合约代码编写及测试
2019-12-14 本文已影响0人
52hz_55ed
准备代码
创建文件夹
root@wang-virtual-machine:/home/wang# mkdir fish
root@wang-virtual-machine:/home/wang# cd fish
root@wang-virtual-machine:/home/wang/fish# mkdir chaincode
root@wang-virtual-machine:/home/wang/fish# cd chaincode
root@wang-virtual-machine:/home/wang/fish/chaincode# mkdir fishcc
root@wang-virtual-machine:/home/wang/fish/chaincode# cd fishcc/
root@wang-virtual-machine:/home/wang/fish/chaincode/fishcc# npm init
root@wang-virtual-machine:/home/wang/fish/chaincode/fishcc# npm install --save fabric-shim
在fish目录创建index.js
'use strict';
const shim require('fabric-shim');
const util = require('util');
let Chaincode = class {
//初始化智能合约的方法
async Init(stub) {
console.info('=========== Instantiated fabcar chaincode ===========');
return shim.success();
}
async Invoke(stub) {
let ret = stub.getFunctionAndParameters(); //获取函数和参数
console.info(ret);
let method = this[ret.fcn];
if (!method) {
console.error('找不到要调用的函数,函数名:' + ret.fcn);
throw new Error('找不到要调用的函数,函数名:' + ret.fcn);
}
try {
let payload = await method(stub, ret.params); //直接调用函数,获取返回值
return shim.success(payload);
} catch (err) {
console.log(err);
return shim.error(err);
}
}
async queryFish(stub, args) {
if (args.length != 1) {
throw new Error('错误的调用参数. 实例: FISH01');
}
let fishNumber = args[0];
let fishAsBytes = await stub.getState(fishNumber); //从账本中获取fish的信息,账本是二进制存储的
if (!fishAsBytes || fishAsBytes.toString().length <= 0) {
throw new Error(fishAsBytes + ' 不存在: ');
}
console.log(fishAsBytes.toString());
return fishAsBytes;
}
async initLedger(stub, args) {
console.info('============= 开始 : 初始化账本 ===========');
let fishes = [];
fishes.push({
vessel: "奋进号38A",
location: "67.0006, -70.5476",
timestamp: "1504054225",
holder: "王大壮"
});
fishes.push({
vessel: "光明号66B",
location: "57.9006, -78.3478",
timestamp: "1504054666",
holder: "高大壮"
});
fishes.push({
vessel: "钓鱼岛58B",
location: "77.9034, -75.3455",
timestamp: "1504054888",
holder: "刘胡兰"
});
for (let i = 0; i < fishes.length; i++) {
await stub.putState('FISH' + i, Buffer.from(JSON.stringify(fishes[i])));
console.info('Added <--> ',fishes[i]);
}
console.info('============= 结束 :初始化账本 ===========');
}
async recordFish(stub, args) {
console.info('============= START : record fish ===========');
if (args.length != 5) {
throw new Error('需要5个参数,第0个参数是id,后面的4个参数, vessel, location, timestamp, holder');
}
var fish = {
vessel: args[1],
location: args[2],
timestamp: args[3],
holder: args[4]
};
await stub.putState(args[0], Buffer.from(JSON.stringify(fish)));
console.info('============= END : record fish ===========');
}
async queryAllFish(stub, args) {
let startKey = 'FISH0';
let endKey = 'FISH999';
let iterator = await stub.getStateByRange(startKey, endKey);
let allResults = [];
while (true) {
let res = await iterator.next();
if (res.value && res.value.value.toString()) {
let jsonRes = {};
console.log(res.value.value.toString('utf8'));
jsonRes.Key = res.value.key;
try {
jsonRes.Record = JSON.parse(res.value.value.toString('utf8'));
} catch (err) {
console.log(err);
jsonRes.Record = res.value.value.toString('utf8');
}
allResults.push(jsonRes);
}
if (res.done) {
console.log('end of data');
await iterator.close();
console.info(allResults);
return Buffer.from(JSON.stringify(allResults));
}
}
}
async changeFishHolder(stub, args) {
console.info('============= START : changeFishHolder ===========');
if (args.length != 2) {
throw new Error('参数数量错误,需要两个参数');
}
let fishAsBytes = await stub.getState(args[0]);
let fish = JSON.parse(fishAsBytes);
fish.holder = args[1];
await stub.putState(args[0], Buffer.from(JSON.stringify(fish)));
console.info('============= END : changeFishHolder ===========');
}
}
shim.start(new Chaincode());
##创建网络文件夹
root@wang-virtual-machine:/home/wang/fish# mkdir fishnetwork
创建文件夹存储所有基础的网络配置信息
root@wang-virtual-machine:/home/wang/fish/fishnetwork# mkdir basic-network
配置环境变量
配置msp信息crypto-config.yaml
在fish目录下操作
mkdir fisnetwork
cd fishnetwork
mkdir basic-network
cd basic-network
mkdir crypto-config.yaml
编写crypto-config.yaml
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
# ---------------------------------------------------------------------------
# "OrdererOrgs" - Definition of organizations managing orderer nodes
# ---------------------------------------------------------------------------
OrdererOrgs:
# ---------------------------------------------------------------------------
# Orderer
# ---------------------------------------------------------------------------
- Name: Orderer
Domain: example.com
# ---------------------------------------------------------------------------
# "Specs" - See PeerOrgs below for complete description
# ---------------------------------------------------------------------------
Specs:
- Hostname: orderer
# ---------------------------------------------------------------------------
# "PeerOrgs" - Definition of organizations managing peer nodes
# ---------------------------------------------------------------------------
PeerOrgs:
# ---------------------------------------------------------------------------
# Org1
# ---------------------------------------------------------------------------
- Name: Org1
Domain: org1.example.com
# ---------------------------------------------------------------------------
# "Specs"
# ---------------------------------------------------------------------------
# Uncomment this section to enable the explicit definition of hosts in your
# configuration. Most users will want to use Template, below
#
# Specs is an array of Spec entries. Each Spec entry consists of two fields:
# - Hostname: (Required) The desired hostname, sans the domain.
# - CommonName: (Optional) Specifies the template or explicit override for
# the CN. By default, this is the template:
#
# "{{.Hostname}}.{{.Domain}}"
#
# which obtains its values from the Spec.Hostname and
# Org.Domain, respectively.
# ---------------------------------------------------------------------------
# Specs:
# - Hostname: foo # implicitly "foo.org1.example.com"
# CommonName: foo27.org5.example.com # overrides Hostname-based FQDN set above
# - Hostname: bar
# - Hostname: baz
# ---------------------------------------------------------------------------
# "Template"
# ---------------------------------------------------------------------------
# Allows for the definition of 1 or more hosts that are created sequentially
# from a template. By default, this looks like "peer%d" from 0 to Count-1.
# You may override the number of nodes (Count), the starting index (Start)
# or the template used to construct the name (Hostname).
#
# Note: Template and Specs are not mutually exclusive. You may define both
# sections and the aggregate nodes will be created for you. Take care with
# name collisions
# ---------------------------------------------------------------------------
Template:
Count: 1
# Start: 5
# Hostname: {{.Prefix}}{{.Index}} # default
# ---------------------------------------------------------------------------
# "Users"
# ---------------------------------------------------------------------------
# Count: The number of user accounts _in addition_ to Admin
# ---------------------------------------------------------------------------
Users:
Count: 1
配置组织和排序节点 configtx.yaml
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
---
################################################################################
#
# Profile
#
# - Different configuration profiles may be encoded here to be specified
# as parameters to the configtxgen tool
#
################################################################################
Profiles:
OneOrgOrdererGenesis:
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Consortiums:
SampleConsortium:
Organizations:
- *Org1
OneOrgChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
################################################################################
#
# Section: Organizations
#
# - This section defines the different organizational identities which will
# be referenced later in the configuration.
#
################################################################################
Organizations:
# SampleOrg defines an MSP using the sampleconfig. It should never be used
# in production but may be used as a template for other definitions
- &OrdererOrg
# DefaultOrg defines the organization which is used in the sampleconfig
# of the fabric.git development environment
Name: OrdererOrg
# ID to load the MSP definition as
ID: OrdererMSP
# MSPDir is the filesystem path which contains the MSP configuration
MSPDir: crypto-config/ordererOrganizations/example.com/msp
- &Org1
# DefaultOrg defines the organization which is used in the sampleconfig
# of the fabric.git development environment
Name: Org1MSP
# ID to load the MSP definition as
ID: Org1MSP
MSPDir: crypto-config/peerOrganizations/org1.example.com/msp
AnchorPeers:
# AnchorPeers defines the location of peers which can be used
# for cross org gossip communication. Note, this value is only
# encoded in the genesis block in the Application section context
- Host: peer0.org1.example.com
Port: 7051
################################################################################
#
# SECTION: Orderer
#
# - This section defines the values to encode into a config transaction or
# genesis block for orderer related parameters
#
################################################################################
Orderer: &OrdererDefaults
# Orderer Type: The orderer implementation to start
# Available types are "solo" and "kafka"
OrdererType: solo
Addresses:
- orderer.example.com:7050
# Batch Timeout: The amount of time to wait before creating a batch
BatchTimeout: 2s
# Batch Size: Controls the number of messages batched into a block
BatchSize:
# Max Message Count: The maximum number of messages to permit in a batch
MaxMessageCount: 10
# Absolute Max Bytes: The absolute maximum number of bytes allowed for
# the serialized messages in a batch.
AbsoluteMaxBytes: 99 MB
# Preferred Max Bytes: The preferred maximum number of bytes allowed for
# the serialized messages in a batch. A message larger than the preferred
# max bytes will result in a batch larger than preferred max bytes.
PreferredMaxBytes: 512 KB
Kafka:
# Brokers: A list of Kafka brokers to which the orderer connects
# NOTE: Use IP:port notation
Brokers:
- 127.0.0.1:9092
# Organizations is the list of orgs which are defined as participants on
# the orderer side of the network
Organizations:
################################################################################
#
# SECTION: Application
#
# - This section defines the values to encode into a config transaction or
# genesis block for application related parameters
#
################################################################################
Application: &ApplicationDefaults
# Organizations is the list of orgs which are defined as participants on
# the application side of the network
Organizations:
root@wang-virtual-machine:/home/wang/fabric-samples/bin# export PATH=/home/wang/fabric-samples/bin:$PATH
root@wang-virtual-machine:/home/wang/fish/fishnetwork/basic-network# cryptogen generate --config ./crypto-config.yaml
生成创世区块
root@wang-virtual-machine:/home/wang/fish/fishnetwork/basic-network# mkdir channel-artifacts
root@wang-virtual-machine:/home/wang/fish/fishnetwork/basic-network# configtxgen -profile OneOrgOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
root@wang-virtual-machine:/home/wang/fish/fishnetwork/basic-network# configtxgen -profile OneOrgChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel