自己开发的智能合约在channel上的所有成员都可以看到,这不符合现实世界中的交易规则。理论上两个组织之间的交易是不允许别人看到的。所以这次我使用fabric-samples提供的asset-transfer-secured-agreement
来作为我的供应链金融区块链项目的chaincode。
部署链码
打包
1 peer lifecycle chaincode package secured_supply.5.tar.gz --path ./asset-transfer-secured-agreement/chaincode-go --lang golang --label secured_supply_15.0
安装链码包,每个peer都要安装:
1 peer lifecycle chaincode install secured_supply.5.tar.gz
批准链码定义
查看已经安装的chaincode
1 peer lifecycle chaincode queryinstalled
将链码的信息保存为一个变量,两个组织都需要定义此变量:
1 export CC_PACKAGE_ID=secured_supply_22.0:e815ca2d270dea029bc6992952140b1288a440aba8c430853f72eee7d5de24a7
批准链码定义,每个peer都要执行此命令:
1 peer lifecycle chaincode approveformyorg -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --channelID alljoinchannel --name secured_supply --version 23.0 --package-id $CC_PACKAGE_ID --sequence 23 --signature-policy "OR('GylCoreOrg1MSP.member','GylFOrg1MSP.member','GylSOrg1MSP.member','GylSOrg2MSP.member')" --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem
将链码定义提交到通道
检查channel上的成员是否已经批准了链码定义:
1 peer lifecycle chaincode checkcommitreadiness --channelID alljoinchannel --name secured_supply --version 23.0 --sequence 23 --signature-policy "OR('GylCoreOrg1MSP.member','GylFOrg1MSP.member','GylSOrg1MSP.member','GylSOrg2MSP.member')" --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem --output json
在所有组织都批准之后,执行下面的命令将链码定义提交到通道:
1 peer lifecycle chaincode commit -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --channelID alljoinchannel --name secured_supply --version 23.0 --sequence 23 --signature-policy "OR('GylCoreOrg1MSP.member','GylFOrg1MSP.member','GylSOrg1MSP.member','GylSOrg2MSP.member')" --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem --peerAddresses localhost:8053 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/f1.supply.com/peers/peer0.f1.supply.com/tls/ca.crt --peerAddresses localhost:8055 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/s1.supply.com/peers/peer0.s1.supply.com/tls/ca.crt --peerAddresses localhost:8151 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/s2.supply.com/peers/peer0.s2.supply.com/tls/ca.crt --peerAddresses localhost:8051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/core.supply.com/peers/peer0.core.supply.com/tls/ca.crt
使用 peer lifecycle chaincode querycommitted 命令来确认链码定义已经提交到通道。
1 peer lifecycle chaincode querycommitted --channelID alljoinchannel --name secured_supply --output json
调用链码
创建资产
资产的内容需要打个问号,因为这个资产在后面需要被交易,如果资产的内容不能够修改那么合同和发票的hash应该不在资产的详细信息里面,这里先放这里后面再改
发行者能否放在外面而不是资产里面?哪种方式比较好呢?
在核心企业的节点创建一个资产如下:
1 export ASSET_PROPERTIES=$(echo -n "{\"objectType\":\"asset_properties\",\"assetID\":\"asset011\",\"issuer\":\"GylCoreOrg1MSP\",\"amount\":1000,\"createDate\":\"2020-01-11T06:57:06.963617Z\",\"endDate\":\"2021-07-11T06:57:06.963617Z\",\"salt\":\"224cba6c547aecc76ab6acfac41d12dfd96e7165\"}" | base64 | tr -d \\n)
在核心企业的节点上调用chaincode,创建资产:
1 peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"CreateAsset","Args":["asset011", "A new asset for GylCoreOrg1MSP"]}' --transient "{\"asset_properties\":\"$ASSET_PROPERTIES\"}"
在私有数据集中查询刚才创建的资产:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetPrivateProperties","Args":["asset011"]}'|jq
成功结果:
1 2 3 4 5 6 7 8 9 { "objectType" : "asset_properties" , "assetID" : "asset010" , "issuer" : "GylCoreOrg1MSP" , "amount" : 1000 , "createDate" : "2020-01-11T06:57:06.963617Z" , "endDate" : "2021-07-11T06:57:06.963617Z" , "salt" : "224cba6c547aecc76ab6acfac41d12dfd96e7165" }
查询账本来查看公共记录,所有在channel上的成员都可以查询得到:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ReadAsset","Args":["asset010"]}'
返回结果,channel上的成员只能看到资产的部分信息,详细信息是无法看到的。:
1 2 3 4 5 6 7 8 { "objectType" : "asset" , "assetID" : "asset010" , "ownerOrg" : "GylCoreOrg1MSP" , "publicDescription" : "A new asset for GylCoreOrg1MSP" , "status" : "enable" , "parentID" : "" }
资产拥有者更改资产的公共信息
1 peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ChangePublicDescription","Args":["asset010","This asset is for sale"]}'
上面的方法,在核心企业的peer节点返回日志如下:
1 2021-01-07 16:07:43.589 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
其他的组织如果想要调用这个链码的方法更改信息,则会报错,因为属于核心企业的资产别人不可以更改:
1 Error: endorsement failure during invoke. response: status:500 message:"a client from GylFOrg1MSP cannot update the description of a asset owned by GylCoreOrg1MSP"
资产交易
允许出售资产
现在核心企业要与一级供应商交易核心企业的资产。首先核心企业与一级供应商要在链下对价格达成共识,并且核心企业要把资产的详情也通过链下的通道发送给一级供应商。之后买卖双方就可以对价格达成共识了。
核心企业将资产的价格设置为1000:
下面的trade_id是合同的hash值
1 2 export ASSET_PRICE=$(echo -n "{\"asset_id\":\"asset007\",\"trade_id\":\"93b46869be90a6b1f688357965f89b5a8a5e32bf13710fb4ad00e25cca0f0b14\",\"price\":1000}" | base64) peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"AgreeToSell","Args":["asset007"]}' --transient "{\"asset_price\":\"$ASSET_PRICE\"}"
查询核心企业的私有数据集合来读取同意的销售价格:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetSalesPrice","Args":["asset007"]}'
一级供应商出价1000
在一级供应商出价之前,他需要先验证资产的信息是否正确。此链码中返回true即为正确。
1 2 # export ASSET_PROPERTIES=$(echo -n "{\"object_type\":\"asset_properties\",\"asset_id\":\"asset006\",\"issuer\":\"GylCoreOrg1MSP\",\"amount\":1000,\"createDate\":\"2020-01-11T06:57:06.963617Z\",\"endDate\":\"2021-07-11T06:57:06.963617Z\",\"salt\":\"224cba6c547aecc76ab6acfac41d12dfd96e7165\"}" | base64 | tr -d \\n)peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"VerifyAssetProperties","Args":["asset007"]}' --transient "{\"asset_properties\":\"$ASSET_PROPERTIES\"}"
验证通过之后,就对资产出价:
1 2 export ASSET_PRICE=$(echo -n "{\"asset_id\":\"asset007\",\"trade_id\":\"93b46869be90a6b1f688357965f89b5a8a5e32bf13710fb4ad00e25cca0f0b14\",\"price\":1000}" | base64) peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"AgreeToBuy","Args":["asset007"]}' --transient "{\"asset_price\":\"$ASSET_PRICE\"}"
可以在一级供应商的隐私数据集中查询到出价信息:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetBidPrice","Args":["asset007"]}'
如果在其他组织上查询,会看到如下错误,说明出价卖出设置的价格信息是隐秘的:
1 Error: endorsement failure during query. response: status:500 message:"asset price does not exist: asset001"
核心企业把资产转移给一级供应商
核心企业和一级供应商对相同的价格达成共识之后,核心企业就可以把资产转移给一级供应商了。
1 peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply --peerAddresses localhost:8051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/core.supply.com/peers/peer0.core.supply.com/tls/ca.crt --peerAddresses localhost:8053 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/f1.supply.com/peers/peer0.f1.supply.com/tls/ca.crt -c '{"function":"TransferAsset","Args":["asset007","GylFOrg1MSP"]}' --transient "{\"asset_properties\":\"$ASSET_PROPERTIES\",\"asset_price\":\"$ASSET_PRICE\"}"
查询公共数据的资产归属以验证交易成功:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ReadAsset","Args":["asset001"]}'
交易验证
除了交易双方其他人无法查看到资产详情
验证一级供应商可以修改自己的资产的公共属性:
1 peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ChangePublicDescription","Args":["asset005","This asset is not for sale now"]}'
然后通过所有四个组织查询资产ID为asset005的公共信息如下,说明一级供应商已经获得了修改权限并修改了这个资产的公共信息:
1 2 3 4 5 6 7 (base) w:supply-finance apple$ peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ReadAsset","Args":["asset005"]}'|jq { "objectType": "asset", "assetID": "asset005", "ownerOrg": "GylFOrg1MSP", "publicDescription": "This asset is not for sale now" }
验证核心企业不可以再修改这个资产的公共信息
1 peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ChangePublicDescription","Args":["asset005","This asset is not for sale again"]}'
结果报错如下,符合预期:
1 Error: endorsement failure during invoke. response: status:500 message:"a client from GylCoreOrg1MSP cannot update the description of a asset owned by GylFOrg1MSP"
验证只有一级供应商才可以查询这个资产的私有信息
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetPrivateProperties","Args":["asset005"]}'
结果如下,验证通过:
再一级供应商的peer节点可以查询到资产的私有属性,其他组织的peer节点都报错:Error: endorsement failure during query. response: status:500 message:"asset private details does not exist in client org's collection: asset005"
资产拆分
调用拆分方法
完成资产的拆分chaincode的更新之后,调用拆分的方法:
1 peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"SplitAsset","Args":["asset010", "500"]}'
验证拆分结果
私有数据验证
第一个资产:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetPrivateProperties","Args":["asset0101"]}'|jq
1 2 3 4 5 6 7 8 9 { "objectType": "asset_properties", "assetID": "asset0101", "issuer": "GylCoreOrg1MSP", "amount": 500, "createDate": "2020-01-11T06:57:06.963617Z", "endDate": "2021-07-11T06:57:06.963617Z", "salt": "224cba6c547aecc76ab6acfac41d12dfd96e7165" }
第二个资产:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetPrivateProperties","Args":["asset0102"]}'|jq
结果如下:
1 2 3 4 5 6 7 8 9 { "objectType" : "asset_properties" , "assetID" : "asset0102" , "issuer" : "GylCoreOrg1MSP" , "amount" : 500 , "createDate" : "2020-01-11T06:57:06.963617Z" , "endDate" : "2021-07-11T06:57:06.963617Z" , "salt" : "224cba6c547aecc76ab6acfac41d12dfd96e7165" }
原始的资产:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetPrivateProperties","Args":["asset010"]}'|jq
结果如下,原始资产已经没有了:
1 Error: endorsement failure during query. response: status:500 message:"asset private details does not exist in client org's collection: asset010"
公共数据验证
第一个资产:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ReadAsset","Args":["asset0101"]}'|jq
结果如下,channel上的所有的组织都可以看到相同的数据:
1 2 3 4 5 6 7 8 { "objectType" : "asset" , "assetID" : "asset0101" , "ownerOrg" : "GylCoreOrg1MSP" , "publicDescription" : "A new asset for GylCoreOrg1MSP" , "status" : "enable" , "parentID" : "asset010" }
第二个资产:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ReadAsset","Args":["asset0102"]}'|jq
结果如下:
1 2 3 4 5 6 7 8 { "objectType" : "asset" , "assetID" : "asset0102" , "ownerOrg" : "GylCoreOrg1MSP" , "publicDescription" : "A new asset for GylCoreOrg1MSP" , "status" : "enable" , "parentID" : "asset010" }
原始的资产:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ReadAsset","Args":["asset010"]}'|jq
结果如下,chaincode有问题,拆分资产之后原始资产的状态应该改变:
1 2 3 4 5 6 7 8 { "objectType" : "asset" , "assetID" : "asset010" , "ownerOrg" : "GylCoreOrg1MSP" , "publicDescription" : "已拆分" , "status" : "delete" , "parentID" : "" }
拆分后的资产交易
核心允许出售资产,价格设置为500:
下面的trade_id是合同的hash值
1 2 export ASSET_PRICE=$(echo -n "{\"asset_id\":\"asset0101\",\"trade_id\":\"93b46869be90a6b1f688357965f89b5a8a5e32bf13710fb4ad00e25cca0f0b14\",\"price\":500}" | base64) peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"AgreeToSell","Args":["asset0101"]}' --transient "{\"asset_price\":\"$ASSET_PRICE\"}"
查询核心企业的私有数据集合来读取同意的销售价格:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetSalesPrice","Args":["asset0101"]}'
一级供应商出价500
在一级供应商出价之前,他需要先验证资产的信息是否正确。此链码中返回true即为正确。
1 2 export ASSET_PROPERTIES=$(echo -n "{\"objectType\":\"asset_properties\",\"assetID\":\"asset0101\",\"issuer\":\"GylCoreOrg1MSP\",\"amount\":500,\"createDate\":\"2020-01-11T06:57:06.963617Z\",\"endDate\":\"2021-07-11T06:57:06.963617Z\",\"salt\":\"224cba6c547aecc76ab6acfac41d12dfd96e7165\"}" | base64 | tr -d \\n) peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"VerifyAssetProperties","Args":["asset0101"]}' --transient "{\"asset_properties\":\"$ASSET_PROPERTIES\"}"
验证通过之后,就对资产出价:
1 2 export ASSET_PRICE=$(echo -n "{\"asset_id\":\"asset0101\",\"trade_id\":\"93b46869be90a6b1f688357965f89b5a8a5e32bf13710fb4ad00e25cca0f0b14\",\"price\":500}" | base64) peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"AgreeToBuy","Args":["asset0101"]}' --transient "{\"asset_price\":\"$ASSET_PRICE\"}"
可以在一级供应商的隐私数据集中查询到出价信息:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetBidPrice","Args":["asset0101"]}'
如果在其他组织上查询,会看到如下错误,说明出价卖出设置的价格信息是隐秘的:
1 Error: endorsement failure during query. response: status:500 message:"asset price does not exist: asset001"
核心企业把资产转移给一级供应商
核心企业和一级供应商对相同的价格达成共识之后,核心企业就可以把资产转移给一级供应商了。
1 peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply --peerAddresses localhost:8051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/core.supply.com/peers/peer0.core.supply.com/tls/ca.crt --peerAddresses localhost:8053 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/f1.supply.com/peers/peer0.f1.supply.com/tls/ca.crt -c '{"function":"TransferAsset","Args":["asset0101","GylFOrg1MSP"]}' --transient "{\"asset_properties\":\"$ASSET_PROPERTIES\",\"asset_price\":\"$ASSET_PRICE\"}"
查询公共数据的资产归属以验证交易成功:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ReadAsset","Args":["asset0101"]}'|jq
结果如下:
1 2 3 4 5 6 7 8 { "objectType" : "asset" , "assetID" : "asset0101" , "ownerOrg" : "GylFOrg1MSP" , "publicDescription" : "A new asset for GylCoreOrg1MSP" , "status" : "enable" , "parentID" : "asset010" }
交易验证
除了交易双方其他人无法查看到资产详情
验证一级供应商可以修改自己的资产的公共属性:
1 peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ChangePublicDescription","Args":["asset0101","This asset is not for sale now"]}'
修改成功之后重新查询资产的公共信息,验证通过:
1 2 3 4 5 6 7 8 { "objectType" : "asset" , "assetID" : "asset0101" , "ownerOrg" : "GylFOrg1MSP" , "publicDescription" : "This asset is not for sale now" , "status" : "enable" , "parentID" : "asset010" }
验证核心企业不可以再修改这个资产的公共信息
1 peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ChangePublicDescription","Args":["asset0101","This asset is not for sale again"]}'
结果报错如下,符合预期:
1 Error: endorsement failure during invoke. response: status:500 message:"a client from GylCoreOrg1MSP cannot update the description of a asset owned by GylFOrg1MSP"
验证只有一级供应商才可以查询这个资产的私有信息
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetPrivateProperties","Args":["asset0101"]}'
结果如下,验证通过:
在一级供应商的peer节点可以查询到资产的私有属性,其他组织的peer节点都报错:Error: endorsement failure during query. response: status:500 message:"asset private details does not exist in client org's collection: asset005"
一级供应商与二级供应商交易
调用拆分的方法,将资产拆分成200和300:
1 peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"SplitAsset","Args":["asset0101", "200"]}'
验证拆分结果
私有数据验证
第一个资产:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetPrivateProperties","Args":["asset01011"]}'|jq
第二个资产:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetPrivateProperties","Args":["asset01012"]}'|jq
原始的资产,原始资产已经没有了:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetPrivateProperties","Args":["asset0101"]}'|jq
公共数据验证
第一个资产:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ReadAsset","Args":["asset01011"]}'|jq
第二个资产:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ReadAsset","Args":["asset01012"]}'|jq
原始的资产,拆分资产之后原始资产的状态应该改变:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ReadAsset","Args":["asset0101"]}'|jq
拆分后的资产交易
一级供应商允许出售资产,设置价格:
下面的trade_id是合同的hash值
1 2 export ASSET_PRICE=$(echo -n "{\"asset_id\":\"asset01012\",\"trade_id\":\"f46555b7ddd1f8dd232bdc0dcbc5b1f34bdf1d4bb7c123a79a6ed628175f29bb\",\"price\":300}" | base64) peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"AgreeToSell","Args":["asset01012"]}' --transient "{\"asset_price\":\"$ASSET_PRICE\"}"
查询核心企业的私有数据集合来读取同意的销售价格:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetSalesPrice","Args":["asset01012"]}'
二级供应商2出价300
在二级供应商2出价之前,他需要先验证资产的信息是否正确。此链码中返回true即为正确。
1 2 export ASSET_PROPERTIES=$(echo -n "{\"objectType\":\"asset_properties\",\"assetID\":\"asset01012\",\"issuer\":\"GylCoreOrg1MSP\",\"amount\":300,\"createDate\":\"2020-01-11T06:57:06.963617Z\",\"endDate\":\"2021-07-11T06:57:06.963617Z\",\"salt\":\"224cba6c547aecc76ab6acfac41d12dfd96e7165\"}" | base64 | tr -d \\n) peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"VerifyAssetProperties","Args":["asset01012"]}' --transient "{\"asset_properties\":\"$ASSET_PROPERTIES\"}"
验证通过之后,就对资产出价:
1 2 export ASSET_PRICE=$(echo -n "{\"asset_id\":\"asset01012\",\"trade_id\":\"f46555b7ddd1f8dd232bdc0dcbc5b1f34bdf1d4bb7c123a79a6ed628175f29bb\",\"price\":300}" | base64) peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"AgreeToBuy","Args":["asset01012"]}' --transient "{\"asset_price\":\"$ASSET_PRICE\"}"
可以在一级供应商的隐私数据集中查询到出价信息:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetBidPrice","Args":["asset01012"]}'
如果在其他组织上查询,会看到如下错误,说明出价卖出设置的价格信息是隐秘的:
1 Error: endorsement failure during query. response: status:500 message:"asset price does not exist: asset001"
一级供应商把资产转移给二级供应商2
1 peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply --peerAddresses localhost:8053 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/f1.supply.com/peers/peer0.f1.supply.com/tls/ca.crt --peerAddresses localhost:8151 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/s2.supply.com/peers/peer0.s2.supply.com/tls/ca.crt -c '{"function":"TransferAsset","Args":["asset01012","GylSOrg2MSP"]}' --transient "{\"asset_properties\":\"$ASSET_PROPERTIES\",\"asset_price\":\"$ASSET_PRICE\"}"
查询公共数据的资产归属以验证交易成功:
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ReadAsset","Args":["asset01012"]}'|jq
结果如下:
1 2 3 4 5 6 7 8 { "objectType" : "asset" , "assetID" : "asset01012" , "ownerOrg" : "GylSOrg2MSP" , "publicDescription" : "This asset is not for sale now" , "status" : "enable" , "parentID" : "asset0101" }
交易验证
除了交易双方其他人无法查看到资产详情
验证二级级供应商2可以修改自己的资产的公共属性:
1 peer chaincode invoke -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ChangePublicDescription","Args":["asset01012","hello i am GylSOrg2MSP"]}'
修改成功之后重新查询资产的公共信息,验证通过:
1 2 3 4 5 6 7 8 { "objectType" : "asset" , "assetID" : "asset01012" , "ownerOrg" : "GylSOrg2MSP" , "publicDescription" : "hello i am GylSOrg2MSP" , "status" : "enable" , "parentID" : "asset0101" }
验证只有二级级供应商2才可以查询这个资产的私有信息
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetPrivateProperties","Args":["asset01012"]}'
结果如下,验证通过:
在一级供应商的peer节点可以查询到资产的私有属性,其他组织的peer节点都报错:Error: endorsement failure during query. response: status:500 message:"asset private details does not exist in client org's collection: asset005"
chaincode接口记录
查询卖出的交易信息
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"QueryAssetSaleAgreements","Args":[]}'
查询资产的公共信息
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"ReadAsset","Args":["asset01012"]}'|jq
查询私有资产信息
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"GetAssetPrivateProperties","Args":["asset01012"]}'|jq
查询一个资产公共信息的历史数据
1 peer chaincode query -o localhost:8050 --ordererTLSHostnameOverride orderer.supply.com --tls --cafile ${PWD}/organizations/ordererOrganizations/supply.com/orderers/orderer.supply.com/msp/tlscacerts/tlsca.supply.com-cert.pem -C alljoinchannel -n secured_supply -c '{"function":"QueryAssetHistory","Args":["asset01012"]}'|jq