Smart Contract 一步步走近“智能合约”
配置“智能合约”运行环境
基础配置请参考前两篇文章
Node.js(目前Fabric只支持6.9.X或更早版本)下载安装
https://nodejs.org/dist/v6.9.2/node-v6.9.2-linux-x64.tar.xz
[root@huangzhenhua tmp]# tar -xJf node-v6.9.2-linux-x64.tar.xz -C /usr/local/
设置node环境变量
[root@huangzhenhua Desktop]# vi /etc/profile
export NODE_HOME=/usr/local/node-v6.9.2-linux-x64
export PATH=$NODE_HOME/bin:$PATH
[root@huangzhenhua Desktop]# source /etc/profile
检查node配置是否成功
[root@huangzhenhua Desktop]# node -v
v6.9.2
[root@huangzhenhua Desktop]# npm -v
3.10.9
升级npm
[root@huangzhenhua Desktop]# npm install [email protected] -g
#安装g++,以便npm install初始化环境编译成功
[root@huangzhenhua Desktop]#yum install gcc-c++ libstdc++-devel
开启“智能合约”之旅
初始化客户端
[root@huangzhenhua Desktop]#cd /opt/gopath/src/github.com/hyperledger/fabric-samples/fabcar
[root@huangzhenhua fabcar]# npm install
[root@huangzhenhua fabcar]# ls
enrollAdmin.js invoke.js node_modules package.json query.js registerUser.js startFabric.sh
#新增node_modules目录
开启Fabric网络
[root@huangzhenhua fabcar]# ./startFabric.sh
# don't rewrite paths for Windows Git Bash users
export MSYS_NO_PATHCONV=1
docker-compose -f docker-compose.yml down
Removing network net_basic
WARNING: Network net_basic not found.
docker-compose -f docker-compose.yml up -d ca.example.com orderer.example.com peer0.org1.example.com couchdb
Creating orderer.example.com ... done
Creating peer0.org1.example.com ... done
Creating ca.example.com ...
Creating couchdb ...
Creating peer0.org1.example.com ...
# wait for Hyperledger Fabric to start
# incase of errors when running later commands, issue export FABRIC_START_TIMEOUT=
export FABRIC_START_TIMEOUT=10
#echo ${FABRIC_START_TIMEOUT}
sleep ${FABRIC_START_TIMEOUT}
# Create the channel
docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/[email protected]/msp" peer0.org1.example.com peer channel create -o orderer.example.com:7050 -c mychannel -f /etc/hyperledger/configtx/channel.tx
2018-02-09 01:57:19.575 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-02-09 01:57:19.575 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-02-09 01:57:19.613 UTC [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized
2018-02-09 01:57:19.772 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
2018-02-09 01:57:19.773 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
2018-02-09 01:57:19.782 UTC [msp] GetLocalMSP -> DEBU 006 Returning existing local MSP
2018-02-09 01:57:19.782 UTC [msp] GetDefaultSigningIdentity -> DEBU 007 Obtaining default signing identity
2018-02-09 01:57:19.782 UTC [msp/identity] Sign -> DEBU 008 Sign: plaintext: 0A88060A074F7267314D535012FC052D...53616D706C65436F6E736F727469756D
2018-02-09 01:57:19.782 UTC [msp/identity] Sign -> DEBU 009 Sign: digest: 75403FC8DC482C1B3066D9C407AADB725386A3726C62C555B04DB36939776BE6
2018-02-09 01:57:19.784 UTC [msp] GetLocalMSP -> DEBU 00a Returning existing local MSP
2018-02-09 01:57:19.784 UTC [msp] GetDefaultSigningIdentity -> DEBU 00b Obtaining default signing identity
2018-02-09 01:57:19.785 UTC [msp] GetLocalMSP -> DEBU 00c Returning existing local MSP
2018-02-09 01:57:19.785 UTC [msp] GetDefaultSigningIdentity -> DEBU 00d Obtaining default signing identity
2018-02-09 01:57:19.785 UTC [msp/identity] Sign -> DEBU 00e Sign: plaintext: 0ABF060A1508021A0608FFFFF3D30522...3DFDE089B2D35E4727BF90DE45BCCAF0
2018-02-09 01:57:19.786 UTC [msp/identity] Sign -> DEBU 00f Sign: digest: D9E138501FAAAEB049760F6B77E340C816EDB3A7BBF9975956128F19389DAEFD
2018-02-09 01:57:20.034 UTC [msp] GetLocalMSP -> DEBU 010 Returning existing local MSP
2018-02-09 01:57:20.035 UTC [msp] GetDefaultSigningIdentity -> DEBU 011 Obtaining default signing identity
2018-02-09 01:57:20.035 UTC [msp] GetLocalMSP -> DEBU 012 Returning existing local MSP
2018-02-09 01:57:20.035 UTC [msp] GetDefaultSigningIdentity -> DEBU 013 Obtaining default signing identity
2018-02-09 01:57:20.037 UTC [msp/identity] Sign -> DEBU 014 Sign: plaintext: 0ABF060A1508021A06088080F4D30522...F8192645A8C412080A021A0012021A00
2018-02-09 01:57:20.037 UTC [msp/identity] Sign -> DEBU 015 Sign: digest: 799B0FF90FC2CCE72A0218479F5E7677AC09C350AED36B5CFA8ADA7D6A738527
2018-02-09 01:57:20.053 UTC [channelCmd] readBlock -> DEBU 016 Got status: &{NOT_FOUND}
2018-02-09 01:57:20.053 UTC [msp] GetLocalMSP -> DEBU 017 Returning existing local MSP
2018-02-09 01:57:20.053 UTC [msp] GetDefaultSigningIdentity -> DEBU 018 Obtaining default signing identity
2018-02-09 01:57:20.061 UTC [channelCmd] InitCmdFactory -> INFO 019 Endorser and orderer connections initialized
2018-02-09 01:57:20.262 UTC [msp] GetLocalMSP -> DEBU 01a Returning existing local MSP
2018-02-09 01:57:20.262 UTC [msp] GetDefaultSigningIdentity -> DEBU 01b Obtaining default signing identity
2018-02-09 01:57:20.262 UTC [msp] GetLocalMSP -> DEBU 01c Returning existing local MSP
2018-02-09 01:57:20.262 UTC [msp] GetDefaultSigningIdentity -> DEBU 01d Obtaining default signing identity
2018-02-09 01:57:20.262 UTC [msp/identity] Sign -> DEBU 01e Sign: plaintext: 0ABF060A1508021A06088080F4D30522...F3A58811B5FA12080A021A0012021A00
2018-02-09 01:57:20.262 UTC [msp/identity] Sign -> DEBU 01f Sign: digest: 67282D9B92A83A30575FB8A4716DE78C6E479D20C75E77A639235CFF51B729C8
2018-02-09 01:57:20.268 UTC [channelCmd] readBlock -> DEBU 020 Received block: 0
2018-02-09 01:57:20.270 UTC [main] main -> INFO 021 Exiting.....
# Join peer0.org1.example.com to the channel.
docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/[email protected]/msp" peer0.org1.example.com peer channel join -b mychannel.block
2018-02-09 01:57:20.820 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-02-09 01:57:20.820 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-02-09 01:57:20.822 UTC [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized
2018-02-09 01:57:20.823 UTC [msp/identity] Sign -> DEBU 004 Sign: plaintext: 0A86070A5C08011A0C088080F4D30510...F937848E99E81A080A000A000A000A00
2018-02-09 01:57:20.823 UTC [msp/identity] Sign -> DEBU 005 Sign: digest: 26955468010896439EC6176F85068DCB33C90DB20BF3B014272F55EE0523FE27
2018-02-09 01:57:21.055 UTC [channelCmd] executeJoin -> INFO 006 Peer joined the channel!
2018-02-09 01:57:21.055 UTC [main] main -> INFO 007 Exiting.....
Creating cli ... done
2018-02-09 01:57:27.193 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-02-09 01:57:27.193 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-02-09 01:57:27.193 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc
2018-02-09 01:57:27.193 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc
2018-02-09 01:57:30.348 UTC [golang-platform] getCodeFromFS -> DEBU 005 getCodeFromFS github.com/fabcar
2018-02-09 01:57:32.288 UTC [golang-platform] func1 -> DEBU 006 Discarding GOROOT package bytes
2018-02-09 01:57:32.288 UTC [golang-platform] func1 -> DEBU 007 Discarding GOROOT package encoding/json
2018-02-09 01:57:32.288 UTC [golang-platform] func1 -> DEBU 008 Discarding GOROOT package fmt
2018-02-09 01:57:32.289 UTC [golang-platform] func1 -> DEBU 009 Discarding provided package github.com/hyperledger/fabric/core/chaincode/shim
2018-02-09 01:57:32.289 UTC [golang-platform] func1 -> DEBU 00a Discarding provided package github.com/hyperledger/fabric/protos/peer
2018-02-09 01:57:32.289 UTC [golang-platform] func1 -> DEBU 00b Discarding GOROOT package strconv
2018-02-09 01:57:32.289 UTC [golang-platform] GetDeploymentPayload -> DEBU 00c done
2018-02-09 01:57:32.300 UTC [msp/identity] Sign -> DEBU 00d Sign: plaintext: 0A86070A5C08031A0C088C80F4D30510...939FFF060000FFFF9C08DC0700200000
2018-02-09 01:57:32.300 UTC [msp/identity] Sign -> DEBU 00e Sign: digest: E7C910EE7E21F7132462FF8F7EE0BA073E13092BBE86A96E5DD97ECC7AFE9914
2018-02-09 01:57:32.307 UTC [chaincodeCmd] install -> DEBU 00f Installed remotely response:
2018-02-09 01:57:32.307 UTC [main] main -> INFO 010 Exiting.....
2018-02-09 01:57:32.583 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-02-09 01:57:32.584 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-02-09 01:57:32.601 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc
2018-02-09 01:57:32.601 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc
2018-02-09 01:57:32.605 UTC [msp/identity] Sign -> DEBU 005 Sign: plaintext: 0A91070A6708031A0C088C80F4D30510...324D53500A04657363630A0476736363
2018-02-09 01:57:32.605 UTC [msp/identity] Sign -> DEBU 006 Sign: digest: 5139B2C26E7B338FEDF7CD2ED4FCE3BDDE10EC40463181A2418BAA0018836CCF
2018-02-09 01:58:32.501 UTC [msp/identity] Sign -> DEBU 007 Sign: plaintext: 0A91070A6708031A0C088C80F4D30510...7737C51016751271CBB9CAF8344906AE
2018-02-09 01:58:32.501 UTC [msp/identity] Sign -> DEBU 008 Sign: digest: 8EA2367FC9F161BC1EC118EEAC19C51283C1C74C6FD3352E38C7FE936354B52B
2018-02-09 01:58:32.506 UTC [main] main -> INFO 009 Exiting.....
2018-02-09 01:58:42.864 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-02-09 01:58:42.864 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-02-09 01:58:42.866 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc
2018-02-09 01:58:42.866 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc
2018-02-09 01:58:42.867 UTC [msp/identity] Sign -> DEBU 005 Sign: plaintext: 0A93070A6908031A0C08D280F4D30510...1A0E0A0A696E69744C65646765720A00
2018-02-09 01:58:42.867 UTC [msp/identity] Sign -> DEBU 006 Sign: digest: A8A6C303B6202B78E2F74658D9473A678BD7B577CC0093DEF0E893BBC9D468B2
2018-02-09 01:58:42.934 UTC [msp/identity] Sign -> DEBU 007 Sign: plaintext: 0A93070A6908031A0C08D280F4D30510...57EF20082A5C71FFBCD56A41DF387707
2018-02-09 01:58:42.934 UTC [msp/identity] Sign -> DEBU 008 Sign: digest: C7084BFF48BF445CFA4909A8502D54C68A860A9C8321CFAE18CD3B782EA09D45
2018-02-09 01:58:42.938 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> DEBU 009 ESCC invoke result: version:1 response:
2018-02-09 01:58:42.938 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 00a Chaincode invoke successful. result: status:200
2018-02-09 01:58:42.938 UTC [main] main -> INFO 00b Exiting.....
Total setup execution time : 112 secs ...
Start by installing required packages run 'npm install'
Then run 'node enrollAdmin.js', then 'node registerUser'
The 'node invoke.js' will fail until it has been updated with valid arguments
The 'node query.js' may be run at anytime once the user has been registered
应用与Fabric网络链交互
登记admin用户
[root@huangzhenhua fabcar]# node enrollAdmin.js
Store path:/opt/gopath/src/github.com/hyperledger/fabric-samples/fabcar/hfc-key-store
Successfully loaded admin from persistence
Assigned the admin user to the fabric client ::{"name":"admin","mspid":"Org1MSP","roles":null,"affiliation":"","enrollmentSecret":"","enrollment":{"signingIdentity":"9bda7cde5fceff7596abe3ca9e9b8e448f552a408ad6de23f90372ff30b3c8a1","identity":{"certificate":"-----BEGIN CERTIFICATE-----\nMIIB8TCCAZegAwIBAgIUJlim2c0UjCxSVzcBbSRJra2orD4wCgYIKoZIzj0EAwIw\nczELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh\nbiBGcmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMT\nE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTgwMjA4MDgyNjAwWhcNMTkwMjA4MDgy\nNjAwWjAQMQ4wDAYDVQQDEwVhZG1pbjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA\nBF/M1BIG/uptSR4GSm+iGeVI4AdW1TK1oB1+DZqOi0if3Szd6YRkfjxVRZW2TupX\n0rN3NVl73EvG/wXV0w1OhVmjbDBqMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8E\nAjAAMB0GA1UdDgQWBBQJOBBToxK2FpfWf3hef2jRjxfckTArBgNVHSMEJDAigCBC\nOaoNzXba7ri6DNpwGFHRRQTTGq0bLd3brGpXNl5JfDAKBggqhkjOPQQDAgNIADBF\nAiEAwGuzr3JvZNdfMFp0gTXOcfJyCbjsxvC2lfIZJqG/EDcCIG7zSTSL5BAAnhE6\nCe3SOPyFAuNUTNP0GvIWo3t//l8/\n-----END CERTIFICATE-----\n"}}}
[root@huangzhenhua fabcar]# ls
enrollAdmin.js hfc-key-store invoke.js node_modules package.json query.js registerUser.js startFabric.sh
#新增hfc-key-store目录
注册和登记user1用户
[root@huangzhenhua fabcar]#node registerUser.js
Store path:/opt/gopath/src/github.com/hyperledger/fabric-samples/fabcar/hfc-key-store
Successfully loaded admin from persistence
Failed to register: Error: fabric-ca request register failed with errors [[{"code":400,"message":"Authorization failure"}]]
Authorization failures may be caused by having admin credentials from a previous CA instance.
Try again after deleting the contents of the store directory /opt/gopath/src/github.com/hyperledger/fabric-samples/fabcar/hfc-key-store
应用与智能合约交互
查询所有账本
[root@huangzhenhua fabcar]# node query.js
Store path:/opt/gopath/src/github.com/hyperledger/fabric-samples/fabcar/hfc-key-store
Successfully loaded user1 from persistence
Query has completed, checking results
Response is [{"Key":"CAR0", "Record":{"colour":"blue","make":"Toyota","model":"Prius","owner":"Tomoko"}},{"Key":"CAR1", "Record":{"colour":"red","make":"Ford","model":"Mustang","owner":"Brad"}},{"Key":"CAR2", "Record":{"colour":"green","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}},{"Key":"CAR3", "Record":{"colour":"yellow","make":"Volkswagen","model":"Passat","owner":"Max"}},{"Key":"CAR4", "Record":{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}},{"Key":"CAR5", "Record":{"colour":"purple","make":"Peugeot","model":"205","owner":"Michel"}},{"Key":"CAR6", "Record":{"colour":"white","make":"Chery","model":"S22L","owner":"Aarav"}},{"Key":"CAR7", "Record":{"colour":"violet","make":"Fiat","model":"Punto","owner":"Pari"}},{"Key":"CAR8", "Record":{"colour":"indigo","make":"Tata","model":"Nano","owner":"Valeria"}},{"Key":"CAR9", "Record":{"colour":"brown","make":"Holden","model":"Barina","owner":"Shotaro"}}]
查看智能合约
[root@huangzhenhua fabcar]# cd /opt/gopath/src/github.com/hyperledger/fabric-samples/chaincode/fabcar
[root@huangzhenhua fabcar]# ls
fabcar.go
[root@huangzhenhua fabcar]# vi fabcar.go
#主要功能如下:
initLedger, queryCar, queryAllCars, createCar, changeCarOwner.
查询指定Car -- CAR4
[root@huangzhenhua fabcar]# vi query.js
const request = {
//targets : --- letting this default to the peers assigned to the channel
chaincodeId: 'fabcar',
fcn: 'queryCar',
args: ['CAR4']
};
[root@huangzhenhua fabcar]# node query.js
Store path:/opt/gopath/src/github.com/hyperledger/fabric-samples/fabcar/hfc-key-store
Successfully loaded user1 from persistence
Query has completed, checking results
Response is {"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}
修改账本
[root@huangzhenhua fabcar]# node invoke.js
Store path:/opt/gopath/src/github.com/hyperledger/fabric-samples/fabcar/hfc-key-store
Successfully loaded user1 from persistence
Assigning transaction_id: 96d3350a871a93f4c1bbbd9be65c78389414225948599826027bb4073d39218d
Transaction proposal was good
Successfully sent Proposal and received ProposalResponse: Status - 200, message - "OK"
info: [EventHub.js]: _connect - options {}
The transaction has been committed on peer localhost:7053
Send transaction promise and event listener promise have completed
Successfully sent transaction to the orderer.
Successfully committed the change to the ledger by the peer
再次查询所有账本
[root@huangzhenhua fabcar]# node query.js
Store path:/opt/gopath/src/github.com/hyperledger/fabric-samples/fabcar/hfc-key-store
Successfully loaded user1 from persistence
Query has completed, checking results
Response is [{"Key":"CAR0", "Record":{"colour":"blue","make":"Toyota","model":"Prius","owner":"Tomoko"}},{"Key":"CAR1", "Record":{"colour":"red","make":"Ford","model":"Mustang","owner":"Brad"}},{"Key":"CAR10", "Record":{"colour":"","make":"","model":"","owner":"Dave"}},{"Key":"CAR2", "Record":{"colour":"green","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}},{"Key":"CAR3", "Record":{"colour":"yellow","make":"Volkswagen","model":"Passat","owner":"Max"}},{"Key":"CAR4", "Record":{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}},{"Key":"CAR5", "Record":{"colour":"purple","make":"Peugeot","model":"205","owner":"Michel"}},{"Key":"CAR6", "Record":{"colour":"white","make":"Chery","model":"S22L","owner":"Aarav"}},{"Key":"CAR7", "Record":{"colour":"violet","make":"Fiat","model":"Punto","owner":"Pari"}},{"Key":"CAR8", "Record":{"colour":"indigo","make":"Tata","model":"Nano","owner":"Valeria"}},{"Key":"CAR9", "Record":{"colour":"brown","make":"Holden","model":"Barina","owner":"Shotaro"}}]
修改CAR10的owner
[root@huangzhenhua fabcar]# vi invoke.js
var request = {
//targets: let default to the peer assigned to the client
chaincodeId: 'fabcar',
fcn: 'changeCarOwner',
args: ['CAR10', 'Nick002'],
chainId: 'mychannel',
txId: tx_id
};
[root@huangzhenhua fabcar]# node invoke.js
Store path:/opt/gopath/src/github.com/hyperledger/fabric-samples/fabcar/hfc-key-store
Successfully loaded user1 from persistence
Assigning transaction_id: 6a512da313097f66121944b1b784673636198972cbf6ec6c97e22758a54d25b5
Transaction proposal was good
Successfully sent Proposal and received ProposalResponse: Status - 200, message - "OK"
info: [EventHub.js]: _connect - options {}
The transaction has been committed on peer localhost:7053
Send transaction promise and event listener promise have completed
Successfully sent transaction to the orderer.
Successfully committed the change to the ledger by the peer
查询指定Car -- CAR10
[root@huangzhenhua fabcar]# node query.js
Store path:/opt/gopath/src/github.com/hyperledger/fabric-samples/fabcar/hfc-key-store
Successfully loaded user1 from persistence
Query has completed, checking results
Response is {"colour":"","make":"","model":"","owner":"Nick002"}