1. 1. 部署链码
    1. 1.1. 打包
    2. 1.2. 安装链码包,每个peer都要安装:
    3. 1.3. 批准链码定义
      1. 1.3.1. 查看已经安装的chaincode
      2. 1.3.2. 批准链码定义,每个peer都要执行此命令:
    4. 1.4. 将链码定义提交到通道
      1. 1.4.1. 检查channel上的成员是否已经批准了链码定义:
      2. 1.4.2. 在所有组织都批准之后,执行下面的命令将链码定义提交到通道:
  2. 2. 调用链码
    1. 2.1. 创建资产
    2. 2.2. 资产拥有者更改资产的公共信息
    3. 2.3. 资产交易
      1. 2.3.1. 允许出售资产
        1. 2.3.1.1. 核心企业将资产的价格设置为1000:
        2. 2.3.1.2. 一级供应商出价1000
      2. 2.3.2. 核心企业把资产转移给一级供应商
    4. 2.4. 交易验证
      1. 2.4.0.1. 验证一级供应商可以修改自己的资产的公共属性:
      2. 2.4.0.2. 验证核心企业不可以再修改这个资产的公共信息
      3. 2.4.0.3. 验证只有一级供应商才可以查询这个资产的私有信息
  • 3. 资产拆分
    1. 3.1. 调用拆分方法
    2. 3.2. 验证拆分结果
      1. 3.2.1. 私有数据验证
        1. 3.2.1.1. 第一个资产:
        2. 3.2.1.2. 第二个资产:
        3. 3.2.1.3. 原始的资产:
      2. 3.2.2. 公共数据验证
        1. 3.2.2.1. 第一个资产:
        2. 3.2.2.2. 第二个资产:
        3. 3.2.2.3. 原始的资产:
  • 4. 拆分后的资产交易
    1. 4.0.1. 核心允许出售资产,价格设置为500:
      1. 4.0.1.1. 一级供应商出价500
    2. 4.0.2. 核心企业把资产转移给一级供应商
  • 4.1. 交易验证
    1. 4.1.0.1. 验证一级供应商可以修改自己的资产的公共属性:
    2. 4.1.0.2. 验证核心企业不可以再修改这个资产的公共信息
    3. 4.1.0.3. 验证只有一级供应商才可以查询这个资产的私有信息
  • 5. 一级供应商与二级供应商交易
    1. 5.1. 验证拆分结果
      1. 5.1.1. 私有数据验证
        1. 5.1.1.1. 第一个资产:
        2. 5.1.1.2. 第二个资产:
        3. 5.1.1.3. 原始的资产,原始资产已经没有了:
      2. 5.1.2. 公共数据验证
        1. 5.1.2.1. 第一个资产:
        2. 5.1.2.2. 第二个资产:
        3. 5.1.2.3. 原始的资产,拆分资产之后原始资产的状态应该改变:
  • 6. 拆分后的资产交易
    1. 6.0.1. 一级供应商允许出售资产,设置价格:
      1. 6.0.1.1. 二级供应商2出价300
    2. 6.0.2. 一级供应商把资产转移给二级供应商2
  • 6.1. 交易验证
    1. 6.1.0.1. 验证二级级供应商2可以修改自己的资产的公共属性:
    2. 6.1.0.2. 验证只有二级级供应商2才可以查询这个资产的私有信息
  • 7. chaincode接口记录
    1. 7.1. 查询卖出的交易信息
    2. 7.2. 查询资产的公共信息
    3. 7.3. 查询私有资产信息
    4. 7.4. 查询一个资产公共信息的历史数据
  • 隐秘交易.md

    自己开发的智能合约在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