diff --git a/asset-transfer-private-data/application-javascript/app.js b/asset-transfer-private-data/application-javascript/app.js index a51798fb..4c0edb26 100644 --- a/asset-transfer-private-data/application-javascript/app.js +++ b/asset-transfer-private-data/application-javascript/app.js @@ -153,7 +153,21 @@ async function main() { result = await contractOrg1.evaluateTransaction('ReadAssetPrivateDetails', org1PrivateCollectionName, assetID1); console.log(' result: ' + prettyJSONString(result.toString())); - + // Attempt Transfer the asset to Org2 , without Org2 adding AgreeToTransfer // + // Transaction should return an error: "failed transfer verification ..." + let buyerDetails = { assetID: assetID1, buyerMSP: mspOrg2 }; + try { + console.log('\n--> Attempt Submit Transaction: TransferAsset ' + assetID1); + statefulTxn = contractOrg1.createTransaction('TransferAsset'); + tmapData = Buffer.from(JSON.stringify(buyerDetails)); + statefulTxn.setTransient({ + asset_owner: tmapData + }); + result = await statefulTxn.submit(); + console.log('******** FAILED: above operation expected to return an error'); + } catch (error) { + console.log(` Successfully caught the error: \n ${error}`); + } console.log('\n~~~~~~~~~~~~~~~~ As Org2 Client ~~~~~~~~~~~~~~~~'); console.log('\n--> Evaluate Transaction: ReadAsset ' + assetID1); result = await contractOrg2.evaluateTransaction('ReadAsset', assetID1); @@ -194,7 +208,7 @@ async function main() { // Transfer the asset to Org2 // // To transfer the asset, the owner needs to pass the MSP ID of new asset owner, and initiate the transfer console.log('\n--> Submit Transaction: TransferAsset ' + assetID1); - let buyerDetails = { assetID: assetID1, buyerMSP: mspOrg2 }; + statefulTxn = contractOrg1.createTransaction('TransferAsset'); tmapData = Buffer.from(JSON.stringify(buyerDetails)); statefulTxn.setTransient({ @@ -202,7 +216,6 @@ async function main() { }); result = await statefulTxn.submit(); - //Again ReadAsset : results will show that the buyer identity now owns the asset: console.log('\n--> Evaluate Transaction: ReadAsset ' + assetID1); result = await contractOrg1.evaluateTransaction('ReadAsset', assetID1); @@ -221,11 +234,23 @@ async function main() { console.log(' result: ' + prettyJSONString(result.toString())); console.log('\n********* Demo deleting asset **************'); - // Delete Asset2 - console.log('--> Submit Transaction: DeleteAsset ' + assetID2); - statefulTxn = contractOrg1.createTransaction('DeleteAsset'); - let dataForDelete = { assetID: assetID2 }; + try { + //Non-owner Org2 should not be able to DeleteAsset. Expect an error from DeleteAsset + console.log('--> Attempt Transaction: as Org2 DeleteAsset ' + assetID2); + statefulTxn = contractOrg2.createTransaction('DeleteAsset'); + tmapData = Buffer.from(JSON.stringify(dataForDelete)); + statefulTxn.setTransient({ + asset_delete: tmapData + }); + result = await statefulTxn.submit(); + console.log('******** FAILED : expected to return an error'); + } catch (error) { + console.log(` Successfully caught the error: \n ${error}`); + } + // Delete Asset2 as Org1 + console.log('--> Submit Transaction: as Org1 DeleteAsset ' + assetID2); + statefulTxn = contractOrg1.createTransaction('DeleteAsset'); tmapData = Buffer.from(JSON.stringify(dataForDelete)); statefulTxn.setTransient({ asset_delete: tmapData diff --git a/asset-transfer-private-data/chaincode-go/chaincode/asset_transfer.go b/asset-transfer-private-data/chaincode-go/chaincode/asset_transfer.go index aeb19b72..2e7c197c 100644 --- a/asset-transfer-private-data/chaincode-go/chaincode/asset_transfer.go +++ b/asset-transfer-private-data/chaincode-go/chaincode/asset_transfer.go @@ -123,7 +123,7 @@ func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface) Size: assetInput.Size, Owner: clientID, } - assetJSONasBytes, err := json.Marshal(&asset) + assetJSONasBytes, err := json.Marshal(asset) if err != nil { return fmt.Errorf("failed to marshal asset into JSON: %v", err) } @@ -143,7 +143,7 @@ func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface) AppraisedValue: assetInput.AppraisedValue, } - assetPrivateDetailsAsBytes, err := json.Marshal(&assetPrivateDetails) // marshal asset details to JSON + assetPrivateDetailsAsBytes, err := json.Marshal(assetPrivateDetails) // marshal asset details to JSON if err != nil { return fmt.Errorf("failed to marshal into JSON: %v", err) } @@ -443,10 +443,18 @@ func (s *SmartContract) DeleteAsset(ctx contractapi.TransactionContextInterface) return fmt.Errorf("asset not found: %v", assetDeleteInput.ID) } - var assetToDelete Asset - err = json.Unmarshal([]byte(valAsbytes), &assetToDelete) + ownerCollection, err := getCollectionName(ctx) // Get owners collection if err != nil { - return fmt.Errorf("failed to unmarshal JSON: %v", err) + return fmt.Errorf("failed to infer private collection name for the org: %v", err) + } + + //check the asset is in the caller org's private collection + valAsbytes, err = ctx.GetStub().GetPrivateData(ownerCollection, assetDeleteInput.ID) + if err != nil { + return fmt.Errorf("failed to read asset from owner's Collection: %v", err) + } + if valAsbytes == nil { + return fmt.Errorf("asset not found in owner's private Collection %v: %v", ownerCollection, assetDeleteInput.ID) } // delete the asset from state @@ -456,12 +464,7 @@ func (s *SmartContract) DeleteAsset(ctx contractapi.TransactionContextInterface) } // Finally, delete private details of asset - ownerCollection, err := getCollectionName(ctx) // Get owners collection - if err != nil { - return fmt.Errorf("failed to infer private collection name for the org: %v", err) - } - - err = ctx.GetStub().DelPrivateData(ownerCollection, assetDeleteInput.ID) // Delete the asset + err = ctx.GetStub().DelPrivateData(ownerCollection, assetDeleteInput.ID) if err != nil { return err }