diff --git a/.github/actions/test-network-setup/action.yaml b/.github/actions/test-network-setup/action.yaml index ed6587c6..f36169b2 100644 --- a/.github/actions/test-network-setup/action.yaml +++ b/.github/actions/test-network-setup/action.yaml @@ -10,6 +10,12 @@ inputs: java-version: description: Version of JDK default: 11.x + fabric-version: + description: Version of Hyperledger Fabric + default: 2.5.0-alpha3 + ca-version: + description: Version of Hyperledger Fabric CA + default: 1.5.6-beta3 runs: using: "composite" @@ -35,12 +41,15 @@ runs: - name: Install fabric CLI shell: bash run: | - curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install-fabric.sh | bash -s -- binary + curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install-fabric.sh \ + | bash -s -- binary --fabric-version ${{ inputs.fabric-version }} --ca-version ${{ inputs.ca-version }} echo ${PWD}/bin >> $GITHUB_PATH - name: Pull Fabric Docker Images shell: bash - run: curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install-fabric.sh | bash -s -- docker + run: | + curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install-fabric.sh \ + | bash -s -- docker --fabric-version ${{ inputs.fabric-version }} --ca-version ${{ inputs.ca-version }} - name: Install retry CLI shell: bash diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 4ab1ff67..028fea68 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -7,9 +7,9 @@ run-name: ${{ github.actor }} is linting fabric-samples 🎉 on: workflow_dispatch: push: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] pull_request: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] env: GO_VER: 1.18.3 diff --git a/.github/workflows/rest-sample.yaml b/.github/workflows/rest-sample.yaml index ff8659f8..f2cae6eb 100644 --- a/.github/workflows/rest-sample.yaml +++ b/.github/workflows/rest-sample.yaml @@ -10,10 +10,10 @@ env: on: workflow_dispatch: push: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] paths: [ "asset-transfer-basic/rest-api-typescript/**" ] pull_request: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] paths: [ "asset-transfer-basic/rest-api-typescript/**" ] jobs: diff --git a/.github/workflows/test-network-basic.yaml b/.github/workflows/test-network-basic.yaml index eb20869d..72b7c1db 100644 --- a/.github/workflows/test-network-basic.yaml +++ b/.github/workflows/test-network-basic.yaml @@ -7,9 +7,9 @@ run-name: ${{ github.actor }} is running the Test Network Basic tests 🔎 on: workflow_dispatch: push: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] pull_request: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] jobs: basic: diff --git a/.github/workflows/test-network-events.yaml b/.github/workflows/test-network-events.yaml index a1e3e996..4a6ebd99 100644 --- a/.github/workflows/test-network-events.yaml +++ b/.github/workflows/test-network-events.yaml @@ -7,9 +7,9 @@ run-name: ${{ github.actor }} is running the Test Network Events tests 💡 on: workflow_dispatch: push: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] pull_request: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] jobs: events: diff --git a/.github/workflows/test-network-gateway.yaml b/.github/workflows/test-network-gateway.yaml index a5f195ce..06477397 100644 --- a/.github/workflows/test-network-gateway.yaml +++ b/.github/workflows/test-network-gateway.yaml @@ -7,9 +7,9 @@ run-name: ${{ github.actor }} is running the Test Network Gateway tests 🖥️ on: workflow_dispatch: push: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] pull_request: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] jobs: gateway: diff --git a/.github/workflows/test-network-hsm.yaml b/.github/workflows/test-network-hsm.yaml index 51093488..189a77a1 100644 --- a/.github/workflows/test-network-hsm.yaml +++ b/.github/workflows/test-network-hsm.yaml @@ -7,9 +7,9 @@ run-name: ${{ github.actor }} is running the Test Network HSM tests 🍏 on: workflow_dispatch: push: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] pull_request: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] jobs: hsm: diff --git a/.github/workflows/test-network-k8s.yaml b/.github/workflows/test-network-k8s.yaml index cadb4376..7898e820 100644 --- a/.github/workflows/test-network-k8s.yaml +++ b/.github/workflows/test-network-k8s.yaml @@ -7,9 +7,9 @@ run-name: ${{ github.actor }} is testing the Kubernetes Test Network 🍒 on: workflow_dispatch: push: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] pull_request: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] jobs: ccaas-java: diff --git a/.github/workflows/test-network-ledger.yaml b/.github/workflows/test-network-ledger.yaml index 60c566c9..5bc6669b 100644 --- a/.github/workflows/test-network-ledger.yaml +++ b/.github/workflows/test-network-ledger.yaml @@ -7,9 +7,9 @@ run-name: ${{ github.actor }} is running the Test Network Ledger tests 🥑 on: workflow_dispatch: push: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] pull_request: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] jobs: basic: diff --git a/.github/workflows/test-network-off-chain.yaml b/.github/workflows/test-network-off-chain.yaml index fc10b968..1e5840d4 100644 --- a/.github/workflows/test-network-off-chain.yaml +++ b/.github/workflows/test-network-off-chain.yaml @@ -7,9 +7,9 @@ run-name: ${{ github.actor }} is running the Test Network Off Chain tests 🍔 on: workflow_dispatch: push: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] pull_request: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] jobs: off-chain: diff --git a/.github/workflows/test-network-private.yaml b/.github/workflows/test-network-private.yaml index b8185e4d..36ec02de 100644 --- a/.github/workflows/test-network-private.yaml +++ b/.github/workflows/test-network-private.yaml @@ -7,9 +7,9 @@ run-name: ${{ github.actor }} is running the Test Network Private tests 🔒 on: workflow_dispatch: push: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] pull_request: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] jobs: private: diff --git a/.github/workflows/test-network-sbe.yaml b/.github/workflows/test-network-sbe.yaml index 37682f5c..51a12694 100644 --- a/.github/workflows/test-network-sbe.yaml +++ b/.github/workflows/test-network-sbe.yaml @@ -7,9 +7,9 @@ run-name: ${{ github.actor }} is running the Test Network SBE tests 🎵 on: workflow_dispatch: push: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] pull_request: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] jobs: SBE: diff --git a/.github/workflows/test-network-secured.yaml b/.github/workflows/test-network-secured.yaml index a0df52ce..df075158 100644 --- a/.github/workflows/test-network-secured.yaml +++ b/.github/workflows/test-network-secured.yaml @@ -7,9 +7,9 @@ run-name: ${{ github.actor }} is running the Test Network Secured tests 🔔 on: workflow_dispatch: push: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] pull_request: - branches: [ "main" ] + branches: [ "main", "release-2.5" ] jobs: secured: diff --git a/asset-transfer-basic/rest-api-typescript/package-lock.json b/asset-transfer-basic/rest-api-typescript/package-lock.json index 42448c55..e0ad8046 100644 --- a/asset-transfer-basic/rest-api-typescript/package-lock.json +++ b/asset-transfer-basic/rest-api-typescript/package-lock.json @@ -2567,9 +2567,9 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, "node_modules/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true }, "node_modules/cors": { @@ -5272,13 +5272,10 @@ "dev": true }, "node_modules/json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, "bin": { "json5": "lib/cli.js" }, @@ -5547,9 +5544,9 @@ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -5558,12 +5555,6 @@ "node": "*" } }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, "node_modules/moment": { "version": "2.29.4", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", @@ -9677,9 +9668,9 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, "cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true }, "cors": { @@ -11718,13 +11709,10 @@ "dev": true }, "json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true }, "jsrsasign": { "version": "10.5.26", @@ -11935,20 +11923,14 @@ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, "moment": { "version": "2.29.4", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", diff --git a/asset-transfer-private-data/application-gateway-typescript/src/app.ts b/asset-transfer-private-data/application-gateway-typescript/src/app.ts index 0513807d..ac292330 100644 --- a/asset-transfer-private-data/application-gateway-typescript/src/app.ts +++ b/asset-transfer-private-data/application-gateway-typescript/src/app.ts @@ -129,6 +129,10 @@ async function main(): Promise { // Delete AssetID2 as Org1. await deleteAsset(contractOrg1, assetID2); + + // Trigger a purge of the private data for the asset + // The previous delete is optinal if purge is used + await purgeAsset(contractOrg1, assetID2); } finally { gatewayOrg1.close(); clientOrg1.close(); @@ -261,6 +265,17 @@ async function deleteAsset(contract: Contract, assetID: string): Promise { console.log('*** Transaction committed successfully'); } + +async function purgeAsset(contract: Contract, assetID: string): Promise { + console.log('\n--> Submit Transaction: PurgeAsset, ID:', assetID); + const dataForPurge = { assetID }; + await contract.submit('PurgeAsset', { + transientData: { asset_purge: JSON.stringify(dataForPurge) }, + }); + + console.log('*** Transaction committed successfully'); +} + async function readAssetPrivateDetails(contract: Contract, assetID: string, collectionName: string): Promise { console.log(`\n--> Evaluate Transaction: ReadAssetPrivateDetails from ${collectionName}, ID: ${assetID}`); 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 92c10424..a377e57c 100644 --- a/asset-transfer-private-data/chaincode-go/chaincode/asset_transfer.go +++ b/asset-transfer-private-data/chaincode-go/chaincode/asset_transfer.go @@ -475,6 +475,68 @@ func (s *SmartContract) DeleteAsset(ctx contractapi.TransactionContextInterface) } +// PurgeAsset can be used by the owner of the asset to delete the asset +// Trigger removal of the asset +func (s *SmartContract) PurgeAsset(ctx contractapi.TransactionContextInterface) error { + + transientMap, err := ctx.GetStub().GetTransient() + if err != nil { + return fmt.Errorf("Error getting transient: %v", err) + } + + // Asset properties are private, therefore they get passed in transient field + transientDeleteJSON, ok := transientMap["asset_purge"] + if !ok { + return fmt.Errorf("asset to purge not found in the transient map") + } + + type assetPurge struct { + ID string `json:"assetID"` + } + + var assetPurgeInput assetPurge + err = json.Unmarshal(transientDeleteJSON, &assetPurgeInput) + if err != nil { + return fmt.Errorf("failed to unmarshal JSON: %v", err) + } + + if len(assetPurgeInput.ID) == 0 { + return fmt.Errorf("assetID field must be a non-empty string") + } + + // Verify that the client is submitting request to peer in their organization + err = verifyClientOrgMatchesPeerOrg(ctx) + if err != nil { + return fmt.Errorf("PurgeAsset cannot be performed: Error %v", err) + } + + log.Printf("Purging Asset: %v", assetPurgeInput.ID) + + // Note that there is no check here to see if the id exist; it might have been 'deleted' already + // so a check here is pointless. We would need to call purge irrespective of the result + // A delete can be called before purge, but is not essential + + ownerCollection, err := getCollectionName(ctx) // Get owners collection + if err != nil { + return fmt.Errorf("failed to infer private collection name for the org: %v", err) + } + + // delete the asset from state + err = ctx.GetStub().PurgePrivateData(assetCollection, assetPurgeInput.ID) + if err != nil { + return fmt.Errorf("failed to purge state from asset collection: %v", err) + } + + // Finally, delete private details of asset + err = ctx.GetStub().PurgePrivateData(ownerCollection, assetPurgeInput.ID) + if err != nil { + return fmt.Errorf("failed to purge state from owner collection: %v", err) + } + + return nil + +} + // DeleteTranferAgreement can be used by the buyer to withdraw a proposal from // the asset collection and from his own collection. func (s *SmartContract) DeleteTranferAgreement(ctx contractapi.TransactionContextInterface) error { diff --git a/asset-transfer-private-data/chaincode-go/go.mod b/asset-transfer-private-data/chaincode-go/go.mod index ba25be99..305208de 100644 --- a/asset-transfer-private-data/chaincode-go/go.mod +++ b/asset-transfer-private-data/chaincode-go/go.mod @@ -3,7 +3,7 @@ module github.com/hyperledger/fabric-samples/asset-transfer-private-data/chainco go 1.17 require ( - github.com/hyperledger/fabric-chaincode-go v0.0.0-20220720122508-9207360bbddd + github.com/hyperledger/fabric-chaincode-go v0.0.0-20220920210243-7bc6fa0dd58b github.com/hyperledger/fabric-contract-api-go v1.2.0 github.com/hyperledger/fabric-protos-go v0.0.0-20220613214546-bf864f01d75e github.com/stretchr/testify v1.8.0 diff --git a/asset-transfer-private-data/chaincode-go/go.sum b/asset-transfer-private-data/chaincode-go/go.sum index 6d35e832..f352bca5 100644 --- a/asset-transfer-private-data/chaincode-go/go.sum +++ b/asset-transfer-private-data/chaincode-go/go.sum @@ -165,6 +165,8 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hyperledger/fabric-chaincode-go v0.0.0-20220720122508-9207360bbddd h1:AIa0b7UPrt8e1YN4/68vhNnPxy/Mrgq9d2bYJ6O/KTE= github.com/hyperledger/fabric-chaincode-go v0.0.0-20220720122508-9207360bbddd/go.mod h1:OxME3M0bbgoWYHpXIVMzpbXgFqrTZnFmlH0Cpml54m0= +github.com/hyperledger/fabric-chaincode-go v0.0.0-20220920210243-7bc6fa0dd58b h1:MGT5rdajc4zbsbU7yMzkLJmsiRwJk5gBX5OdpU117Bg= +github.com/hyperledger/fabric-chaincode-go v0.0.0-20220920210243-7bc6fa0dd58b/go.mod h1:OxME3M0bbgoWYHpXIVMzpbXgFqrTZnFmlH0Cpml54m0= github.com/hyperledger/fabric-contract-api-go v1.2.0 h1:BmArPRmTjiC2brHk2FNlDoJ8bOI0ExKZhj2YqWAiv5o= github.com/hyperledger/fabric-contract-api-go v1.2.0/go.mod h1:GU2NV95E5LNkFTCL3xcPgXzi8QNLXBZhx7DGnKskuqw= github.com/hyperledger/fabric-protos-go v0.0.0-20220613214546-bf864f01d75e h1:Ae2p0e+v5ekrl4KgkbCStBTSoV67Cg9fPkEWrv0f3nk= diff --git a/asset-transfer-private-data/chaincode-java/build.gradle b/asset-transfer-private-data/chaincode-java/build.gradle index bc59a38f..e5acd742 100644 --- a/asset-transfer-private-data/chaincode-java/build.gradle +++ b/asset-transfer-private-data/chaincode-java/build.gradle @@ -14,7 +14,7 @@ version '1.0-SNAPSHOT' dependencies { - implementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.+' + implementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.5.+' implementation 'org.json:json:+' testImplementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.+' diff --git a/asset-transfer-private-data/chaincode-java/src/main/java/org/hyperledger/fabric/samples/privatedata/AssetTransfer.java b/asset-transfer-private-data/chaincode-java/src/main/java/org/hyperledger/fabric/samples/privatedata/AssetTransfer.java index 94a261c4..eac72319 100644 --- a/asset-transfer-private-data/chaincode-java/src/main/java/org/hyperledger/fabric/samples/privatedata/AssetTransfer.java +++ b/asset-transfer-private-data/chaincode-java/src/main/java/org/hyperledger/fabric/samples/privatedata/AssetTransfer.java @@ -488,6 +488,9 @@ public final class AssetTransfer implements ContractInterface { * Deletes a asset & related details from the ledger. * Input in transient map: asset_delete * + * This deletes the private data, but does not trigger an immediate cleanup + * of the history. To specifically force removal right now use purge + * * @param ctx the transaction context */ @Transaction(intent = Transaction.TYPE.SUBMIT) @@ -539,6 +542,53 @@ public final class AssetTransfer implements ContractInterface { stub.delPrivateData(ownersCollectionName, assetID); } + /** + * Purges the history of the asset from Private Data + * (delete does not need to be called as well) + * Input in transient map: asset_delete + * + * @param ctx the transaction context + */ + @Transaction(intent = Transaction.TYPE.SUBMIT) + public void PurgeAsset(final Context ctx) { + ChaincodeStub stub = ctx.getStub(); + Map transientMap = ctx.getStub().getTransient(); + if (!transientMap.containsKey("asset_purge")) { + String errorMessage = String.format("PurgeAsset call must specify 'asset_purge' in Transient map input"); + System.err.println(errorMessage); + throw new ChaincodeException(errorMessage, AssetTransferErrors.INCOMPLETE_INPUT.toString()); + } + + byte[] transientAssetJSON = transientMap.get("asset_purge"); + final String assetID; + + try { + JSONObject json = new JSONObject(new String(transientAssetJSON, UTF_8)); + assetID = json.getString("assetID"); + + } catch (Exception err) { + String errorMessage = String.format("TransientMap deserialized error: %s ", err); + System.err.println(errorMessage); + throw new ChaincodeException(errorMessage, AssetTransferErrors.INCOMPLETE_INPUT.toString()); + } + + // Note that there is no check here to see if the id exist; it might have been 'deleted' already + // so a check here is pointless. We would need to call purge irrespective of the result + // A delete can be called before purge, but is not essential + + String ownersCollectionName = getCollectionName(ctx); + verifyClientOrgMatchesPeerOrg(ctx); + + // delete the key from asset collection + System.out.printf("PurgeAsset: collection %s, ID %s\n", ASSET_COLLECTION_NAME, assetID); + stub.purgePrivateData(ASSET_COLLECTION_NAME, assetID); + + // Finally, delete private details of asset + System.out.printf("PurgeAsset: collection %s, ID %s\n", ownersCollectionName, assetID); + stub.purgePrivateData(ownersCollectionName, assetID); + } + + // Used by TransferAsset to verify that the transfer is being initiated by the owner and that // the buyer has agreed to the same appraisal value as the owner private void verifyAgreement(final Context ctx, final String assetID, final String owner, final String buyerMSP) { diff --git a/ci/scripts/lint-java.sh b/ci/scripts/lint-java.sh index 327a91e7..472b8571 100755 --- a/ci/scripts/lint-java.sh +++ b/ci/scripts/lint-java.sh @@ -8,6 +8,7 @@ function print() { echo -e "${GREEN}${1}${NC}" } +# remove the java asset-private-data until the publishing issues have been resolved dirs=("$(find . -name "*-java" -type d -not -path '*/.*')") for dir in $dirs; do print "Linting $dir" diff --git a/commercial-paper/organization/digibank/contract-java/src/main/java/org/example/CommercialPaperContract.java b/commercial-paper/organization/digibank/contract-java/src/main/java/org/example/CommercialPaperContract.java index a75f47e3..a46a7038 100644 --- a/commercial-paper/organization/digibank/contract-java/src/main/java/org/example/CommercialPaperContract.java +++ b/commercial-paper/organization/digibank/contract-java/src/main/java/org/example/CommercialPaperContract.java @@ -107,7 +107,7 @@ public class CommercialPaperContract implements ContractInterface { String newOwner, int price, String purchaseDateTime) { // Retrieve the current paper using key fields provided - String paperKey = State.makeKey(new String[] { paperNumber }); + String paperKey = State.makeKey(new String[] { issuer, paperNumber }); CommercialPaper paper = ctx.paperList.getPaper(paperKey); // Validate current owner @@ -146,7 +146,7 @@ public class CommercialPaperContract implements ContractInterface { public CommercialPaper redeem(CommercialPaperContext ctx, String issuer, String paperNumber, String redeemingOwner, String redeemDateTime) { - String paperKey = CommercialPaper.makeKey(new String[] { paperNumber }); + String paperKey = CommercialPaper.makeKey(new String[] { issuer, paperNumber }); CommercialPaper paper = ctx.paperList.getPaper(paperKey); diff --git a/commercial-paper/organization/magnetocorp/contract-java/src/main/java/org/example/CommercialPaperContract.java b/commercial-paper/organization/magnetocorp/contract-java/src/main/java/org/example/CommercialPaperContract.java index a781c360..a04e62db 100644 --- a/commercial-paper/organization/magnetocorp/contract-java/src/main/java/org/example/CommercialPaperContract.java +++ b/commercial-paper/organization/magnetocorp/contract-java/src/main/java/org/example/CommercialPaperContract.java @@ -107,7 +107,7 @@ public class CommercialPaperContract implements ContractInterface { String newOwner, int price, String purchaseDateTime) { // Retrieve the current paper using key fields provided - String paperKey = State.makeKey(new String[] { paperNumber }); + String paperKey = State.makeKey(new String[] { issuer, paperNumber }); CommercialPaper paper = ctx.paperList.getPaper(paperKey); // Validate current owner @@ -146,7 +146,7 @@ public class CommercialPaperContract implements ContractInterface { public CommercialPaper redeem(CommercialPaperContext ctx, String issuer, String paperNumber, String redeemingOwner, String redeemDateTime) { - String paperKey = CommercialPaper.makeKey(new String[] { paperNumber }); + String paperKey = CommercialPaper.makeKey(new String[] {issuer, paperNumber }); CommercialPaper paper = ctx.paperList.getPaper(paperKey); diff --git a/interest_rate_swaps/network/configtx.yaml b/interest_rate_swaps/network/configtx.yaml index 2d1c6cae..43948e72 100644 --- a/interest_rate_swaps/network/configtx.yaml +++ b/interest_rate_swaps/network/configtx.yaml @@ -269,13 +269,11 @@ Capabilities: # used with prior release orderers. # Set the value of the capability to true to require it. Application: &ApplicationCapabilities - # V2_0 application capability ensures that peers behave according - # to v2.0 application capabilities. Peers from - # prior releases would behave in an incompatible way, and are therefore - # not able to participate in channels at v2.0 application capability. - # Prior to enabling V2.0 application capabilities, ensure that all - # peers on channel are at v2.0.0 or later. - V2_0: true + # V2.5 for Application enables the new non-backwards compatible + # features of fabric v2.5, namely the ability to purge private data. + # Prior to enabling V2.5 application capabilities, ensure that all + # peers on a channel are at v2.5.0 or later. + V2_5: true ################################################################################ # diff --git a/test-network-nano-bash/configtx.yaml b/test-network-nano-bash/configtx.yaml index e1634014..0a0c05d6 100644 --- a/test-network-nano-bash/configtx.yaml +++ b/test-network-nano-bash/configtx.yaml @@ -163,13 +163,11 @@ Capabilities: # used with prior release orderers. # Set the value of the capability to true to require it. Application: &ApplicationCapabilities - # V2_0 application capability ensures that peers behave according - # to v2.0 application capabilities. Peers from - # prior releases would behave in an incompatible way, and are therefore - # not able to participate in channels at v2.0 application capability. - # Prior to enabling V2.0 application capabilities, ensure that all - # peers on channel are at v2.0.0 or later. - V2_0: true + # V2.5 for Application enables the new non-backwards compatible + # features of fabric v2.5, namely the ability to purge private data. + # Prior to enabling V2.5 application capabilities, ensure that all + # peers on a channel are at v2.5.0 or later. + V2_5: true ################################################################################ # diff --git a/test-network/configtx/configtx.yaml b/test-network/configtx/configtx.yaml index 48bd1d75..01fb15fb 100644 --- a/test-network/configtx/configtx.yaml +++ b/test-network/configtx/configtx.yaml @@ -129,6 +129,7 @@ Capabilities: # Prior to enabling V2.0 channel capabilities, ensure that all # orderers and peers on a channel are at v2.0.0 or later. V2_0: true + # Orderer capabilities apply only to the orderers, and may be safely # used with prior release peers. @@ -146,13 +147,11 @@ Capabilities: # used with prior release orderers. # Set the value of the capability to true to require it. Application: &ApplicationCapabilities - # V2_0 application capability ensures that peers behave according - # to v2.0 application capabilities. Peers from - # prior releases would behave in an incompatible way, and are therefore - # not able to participate in channels at v2.0 application capability. - # Prior to enabling V2.0 application capabilities, ensure that all - # peers on channel are at v2.0.0 or later. - V2_0: true + # V2.5 for Application enables the new non-backwards compatible + # features of fabric v2.5, namely the ability to purge private data. + # Prior to enabling V2.5 application capabilities, ensure that all + # peers on a channel are at v2.5.0 or later. + V2_5: true ################################################################################ #