刚刚配置好了镜像加速器
现在我们来安装fabric镜像
地址
https://hyperledger-fabric.readthedocs.io/en/release-1.1/samples.html#binaries
官方使用curl
但是这里的http://goo.gl我们不能打开
所以我们去官方推荐的github上看这个sh脚本
If you get an error running the above curl command, you may have too old a version of curl that does not handle redirects or an unsupported environment.
Please visit the Prerequisites page for additional information on where to find the latest version of curl and get the right environment. Alternately, you can substitute the un-shortened URL: https://github.com/hyperledger/fabric/blob/master/scripts/bootstrap.sh
然后我们下载一下这个bootstrap.sh脚本文件
本来是可以用比如xhtp 直接把这个sh文件拖到服务器里面的
但是我这里网速太慢了
所以我就用
touch bootstrap.sh 创建了文件
然后复制了进去
然后我们修改一下他的权限
chmod 777 bootstrap.sh
777就是
1.Owner 4+2+1=7
2.Group 4+2+1=7
3. Other 4+2+1=7
修改完权限了
我们来运行吧
./bootstrap.sh
什么叫良心解说
什么叫良心解说
什么叫良心解说
我买了杭州60块的轻量级
结果速度100K
现在买了24块的香港轻量级
这速度,这速度,这速度
开心啊
不过呢,这里又踩了一个坑
如果是香港的,就不要配阿里镜像加速了
哎
完成啦
看到这个速度
确实是非常爽啊
现在我们来看一下docker的所有镜像
docker images
现在我们来看一下fabric给的示例代码
我们看一下test-network这个文件夹
我们来看一下network.sh这个脚本文件
cat network.sh
然后我们需要安装docker-compose
https://github.com/docker/compose
然后我们启动network.sh
./network.sh up
这样这个network示例算是运行成功了
整个过程下来虽然看上去简单
但是确实很恶心
然后我们装一下nodejs
这边我们使用的是nodesource提供的脚本安装
https://github.com/nodesource/distributions/blob/master/README.md
我们看下官网的版本
LTS是12
现在是14
我们就选12就好了
执行一下
# Using Ubuntu
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt-get install -y nodejs
现在nodejs安装好了
我们来写chaincode,也就是智能合约
我们创建一下文件夹
然后用npm init初始化一下
然后使用npm 安装一下fabric-shim
npm install --save fabric-shim
看一下目录
然后我们来写代码吧
我们先看一下fabric-shim的官方介绍
https://www.npmjs.com/package/fabric-shim
然后我们复制一下他们的官方示例代码
const shim = require('fabric-shim');
const Chaincode = class {
async Init(stub) {
// use the instantiate input arguments to decide initial chaincode state values
// save the initial states
await stub.putState(key, Buffer.from(aStringValue));
return shim.success(Buffer.from('Initialized Successfully!'));
}
async Invoke(stub) {
// use the invoke input arguments to decide intended changes
// retrieve existing chaincode states
let oldValue = await stub.getState(key);
// calculate new state values and saves them
let newValue = oldValue + delta;
await stub.putState(key, Buffer.from(newValue));
return shim.success(Buffer.from(newValue.toString()));
}
};
shim.start(new Chaincode());
我们看这个Init方法和Invoke方法
其实很简单
把状态放到stub里面,
然后从stub里面取出来处理一下
然后我们把index.js拷贝到目录下面
现在Init和Invoke这两个最基本的函数有了
然后我们写一下查询的函数
async query(stub, args) {
let productId = args[0];
let productBytes = await stub.getState(productId);
console.log(productBytes.toString());
return productBytes;
}
然后是initLedger 初始化账本
async initLedger(stub, args) {
console.log('====================Init Ledger Start====================');
let products = [];
products.push({
id: '001',
name: 'apple',
price: '10'
});
products.push({
id: '002',
name: 'banana',
price: '20'
});
products.push({
id: '003',
name: 'orange',
price: '30'
});
for (let i = 0; i < products.length; i++) {
await stub.putState('Product' + i, Buffer.from(JSON.stringify(products[i])));
console.log('Added <-->', products[i]);
}
console.log('====================Init Ledger End====================')
}
然后写一个插入
async insert(stub, args) {
console.log('====================START : Insert====================');
let product = {
id: args[1],
name: args[2],
price: args[3]
};
await stub.putState(args[0], Buffer.from(JSON.stringify(product)));
console.log('====================END : Insert====================');
}
然后写一个查询所有
async queryAll(stub, args) {
let startKey = 'Product0';
let endKey = 'Product999';
let iterator = await stub.getStateByRange(startKey, endKey);
let allResults = [];
while (true) {
let next = iterator.next();
if (next.value && next.value.value.toString()) {
let jsonNext = {};
jsonNext.Key = next.value.key;
jsonNext.Record = JSON.parse(next.value.value.toString('utf-8'));
allResults.push(jsonNext);
}
if (next.done) {
console.log('End of data');
await iterator.close();
console.log(allResults);
return Buffer.from(JSON.stringify(allResults));
}
}
}
然后看一下我们现在的chaincode代码
const shim = require('fabric-shim');
const Chaincode = class {
async Init(stub) {
// use the instantiate input arguments to decide initial chaincode state values
// save the initial states
await stub.putState('state', Buffer.from('init'));
return shim.success(Buffer.from('Initialized Successfully!'));
}
async Invoke(stub) {
// use the invoke input arguments to decide intended changes
// retrieve existing chaincode states
let oldValue = await stub.getState('state');
// calculate new state values and saves them
let newValue = 'invoke';
await stub.putState('state', Buffer.from(newValue));
return shim.success(Buffer.from(newValue.toString()));
}
async query(stub, args) {
let productId = args[0];
let productBytes = await stub.getState(productId);
console.log(productBytes.toString());
return productBytes;
}
async initLedger(stub, args) {
console.log('====================START : Init Ledger====================');
let products = [];
products.push({
id: '001',
name: 'apple',
price: '10'
});
products.push({
id: '002',
name: 'banana',
price: '20'
});
products.push({
id: '003',
name: 'orange',
price: '30'
});
for (let i = 0; i < products.length; i++) {
await stub.putState('Product' + i, Buffer.from(JSON.stringify(products[i])));
console.log('Added <-->', products[i]);
}
console.log('====================END : Init Ledger====================');
}
async insert(stub, args) {
console.log('====================START : Insert====================');
let product = {
id: args[1],
name: args[2],
price: args[3]
};
await stub.putState(args[0], Buffer.from(JSON.stringify(product)));
console.log('====================END : Insert====================');
}
async queryAll(stub, args) {
let startKey = 'Product0';
let endKey = 'Product999';
let iterator = await stub.getStateByRange(startKey, endKey);
let allResults = [];
while (true) {
let next = iterator.next();
if (next.value && next.value.value.toString()) {
let jsonNext = {};
jsonNext.Key = next.value.key;
jsonNext.Record = JSON.parse(next.value.value.toString('utf-8'));
allResults.push(jsonNext);
}
if (next.done) {
console.log('End of data');
await iterator.close();
console.log(allResults);
return Buffer.from(JSON.stringify(allResults));
}
}
}
};
shim.start(new Chaincode());
chaincode代码写完了
把index.js放到目录里面去
现在fish目录有chaincode文件夹,
我们再创建一个fishnetwork文件夹
然后我们需要配置msp信息
member service provider成员服务提供者
crypto-config.yaml
现在暂时还是根据视频来搞吧
现在把crypto-config.yaml文件放到network里面
OrdererOrgs:
- Name: Orderer
Domain: example.com
- Specs:
- Hostname: Orderer
PeerOrgs:
- Name: Org1
Domain: org1.example.com
Template:
Count: 1
- Users:
Count: 1
然后再看一下configtx.yaml文件
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: crypto-config/ordererOrganizations/example.com/msp
- &Org1
Name: Org1MSP
ID: Org1MSP
MSPDir: crypto-config/peerOrganizations/org1.example.com/msp
Application: &ApplicationDefaults
Organizations:
Orderer: &OrdererDefaults
OrdererType: solo
Addresses:
- orderer.example.com:7050
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 10
AbsoluteMaxBytes: 99 MB
PreferredMaxBytes: 512 KB
Organizations:
Profiles:
OneOrgsOrdererGenesis:
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Consortiums:
SampleConsortium:
Organizations:
- *Org1
OneOrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
也放到network里面
现在看看
然后我们要使用
cryptogen generate --config ./crypto-config.yaml
来创建
但是我们发现出现了
因为我们还没有配置cryptogen的环境变量
那么我们配置一下环境变量
export PATH=/root/howger/fabric-samples/bin:$PATH
然后我们再来执行一下
中间出了点小错误
就是crypto-config.yaml文件的横杠- 出不出现的问题
这个可能各个版本不一样
反正加上或者删掉就可以了
现在我们看
有了crypto-config文件夹
然后我们tree一下
看看目录结构
我们看到有
ca
msp
org
tlsca
users
然后我们生成创世区块
现在发生了问题
需要他妈的policies
所以我们还是加上
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: crypto-config/ordererOrganizations/example.com/msp
Policies:
Readers:
Type: Signature
Rule: "OR('OrdererMSP.member')"
Writers:
Type: Signature
Rule: "OR('OrdererMSP.member')"
Admins:
Type: Signature
Rule: "OR('OrdererMSP.admin')"
OrdererEndpoints:
- orderer.example.com:7050
- &Org1
Name: Org1MSP
ID: Org1MSP
MSPDir: crypto-config/peerOrganizations/org1.example.com/msp
Policies:
Readers:
Type: Signature
Rule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')"
Writers:
Type: Signature
Rule: "OR('Org1MSP.admin', 'Org1MSP.client')"
Admins:
Type: Signature
Rule: "OR('Org1MSP.admin')"
Endorsement:
Type: Signature
Rule: "OR('Org1MSP.peer')"
AnchorPeers:
- Host: peer0.org1.example.com
Port: 7051
Capabilities:
Channel: &ChannelCapabilities
V2_0: true
Orderer: &OrdererCapabilities
V2_0: true
Application: &ApplicationCapabilities
V2_0: true
Application: &ApplicationDefaults
Organizations:
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
LifecycleEndorsement:
Type: ImplicitMeta
Rule: "MAJORITY Endorsement"
Endorsement:
Type: ImplicitMeta
Rule: "MAJORITY Endorsement"
Capabilities:
<<: *ApplicationCapabilities
Orderer: &OrdererDefaults
OrdererType: solo
Addresses:
- orderer.example.com:7050
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 10
AbsoluteMaxBytes: 99 MB
PreferredMaxBytes: 512 KB
Organizations:
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
BlockValidation:
Type: ImplicitMeta
Rule: "ANY Writers"
Channel: &ChannelDefaults
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
Capabilities:
<<: *ChannelCapabilities
Profiles:
OneOrgsOrdererGenesis:
<<: *ChannelDefaults
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *Org1
OneOrgsChannel:
Consortium: SampleConsortium
<<: *ChannelDefaults
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
Capabilities:
<<: *ApplicationCapabilities
然后成功了
创建了创世区块
然后创建channel
真的调了好久好久好久
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: ./crypto-config/ordererOrganizations/example.com/msp
Policies:
Readers:
Type: Signature
Rule: "OR('OrdererMSP.member')"
Writers:
Type: Signature
Rule: "OR('OrdererMSP.member')"
Admins:
Type: Signature
Rule: "OR('OrdererMSP.admin')"
OrdererEndpoints:
- orderer.example.com:7050
- &Org1
Name: Org1MSP
ID: Org1MSP
MSPDir: ./crypto-config/peerOrganizations/org1.example.com/msp
Policies:
Readers:
Type: Signature
Rule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')"
Writers:
Type: Signature
Rule: "OR('Org1MSP.admin', 'Org1MSP.client')"
Admins:
Type: Signature
Rule: "OR('Org1MSP.admin')"
Endorsement:
Type: Signature
Rule: "OR('Org1MSP.peer')"
AnchorPeers:
- Host: peer0.org1.example.com
Port: 7051
Capabilities:
Channel: &ChannelCapabilities
V2_0: true
Orderer: &OrdererCapabilities
V2_0: true
Application: &ApplicationCapabilities
V2_0: true
Application: &ApplicationDefaults
Organizations:
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
LifecycleEndorsement:
Type: ImplicitMeta
Rule: "MAJORITY Endorsement"
Endorsement:
Type: ImplicitMeta
Rule: "MAJORITY Endorsement"
Capabilities:
<<: *ApplicationCapabilities
Orderer: &OrdererDefaults
OrdererType: solo
Addresses:
- orderer.example.com:7050
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 10
AbsoluteMaxBytes: 99 MB
PreferredMaxBytes: 512 KB
Organizations:
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
BlockValidation:
Type: ImplicitMeta
Rule: "ANY Writers"
Channel: &ChannelDefaults
Consortium: SampleConsortium
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
Capabilities:
<<: *ChannelCapabilities
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
Capabilities:
<<: *ApplicationCapabilities
Profiles:
OneOrgsOrdererGenesis:
<<: *ChannelDefaults
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *Org1
OneOrgsChannel:
Consortium: SampleConsortium
<<: *ChannelDefaults
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
Capabilities:
<<: *ApplicationCapabilities
现在创世区块和channel都创建好了
然后我们看下目录吧