Update sbe transfer sample readme (#304)

Signed-off-by: NIKHIL E GUPTA <negupta@us.ibm.com>

Co-authored-by: NIKHIL E GUPTA <negupta@us.ibm.com>
This commit is contained in:
nikhil550 2020-08-19 12:50:33 -04:00 committed by GitHub
parent 9963449387
commit fdebe1f2e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,55 +1,135 @@
# Sample to demonstrate State-Based Endorsements (SBE)
# State-based endorsement asset transfer sample
## Introduction to SBE
Fabric allows different ways to set endorsements for transactions on the network. The default method is specified in chaincode definition, which is agreed by channel members and committed to the channel. However, there are cases where it may be necessary for a particular Key (public channel state or private data collection state) to have a different endorsement policy. State-Based endorsement allows endorsement policies to be overridden for the specified Key's. State-Based Endorsements are also known as Key Level Endorsements. To learn more about endorsement policies and State-Based endorsements, visit the [Fabric Endorsement Policies documentation](https://hyperledger-fabric.readthedocs.io/en/master/endorsement-policies.html).
Transactions that are submitted to Hyperledger Fabric networks need to be endorsed by peers that are joined to a channel before the transaction can be added to the ledger. Fabric peers endorse transactions by executing a smart contract using the inputs of the transaction proposal. The peers then sign the input and output generated by the smart contract execution. The endorsement policy specifies the set of organizations whose peers need to endorse a transaction before it can be added to the ledger.
Each chaincode that is deployed to a channel has an endorsement policy that governs the assets managed by the chaincode smart contracts. However, you can override the chaincode level endorsement policy to create an endorsement policy for a specific key, either on the public channel ledger or in a private collection. State-based endorsement policies, also known as key-level endorsement policies, allow channel members use different endorsement policies for assets that are managed by the same smart contract. For more information about endorsement policies and state-based endorsement, visit the [Endorsement Policies](https://hyperledger-fabric.readthedocs.io/en/master/endorsement-policies.html) topic in the Fabric documentation.
## About the Sample
The state-based endorsement (SBE) asset transfer sample demonstrates how to use key-level endorsement policies to ensure that an asset only needs to be endorsed by an asset owner. In the course of the tutorial, you will use the smart contract to complete the following transfer scenario:
- Deploy the SBE smart contract to a channel that was created using the Fabric test network. The channel will have two members, Org1 and Org2, that will participate in the asset transfer. Each organization operates one peer that is joined to the channel.
- Create an asset using the chaincode endorsement policy. The chaincode level endorsement policy requires that a majority of organizations on the channel to endorse a transaction. As a result, the transaction that creates the asset needs to be endorsed by peers that belong to Org1 and Org2. When the asset is created, the smart contract creates a state-based endorsement policy that specifies that only the organization that owns that asset needs to endorse any asset updates. Because the asset is owned by Org1, any future updates to the asset need to be endorsed by the Org1 peer.
- Update the asset using the state-based endorsement policy.
- Transfer the asset to Org2. The transfer transaction will create a new state-based endorsement policy that reflects the new asset owner.
- Update the asset once more, this time with Org2 as the owner. Because the state-based endorsement policy has been updated, this transaction only needs to be endorsed by Org2.
Fabric Shim Method's for State-Based endorsements (below references from fabric-shim, ChaincodeStub for Node):
- setStateValidationParameter(key: string, ep: Uint8Array): Promise<void>;
- getStateValidationParameter(key: string): Promise<Uint8Array>;
- setPrivateDataValidationParameter(collection: string, key: string, ep: Uint8Array): Promise<void>;
- getPrivateDataValidationParameter(collection: string, key: string): Promise<Uint8Array>;
## Deploy the smart contract
We are going to run the SBE smart contract using the Fabric test network. Open a command terminal and navigate to test network directory in your local clone of the `fabric-samples`. We will operate from the `test-network` directory for the remainder of the tutorial.
```
cd fabric-samples/test-network
```
## About the SBE Asset Transfer Sample
Using this sample we demonstrate State-Based Endorsements (SBE), and set a different endorsement policy for a specified Key, instead of the default chaincode policy. This sample is deployed and demonstrated on the fabric-samples, Test network (2 Org network, Org1 and Org2). The endorsement policy for chaincodes deployed in this network defaults to majority, that is both Org's need to endorse transactions on the network. To bootstrap the Test Network, and deploy the SBE Asset Transfer Sample chaincode, visit the [Test Network documentation](https://hyperledger-fabric.readthedocs.io/en/latest/test_network.html).
Run the following command to deploy the test network and create a channel named `mychannel`:
This sample demonstrates modifying the default chaincode policy (requiring endorsements from both Org Peers), and changing it to a less restrictive policy requiring endorsement only from a specific Org Peer for the specified Key. Endorsements can also be modified to be more restrictive for a particular Key in a similar way.
```
./network.sh up createChannel
```
On Asset creation, State-Based endorsements for the Asset Key is set to either Org1 or Org2 Peer, depending on the client Org creating the Asset. Creation of Asset still needs the default chaincode endorsement policy, and hence will need to be endorsed by both Org's (Org1 & Org2). However, all future updates for the Asset Key will use the modified endorsements as per the State-Based endorsements set during Asset creation.
You can use the test network script to deploy the smart contract to the channel that was just created. The script uses the Fabric chaincode lifecycle to deploy the smart contract to the channel. We will use the default chaincode level endorsement policy used by the Fabric chaincode lifecycle, which requires an endorsement from a majority of channel members. In our case, this will require that both Org1 and Org2 endorse a transaction (2 of 2). Deploy the smart contract to `mychannel` using the following command:
```
./network.sh deployCC -ccn sbe -ccl typescript
```
Hence transactions like UpdateAsset or TransferAsset will not succeed if endorsed by the non-owner Org Peer.
Set the following environment variables to interact with the network as a user from Org1:
Sample invokations to demonstrate State-Based Endorsements (SBE) on test-network, using client identity of Org1
* Create Asset (requires Org1 & Org2 Peer to endorse as per the default chaincode endorsement policy, however future updates will need only Org1 Peer to endorse, as the State-Based endorsement policy is set for assetId Key during the createAsset transaction)
```bash
```
export PATH=${PWD}/../bin:${PWD}:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051
```
## Run the transfer scenario
We can now invoke the SBE smart contract to create a new asset:
```
peer chaincode invoke -o localhost:7050 --waitForEvent --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n sbe --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"CreateAsset","Args":["asset1","100","Org1User1"]}'
```
* Read & Verify Asset (Use this to verify changes for UpdateAsset & TransferAsset)
```bash
The create transaction needs to target both peers from Org1 and Org2 to meet the chaincode endorsement policy. The chaincode will read the MSP ID of the client user submitting the transaction and assign that organization as the asset owner. As a result, the asset will initially be owned by Org1.
You can query the asset using with the following command:
```
peer chaincode query -C mychannel -n sbe -c '{"Args":["ReadAsset","asset1"]}'
```
* Update Asset (requires Org1 Peer to endorse as per SBE specified for assetId Key, but since Org2 Peer is endorsing it will result in ENDORSEMENT_POLICY_FAILURE by the peer during endorsement validations for the transaction)
```bash
The result is a new asset owned by Org1, identified using the Org1 MSP ID `Org1MSP`:
`{"ID":"asset1","Value":100,"Owner":"Org1User1","OwnerOrg":"Org1MSP"}`
In addition to creating the asset, the `CreateAsset` function also sets a state-based endorsement policy for the asset. Only a peer of the asset owner, can successfully endorse an asset update. To demonstrate the key-level endorsement policy, lets try to update the asset while targeting the Org2 peer:
```
peer chaincode invoke -o localhost:7050 --waitForEvent --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n sbe --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"UpdateAsset","Args":["asset1","200"]}'
```
* Update Asset succeeds (requires Org1 Peer to endorse as per SBE specified for assetId Key, and Org1 Peer is endorsing here)
```bash
The result is an endorsement policy failure:
```
Error: transaction invalidated with status (ENDORSEMENT_POLICY_FAILURE) - proposal response: <nil>
```
If we attempt to update the asset with an endorsement from the Org1 peer, the update succeeds:
```
peer chaincode invoke -o localhost:7050 --waitForEvent --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n sbe --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt -c '{"function":"UpdateAsset","Args":["asset1","200"]}'
```
* Transfer Asset (requires Org1 Peer to endorse as per SBE specified for assetId Key, but since Org2 Peer is endorsing it will result in ENDORSEMENT_POLICY_FAILURE by the peer during endorsement validations for the transaction)
```bash
peer chaincode invoke -o localhost:7050 --waitForEvent --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n sbe --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"TransferAsset","Args":["asset1","Org2User1","Org2MSP"]}'
You can query the asset one more time to verify that the update was successful:
```
peer chaincode query -C mychannel -n sbe -c '{"Args":["ReadAsset","asset1"]}'
```
The asset value is now 200:
```
{"ID":"asset1","Value":200,"Owner":"Org1User1","OwnerOrg":"Org1MSP"}
```
Now that we have tested the asset key-level endorsement policy, we can transfer the asset to Org2. Run the following command to transfer the asset from Org1 to Org2. This time the Org2 MSP ID is provided as a transaction input. The `TransferAsset` function will update the endorsement policy to specify that only a peer of the new owner can update the asset. Note that this command targets the Org1 peer.
```
* Transfer Asset succeeds (requires Org1 Peer to endorse as per SBE specified for assetId Key, and Org1 Peer is endorsing here)
```bash
peer chaincode invoke -o localhost:7050 --waitForEvent --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n sbe --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt -c '{"function":"TransferAsset","Args":["asset1","Org2User1","Org2MSP"]}'
```
* Update Asset (now requires Org2 Peer to endorse as per SBE specified for assetId Key, but since Org1 Peer is endorsing it will result in ENDORSEMENT_POLICY_FAILURE by the peer during endorsement validations for the transaction)
```bash
We can query the asset to see that the owner has been updated from Org1 to Org2:
```
peer chaincode query -C mychannel -n sbe -c '{"Args":["ReadAsset","asset1"]}'
```
The owning organization is now Org2:
```
{"ID":"asset1","Value":200,"Owner":"Org2User1","OwnerOrg":"Org2MSP"}
```
Org2 now needs to endorse any asset updates. Run the following command to try to update the asset with an endorsement from the Org1 peer:
```
peer chaincode invoke -o localhost:7050 --waitForEvent --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n sbe --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt -c '{"function":"UpdateAsset","Args":["asset1","300"]}'
```
* Update Asset succeeds (requires Org2 Peer to endorse as per SBE specified for assetId Key, and Org2 Peer is endorsing here)
```bash
The response will be an endorsement policy failure:
```
Error: transaction invalidated with status (ENDORSEMENT_POLICY_FAILURE) - proposal response: <nil>
```
Now try to update the asset with an endorsement from the Org2 peer:
```
peer chaincode invoke -o localhost:7050 --waitForEvent --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n sbe --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"UpdateAsset","Args":["asset1","300"]}'
```
You can query the asset again to verify that the transaction update succeeded:
```
peer chaincode query -C mychannel -n sbe -c '{"Args":["ReadAsset","asset1"]}'
```
The asset value is now 300:
```
{"ID":"asset1","Value":300,"Owner":"Org2User1","OwnerOrg":"Org2MSP"}
```
Note that the transaction to update the asset was submitted by a user from Org1, even though the asset was owned by Org2. The transfer enabled by the SBE smart contract is a simple scenario meant only to demonstrate the use of state-based endorsement policies. The smart contract can use access control to specify that an asset can only be updated by its owner. Private data collections can also be used to ensure that transfers need to be endorsed by the owner and recipient of the transfer, instead of just the asset owner. For a more realistic example of an asset transfer scenario, see the [Secured asset transfer in Fabric](https://hyperledger-fabric.readthedocs.io/en/master/secured_asset_transfer/secured_private_asset_transfer_tutorial.html) tutorial.
## Clean up
When you are finished, you can bring down the test network. The command will remove all the nodes of the test network, and delete any ledger data that you created:
```
./network.sh down
```