From ec8123cf954b09ba8cb213c7332dfe82224c351f Mon Sep 17 00:00:00 2001 From: Peter Somogyvari Date: Thu, 6 Jun 2024 09:49:19 -0700 Subject: [PATCH] feat(connector-fabric): drop support for Fabric v1.x BREAKING CHANGE: The Open API specification that has the enums for ledger versions will no longer have an option for Fabric v1.x This means that in the core-api package the LedgerType enum has changes which means that code that depends on that enum value will need to be updated. Fabric v1.x has had unmaintained dependencies associated with it such as the native grpc package that stopped receiving security updates years ago and therefore it's dangerous to have around. There are also some issues with Fabric v1.x that make the AIO image flaky which also makes the relevant tests flaky due to which we couldn't run the v1.x Fabric tests on the CI for a while now anyway. In order to reduce the CI resource usage and our own maintenance burden I suggest that we get rid of the Fabric v1.x support meaning that we can eliminate the AIO image build and some code complexity from the test ledger code as well. In addition some old fixtures can be removed that the tests were using. Overall a net-positive as deleting code without losing functionality (that we care about) is always a plus. Signed-off-by: Peter Somogyvari --- .github/workflows/ci.yaml | 7 - .../workflows/fabric-all-in-one-publish.yaml | 60 ---- .../src/main/typescript/supply-chain-app.ts | 2 +- .../src/main/json/openapi.json | 1 - .../openapitools/client/models/LedgerType.kt | 5 +- .../generated/openapi/typescript-axios/api.ts | 1 - .../.gitignore | 3 - .../hello-world-contract-fabric-v14/README.md | 35 --- .../hello-world-contract-go-source.ts | 105 ------- .../deploy-cc-from-golang-source.test.ts | 260 ------------------ .../run-transaction-endpoint-v1.test.ts | 226 --------------- .../openapi/openapi-validation-go.test.ts | 62 +---- .../fabric/fabric-test-ledger-v1.ts | 42 +-- tools/docker/fabric-all-in-one/README.md | 28 -- 14 files changed, 10 insertions(+), 827 deletions(-) delete mode 100644 .github/workflows/fabric-all-in-one-publish.yaml delete mode 100644 packages/cactus-plugin-ledger-connector-fabric/.gitignore delete mode 100644 packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/fixtures/go/hello-world-contract-fabric-v14/README.md delete mode 100644 packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/fixtures/go/hello-world-contract-fabric-v14/hello-world-contract-go-source.ts delete mode 100644 packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/deploy-cc-from-golang-source.test.ts delete mode 100644 packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f2c3325e16..ff13c33769 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -2297,13 +2297,6 @@ jobs: - name: ghcr.io/hyperledger/cactus-example-supply-chain-app run: DOCKER_BUILDKIT=1 docker build . -f ./examples/cactus-example-supply-chain-backend/Dockerfile -t cactus-example-supply-chain-app - ghcr-fabric-all-in-one: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4.1.1 - - name: ghcr.io/hyperledger/cactus-fabric-all-in-one - run: DOCKER_BUILDKIT=1 docker build ./tools/docker/fabric-all-in-one/ -f ./tools/docker/fabric-all-in-one/Dockerfile_v1.4.x - ghcr-fabric2-all-in-one: runs-on: ubuntu-22.04 steps: diff --git a/.github/workflows/fabric-all-in-one-publish.yaml b/.github/workflows/fabric-all-in-one-publish.yaml deleted file mode 100644 index 71e7db3efb..0000000000 --- a/.github/workflows/fabric-all-in-one-publish.yaml +++ /dev/null @@ -1,60 +0,0 @@ -name: fabric-all-in-one-publish - -on: - push: - # Publish `main` as Docker `latest` image. - branches: - - main - - # Publish `v1.2.3` tags as releases. - tags: - - v* - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -env: - IMAGE_NAME: cactus-fabric-all-in-one - -jobs: - # Push image to GitHub Packages. - # See also https://docs.docker.com/docker-hub/builds/ - build-tag-push-container: - runs-on: ubuntu-22.04 - env: - DOCKER_BUILDKIT: 1 - DOCKERFILE_PATH: ./tools/docker/fabric-all-in-one/Dockerfile_v1.4.x - DOCKER_BUILD_DIR: ./tools/docker/fabric-all-in-one/ - permissions: - packages: write - contents: read - - steps: - - uses: actions/checkout@v4.1.1 - - - name: Build image - run: docker build "$DOCKER_BUILD_DIR" --file "$DOCKERFILE_PATH" --tag "$IMAGE_NAME" --label "runnumber=${GITHUB_RUN_ID}" - - - name: Log in to registry - # This is where you will update the PAT to GITHUB_TOKEN - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin - - - name: Push image - run: | - SHORTHASH=$(git rev-parse --short "$GITHUB_SHA") - TODAYS_DATE="$(date +%F)" - DOCKER_TAG="$TODAYS_DATE-$SHORTHASH" - IMAGE_ID="ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME" - # Change all uppercase to lowercase - IMAGE_ID=$(echo "$IMAGE_ID" | tr '[:upper:]' '[:lower:]') - # Strip git ref prefix from version - VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') - # Strip "v" prefix from tag name - [[ "${{ github.ref }}" == "refs/tags/*" ]] && VERSION="${VERSION//^v//}" - # Do not use the `latest` tag at all, tag with date + git short hash if there is no git tag - [ "$VERSION" == "main" ] && VERSION=$DOCKER_TAG - echo IMAGE_ID="$IMAGE_ID" - echo VERSION="$VERSION" - docker tag "$IMAGE_NAME" "$IMAGE_ID:$VERSION" - docker push "$IMAGE_ID:$VERSION" diff --git a/examples/cactus-example-supply-chain-backend/src/main/typescript/supply-chain-app.ts b/examples/cactus-example-supply-chain-backend/src/main/typescript/supply-chain-app.ts index 56e7b7d199..3ab9eeba07 100644 --- a/examples/cactus-example-supply-chain-backend/src/main/typescript/supply-chain-app.ts +++ b/examples/cactus-example-supply-chain-backend/src/main/typescript/supply-chain-app.ts @@ -542,7 +542,7 @@ export class SupplyChainApp { const ledger3: Ledger = { id: "FabricDemoLedger", - ledgerType: LedgerType.Fabric14X, + ledgerType: LedgerType.Fabric2, }; cactusNodeC.ledgerIds.push(ledger3.id); diff --git a/packages/cactus-core-api/src/main/json/openapi.json b/packages/cactus-core-api/src/main/json/openapi.json index dc1e45be8f..d0746fb402 100644 --- a/packages/cactus-core-api/src/main/json/openapi.json +++ b/packages/cactus-core-api/src/main/json/openapi.json @@ -186,7 +186,6 @@ "BESU_2X", "BURROW_0X", "CORDA_4X", - "FABRIC_14X", "FABRIC_2", "QUORUM_2X", "SAWTOOTH_1X" diff --git a/packages/cactus-core-api/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/LedgerType.kt b/packages/cactus-core-api/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/LedgerType.kt index c52055dea9..dabf585c0c 100644 --- a/packages/cactus-core-api/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/LedgerType.kt +++ b/packages/cactus-core-api/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/LedgerType.kt @@ -22,7 +22,7 @@ import com.squareup.moshi.JsonClass /** * Enumerates the different ledger vendors and their major versions encoded within the name of the LedgerType. For example \"BESU_1X\" involves all of the [1.0.0;2.0.0) where 1.0.0 is included and anything up until, but not 2.0.0. See: https://stackoverflow.com/a/4396303/698470 for further explanation. * - * Values: bESU1X,bESU2X,bURROW0X,cORDA4X,fABRIC14X,fABRIC2,qUORUM2X,sAWTOOTH1X + * Values: bESU1X,bESU2X,bURROW0X,cORDA4X,fABRIC2,qUORUM2X,sAWTOOTH1X */ @JsonClass(generateAdapter = false) @@ -40,9 +40,6 @@ enum class LedgerType(val value: kotlin.String) { @Json(name = "CORDA_4X") cORDA4X("CORDA_4X"), - @Json(name = "FABRIC_14X") - fABRIC14X("FABRIC_14X"), - @Json(name = "FABRIC_2") fABRIC2("FABRIC_2"), diff --git a/packages/cactus-core-api/src/main/typescript/generated/openapi/typescript-axios/api.ts b/packages/cactus-core-api/src/main/typescript/generated/openapi/typescript-axios/api.ts index 34ce3b3146..59bf9f2cbf 100644 --- a/packages/cactus-core-api/src/main/typescript/generated/openapi/typescript-axios/api.ts +++ b/packages/cactus-core-api/src/main/typescript/generated/openapi/typescript-axios/api.ts @@ -524,7 +524,6 @@ export const LedgerType = { Besu2X: 'BESU_2X', Burrow0X: 'BURROW_0X', Corda4X: 'CORDA_4X', - Fabric14X: 'FABRIC_14X', Fabric2: 'FABRIC_2', Quorum2X: 'QUORUM_2X', Sawtooth1X: 'SAWTOOTH_1X' diff --git a/packages/cactus-plugin-ledger-connector-fabric/.gitignore b/packages/cactus-plugin-ledger-connector-fabric/.gitignore deleted file mode 100644 index 99a7101666..0000000000 --- a/packages/cactus-plugin-ledger-connector-fabric/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -src/test/typescript/fixtures/go/hello-world-contract-fabric-v14/hello-world-contract.go -src/test/typescript/fixtures/go/hello-world-contract-fabric-v14/go.mod -src/test/typescript/fixtures/go/hello-world-contract-fabric-v14/go.sum diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/fixtures/go/hello-world-contract-fabric-v14/README.md b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/fixtures/go/hello-world-contract-fabric-v14/README.md deleted file mode 100644 index c17b5a72b2..0000000000 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/fixtures/go/hello-world-contract-fabric-v14/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Fabirc v1.4.x Hello World Contract - - -### Building Locally with v1.4.x ChainCode - -This is useful when you want to avoid having to deal with $GOPATH and friends -and instead just keep everything self-contained in a single directory which is -what we want from an ideal test case, so here's how to do it on the terminal: - -```sh - -# Make sure you are in the right working directory -cd packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/fixtures/go/hello-world-contract-fabric-v14 - -# Export the go source code to the file system into an actual .go file -npx ts-node ./hello-world-contract-go-source.ts - -# Ensure the Go Modules feature is used -export GO111MODULE=on - -# If go.mod file is not present, -# otherwise this can be omitted -go mod init hello-world-contract - -# This will pin on the latest 1.4 commit -go get github.com/hyperledger/fabric@v1.4.8 - -go mod tidy -go mod vendor - -# Now you can just build it like any other go project -# and deploy the resulting binary as a chain code -# contract on a Fabric v.1.4.x ledger -go build -``` diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/fixtures/go/hello-world-contract-fabric-v14/hello-world-contract-go-source.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/fixtures/go/hello-world-contract-fabric-v14/hello-world-contract-go-source.ts deleted file mode 100644 index afc3d63db4..0000000000 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/fixtures/go/hello-world-contract-fabric-v14/hello-world-contract-go-source.ts +++ /dev/null @@ -1,105 +0,0 @@ -export const HELLO_WORLD_CONTRACT_GO_SOURCE = `package main - -import ( - "fmt" - - "github.com/hyperledger/fabric/core/chaincode/shim" - "github.com/hyperledger/fabric/protos/peer" -) - -// SimpleAsset implements a simple chaincode to manage an asset -type SimpleAsset struct { -} - -// Init is called during chaincode instantiation to initialize any -// data. Note that chaincode upgrade also calls this function to reset -// or to migrate data. -func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response { - // Get the args from the transaction proposal - args := stub.GetStringArgs() - if len(args) != 2 { - return shim.Error("Incorrect arguments. Expecting a key and a value") - } - - // Set up any variables or assets here by calling stub.PutState() - - // We store the key and the value on the ledger - err := stub.PutState(args[0], []byte(args[1])) - if err != nil { - return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0])) - } - return shim.Success(nil) -} - -// Invoke is called per transaction on the chaincode. Each transaction is -// either a 'get' or a 'set' on the asset created by Init function. The Set -// method may create a new asset by specifying a new key-value pair. -func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response { - // Extract the function and args from the transaction proposal - fn, args := stub.GetFunctionAndParameters() - - var result string - var err error - if fn == "set" { - result, err = set(stub, args) - } else { // assume 'get' even if fn is nil - result, err = get(stub, args) - } - if err != nil { - return shim.Error(err.Error()) - } - - // Return the result as success payload - return shim.Success([]byte(result)) -} - -// Set stores the asset (both key and value) on the ledger. If the key exists, -// it will override the value with the new one -func set(stub shim.ChaincodeStubInterface, args []string) (string, error) { - if len(args) != 2 { - return "", fmt.Errorf("Incorrect arguments. Expecting a key and a value") - } - - err := stub.PutState(args[0], []byte(args[1])) - if err != nil { - return "", fmt.Errorf("Failed to set asset: %s", args[0]) - } - return args[1], nil -} - -// Get returns the value of the specified asset key -func get(stub shim.ChaincodeStubInterface, args []string) (string, error) { - if len(args) != 1 { - return "", fmt.Errorf("Incorrect arguments. Expecting a key") - } - - value, err := stub.GetState(args[0]) - if err != nil { - return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err) - } - if value == nil { - return "", fmt.Errorf("Asset not found: %s", args[0]) - } - return string(value), nil -} - -// main function starts up the chaincode in the container during instantiate -func main() { - if err := shim.Start(new(SimpleAsset)); err != nil { - fmt.Printf("Error starting SimpleAsset chaincode: %s", err) - } -} - -`; - -const exportSourceToFs = async () => { - const path = await import("path"); - const fs = await import("fs"); - const fileName = "./hello-world-contract.go"; - const scriptPath = path.join(__dirname, fileName); - fs.writeFileSync(scriptPath, HELLO_WORLD_CONTRACT_GO_SOURCE); -}; - -if (require.main === module) { - exportSourceToFs(); -} diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/deploy-cc-from-golang-source.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/deploy-cc-from-golang-source.test.ts deleted file mode 100644 index fcdf0eeca5..0000000000 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/deploy-cc-from-golang-source.test.ts +++ /dev/null @@ -1,260 +0,0 @@ -import { AddressInfo } from "net"; -import http from "http"; - -import test, { Test } from "tape-promise/tape"; -import { v4 as uuidv4 } from "uuid"; - -import express from "express"; -import bodyParser from "body-parser"; - -import { - Containers, - FabricTestLedgerV1, - pruneDockerAllIfGithubAction, -} from "@hyperledger/cactus-test-tooling"; - -import { - IListenOptions, - LogLevelDesc, - Servers, -} from "@hyperledger/cactus-common"; -import { PluginRegistry } from "@hyperledger/cactus-core"; - -import { - DefaultEventHandlerStrategy, - FabricContractInvocationType, - PluginLedgerConnectorFabric, - SSHExecCommandResponse, -} from "../../../../main/typescript/public-api"; - -import { HELLO_WORLD_CONTRACT_GO_SOURCE } from "../../fixtures/go/hello-world-contract-fabric-v14/hello-world-contract-go-source"; - -import { - DefaultApi as FabricApi, - FabricSigningCredential, -} from "../../../../main/typescript/public-api"; - -import { IPluginLedgerConnectorFabricOptions } from "../../../../main/typescript/plugin-ledger-connector-fabric"; - -import { DiscoveryOptions } from "fabric-network"; -import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; -import { Configuration } from "@hyperledger/cactus-core-api"; - -const testCase = "deploys contract from go source"; -const logLevel: LogLevelDesc = "TRACE"; - -test("BEFORE " + testCase, async (t: Test) => { - const pruning = pruneDockerAllIfGithubAction({ logLevel }); - await t.doesNotReject(pruning, "Pruning didn't throw OK"); - t.end(); -}); - -test.skip(testCase, async (t: Test) => { - test.onFailure(async () => { - await Containers.logDiagnostics({ logLevel }); - }); - const ledger = new FabricTestLedgerV1({ - emitContainerLogs: true, - logLevel, - publishAllPorts: true, - imageName: "ghcr.io/hyperledger/cactus-fabric-all-in-one", - }); - - const tearDown = async () => { - await ledger.stop(); - await ledger.destroy(); - await pruneDockerAllIfGithubAction({ logLevel }); - }; - - test.onFinish(tearDown); - - await ledger.start(); - t.doesNotThrow(() => ledger.getContainer(), "Container is set OK"); - const ledgerContainer = ledger.getContainer(); - t.ok(ledgerContainer, "ledgerContainer truthy OK"); - t.ok(ledgerContainer.id, "ledgerContainer.id truthy OK"); - - const connectionProfile = await ledger.getConnectionProfileOrg1(); - t.ok(connectionProfile, "getConnectionProfileOrg1() out truthy OK"); - - const enrollAdminOut = await ledger.enrollAdmin(); - const adminWallet = enrollAdminOut[1]; - const [userIdentity] = await ledger.enrollUser(adminWallet); - const sshConfig = await ledger.getSshConfig(); - - const keychainInstanceId = uuidv4(); - const keychainId = uuidv4(); - const keychainEntryKey = "user2"; - const keychainEntryValue = JSON.stringify(userIdentity); - - const keychainPlugin = new PluginKeychainMemory({ - instanceId: keychainInstanceId, - keychainId, - logLevel, - backend: new Map([ - [keychainEntryKey, keychainEntryValue], - ["some-other-entry-key", "some-other-entry-value"], - ]), - }); - - const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); - - const discoveryOptions: DiscoveryOptions = { - enabled: true, - asLocalhost: true, - }; - - // these below mirror how the fabric-samples sets up the configuration - const org1Env = { - CORE_PEER_LOCALMSPID: "Org1MSP", - CORE_PEER_ADDRESS: "peer0.org1.example.com:7051", - CORE_PEER_MSPCONFIGPATH: - "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp", - CORE_PEER_TLS_ROOTCERT_FILE: - "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt", - ORDERER_TLS_ROOTCERT_FILE: - "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem", - }; - - // these below mirror how the fabric-samples sets up the configuration - const org2Env = { - CORE_PEER_LOCALMSPID: "Org2MSP", - CORE_PEER_ADDRESS: "peer0.org2.example.com:9051", - CORE_PEER_MSPCONFIGPATH: - "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp", - CORE_PEER_TLS_ROOTCERT_FILE: - "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt", - ORDERER_TLS_ROOTCERT_FILE: - "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem", - }; - - const pluginOptions: IPluginLedgerConnectorFabricOptions = { - instanceId: uuidv4(), - dockerBinary: "/usr/local/bin/docker", - pluginRegistry, - peerBinary: "/fabric-samples/bin/peer", - cliContainerEnv: org1Env, - sshConfig, - logLevel, - connectionProfile, - discoveryOptions, - eventHandlerOptions: { - strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, - commitTimeout: 300, - }, - }; - const plugin = new PluginLedgerConnectorFabric(pluginOptions); - - const expressApp = express(); - expressApp.use(bodyParser.json({ limit: "250mb" })); - const server = http.createServer(expressApp); - const listenOptions: IListenOptions = { - hostname: "127.0.0.1", - port: 0, - server, - }; - const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; - const { port } = addressInfo; - test.onFinish(async () => await Servers.shutdown(server)); - - await plugin.getOrCreateWebServices(); - await plugin.registerWebServices(expressApp); - const apiUrl = `http://127.0.0.1:${port}`; - - const config = new Configuration({ basePath: apiUrl }); - const apiClient = new FabricApi(config); - const res = await apiClient.deployContractGoSourceV1({ - targetPeerAddresses: ["peer0.org1.example.com:7051"], - tlsRootCertFiles: - "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt", - policyDslSource: "AND('Org1MSP.member','Org2MSP.member')", - channelId: "mychannel", - chainCodeVersion: "1.0.0", - constructorArgs: { Args: ["john", "99"] }, - goSource: { - body: Buffer.from(HELLO_WORLD_CONTRACT_GO_SOURCE).toString("base64"), - filename: "hello-world.go", - }, - moduleName: "hello-world", - targetOrganizations: [org1Env, org2Env], - pinnedDeps: [ - "github.com/Knetic/govaluate@v3.0.0+incompatible", - "github.com/Shopify/sarama@v1.27.0", - "github.com/fsouza/go-dockerclient@v1.6.5", - "github.com/grpc-ecosystem/go-grpc-middleware@v1.2.1", - "github.com/hashicorp/go-version@v1.2.1", - "github.com/hyperledger/fabric@v1.4.8", - "github.com/hyperledger/fabric-amcl@v0.0.0-20200424173818-327c9e2cf77a", - "github.com/miekg/pkcs11@v1.0.3", - "github.com/mitchellh/mapstructure@v1.3.3", - "github.com/onsi/ginkgo@v1.14.1", - "github.com/onsi/gomega@v1.10.2", - "github.com/op/go-logging@v0.0.0-20160315200505-970db520ece7", - "github.com/pkg/errors@v0.9.1", - "github.com/spf13/viper@v1.7.1", - "github.com/stretchr/testify@v1.6.1", - "github.com/sykesm/zap-logfmt@v0.0.3", - "go.uber.org/zap@v1.16.0", - "golang.org/x/crypto@v0.0.0-20200820211705-5c72a883971a", - "golang.org/x/net@v0.0.0-20210503060351-7fd8e65b6420", - "google.golang.org/grpc@v1.31.1", - ], - }); - - const { - installationCommandResponses: installations, - instantiationCommandResponse: instantiation, - success, - } = res.data; - - installations.forEach((icr: SSHExecCommandResponse, idx: number) => { - t.comment(`CC installation ${idx} out: ${icr.stdout}`); - t.comment(`CC installation ${idx} err: ${icr.stderr}`); - }); - - t.comment(`CC instantiation out: ${instantiation.stdout}`); - t.comment(`CC instantiation err: ${instantiation.stderr}`); - - t.equal(res.status, 200, "deployContractGoSourceV1 res.status === 200 OK"); - t.true(success, "deployContractGoSourceV1 res.data.success === true"); - - // FIXME - without this wait it randomly fails with an error claiming that - // the endorsement was impossible to be obtained. The fabric-samples script - // does the same thing, it just waits 10 seconds for good measure so there - // might not be a way for us to avoid doing this, but if there is a way we - // absolutely should not have timeouts like this, anywhere... - await new Promise((resolve) => setTimeout(resolve, 20000)); - - const testKey = uuidv4(); - const testValue = uuidv4(); - const signingCredential: FabricSigningCredential = { - keychainId, - keychainRef: keychainEntryKey, - }; - - const setRes = await apiClient.runTransactionV1({ - contractName: "hello-world", - channelName: "mychannel", - params: [testKey, testValue], - methodName: "set", - invocationType: FabricContractInvocationType.Send, - signingCredential, - }); - t.ok(setRes, "setRes truthy OK"); - t.true(setRes.status > 199 && setRes.status < 300, "setRes status 2xx OK"); - t.comment(`HelloWorld.set() ResponseBody: ${JSON.stringify(setRes.data)}`); - - const getRes = await apiClient.runTransactionV1({ - contractName: "hello-world", - channelName: "mychannel", - params: [testKey], - methodName: "get", - invocationType: FabricContractInvocationType.Call, - signingCredential, - }); - t.ok(getRes, "getRes truthy OK"); - t.true(getRes.status > 199 && setRes.status < 300, "getRes status 2xx OK"); - t.comment(`HelloWorld.get() ResponseBody: ${JSON.stringify(getRes.data)}`); - t.equal(getRes.data.functionOutput, testValue, "get returns UUID OK"); - t.end(); -}); diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts deleted file mode 100644 index ae0764052a..0000000000 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts +++ /dev/null @@ -1,226 +0,0 @@ -import http from "http"; -import { AddressInfo } from "net"; - -import test, { Test } from "tape-promise/tape"; -import { v4 as uuidv4 } from "uuid"; - -import bodyParser from "body-parser"; -import express from "express"; - -import { - Containers, - FabricTestLedgerV1, - pruneDockerAllIfGithubAction, -} from "@hyperledger/cactus-test-tooling"; -import { PluginRegistry } from "@hyperledger/cactus-core"; - -import { - IListenOptions, - LogLevelDesc, - Servers, -} from "@hyperledger/cactus-common"; - -import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; - -import { - PluginLedgerConnectorFabric, - DefaultApi as FabricApi, - RunTransactionRequest, - FabricContractInvocationType, - DefaultEventHandlerStrategy, - FabricSigningCredential, -} from "../../../../main/typescript/public-api"; - -import { IPluginLedgerConnectorFabricOptions } from "../../../../main/typescript/plugin-ledger-connector-fabric"; -import { DiscoveryOptions } from "fabric-network"; -import { K_CACTUS_FABRIC_TOTAL_TX_COUNT } from "../../../../main/typescript/prometheus-exporter/metrics"; -import { Configuration } from "@hyperledger/cactus-core-api"; - -/** - * Use this to debug issues with the fabric node SDK - * ```sh - * export HFC_LOGGING='{"debug":"console","info":"console"}' - * ``` - */ - -const testCase = "runs tx on a Fabric v1.4.8 ledger"; -const logLevel: LogLevelDesc = "TRACE"; - -test.onFailure(async () => { - await Containers.logDiagnostics({ logLevel }); -}); - -test("BEFORE " + testCase, async (t: Test) => { - const pruning = pruneDockerAllIfGithubAction({ logLevel }); - await t.doesNotReject(pruning, "Pruning didn't throw OK"); - t.end(); -}); - -test.skip(testCase, async (t: Test) => { - const ledger = new FabricTestLedgerV1({ - publishAllPorts: true, - emitContainerLogs: true, - logLevel, - imageName: "ghcr.io/hyperledger/cactus-fabric-all-in-one", - envVars: new Map([ - ["FABRIC_VERSION", "1.4.8"], - ["CA_VERSION", "1.4.9"], - ]), - }); - - const tearDownLedger = async () => { - await ledger.stop(); - await ledger.destroy(); - await pruneDockerAllIfGithubAction({ logLevel }); - }; - test.onFinish(tearDownLedger); - - await ledger.start(); - - const enrollAdminOut = await ledger.enrollAdmin(); - const adminWallet = enrollAdminOut[1]; - const [userIdentity] = await ledger.enrollUser(adminWallet); - - const connectionProfile = await ledger.getConnectionProfileOrg1(); - - const sshConfig = await ledger.getSshConfig(); - - const keychainInstanceId = uuidv4(); - const keychainId = uuidv4(); - const keychainEntryKey = "user2"; - const keychainEntryValue = JSON.stringify(userIdentity); - - const keychainPlugin = new PluginKeychainMemory({ - instanceId: keychainInstanceId, - keychainId, - logLevel, - backend: new Map([ - [keychainEntryKey, keychainEntryValue], - ["some-other-entry-key", "some-other-entry-value"], - ]), - }); - - const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); - - const discoveryOptions: DiscoveryOptions = { - enabled: true, - asLocalhost: true, - }; - - const pluginOptions: IPluginLedgerConnectorFabricOptions = { - instanceId: uuidv4(), - pluginRegistry, - peerBinary: "/fabric-samples/bin/peer", - sshConfig, - cliContainerEnv: {}, - logLevel, - connectionProfile, - discoveryOptions, - eventHandlerOptions: { - strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, - commitTimeout: 300, - }, - }; - const plugin = new PluginLedgerConnectorFabric(pluginOptions); - - const expressApp = express(); - expressApp.use(bodyParser.json({ limit: "250mb" })); - const server = http.createServer(expressApp); - const listenOptions: IListenOptions = { - hostname: "127.0.0.1", - port: 0, - server, - }; - const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; - test.onFinish(async () => await Servers.shutdown(server)); - const { address, port } = addressInfo; - const apiHost = `http://${address}:${port}`; - t.comment( - `Metrics URL: ${apiHost}/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-prometheus-exporter-metrics`, - ); - - const apiConfig = new Configuration({ basePath: apiHost }); - const apiClient = new FabricApi(apiConfig); - - await plugin.getOrCreateWebServices(); - await plugin.registerWebServices(expressApp); - - const carId = "CAR277"; - const carOwner = uuidv4(); - const signingCredential: FabricSigningCredential = { - keychainId, - keychainRef: keychainEntryKey, - }; - - { - const res = await apiClient.runTransactionV1({ - signingCredential, - channelName: "mychannel", - contractName: "fabcar", - invocationType: FabricContractInvocationType.Call, - methodName: "queryAllCars", - params: [], - } as RunTransactionRequest); - t.ok(res); - t.ok(res.data); - t.equal(res.status, 200); - t.doesNotThrow(() => JSON.parse(res.data.functionOutput)); - } - - { - const req: RunTransactionRequest = { - signingCredential, - channelName: "mychannel", - invocationType: FabricContractInvocationType.Send, - contractName: "fabcar", - methodName: "createCar", - params: [carId, "Ford", "601", "Blue", carOwner], - }; - - const res = await apiClient.runTransactionV1(req); - t.ok(res); - t.ok(res.data); - t.equal(res.status, 200); - } - { - const res = await apiClient.runTransactionV1({ - signingCredential, - channelName: "mychannel", - contractName: "fabcar", - invocationType: FabricContractInvocationType.Call, - methodName: "queryAllCars", - params: [], - } as RunTransactionRequest); - t.ok(res); - t.ok(res.data); - t.equal(res.status, 200); - const cars = JSON.parse(res.data.functionOutput); - const car277 = cars.find((c: { Key: string }) => c.Key === carId); - t.ok(car277, "Located Car record by its ID OK"); - t.ok(car277.Record, `Car object has "Record" property OK`); - t.ok(car277.Record.owner, `Car object has "Record"."owner" property OK`); - t.equal(car277.Record.owner, carOwner, `Car has expected owner OK`); - } - { - const res = await apiClient.getPrometheusMetricsV1(); - const promMetricsOutput = - "# HELP " + - K_CACTUS_FABRIC_TOTAL_TX_COUNT + - " Total transactions executed\n" + - "# TYPE " + - K_CACTUS_FABRIC_TOTAL_TX_COUNT + - " gauge\n" + - K_CACTUS_FABRIC_TOTAL_TX_COUNT + - '{type="' + - K_CACTUS_FABRIC_TOTAL_TX_COUNT + - '"} 3'; - t.ok(res); - t.ok(res.data); - t.equal(res.status, 200); - t.true( - res.data.includes(promMetricsOutput), - "Total Transaction Count of 3 recorded as expected. RESULT OK", - ); - } - t.end(); -}); diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation-go.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation-go.test.ts index 365ae19f18..86cb932ed2 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation-go.test.ts +++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation-go.test.ts @@ -21,8 +21,6 @@ import { DeployContractGoSourceV1Request, } from "../../../../main/typescript/public-api"; -import { HELLO_WORLD_CONTRACT_GO_SOURCE } from "../../fixtures/go/hello-world-contract-fabric-v14/hello-world-contract-go-source"; - import { DefaultApi as FabricApi } from "../../../../main/typescript/public-api"; import { IPluginLedgerConnectorFabricOptions } from "../../../../main/typescript/plugin-ledger-connector-fabric"; @@ -127,67 +125,11 @@ test(testCase, async (t: Test) => { const apiClient = new FabricApi(config); const fDeployGo = "deployContractGoSourceV1"; - const cOk = "without bad request error"; const cWithoutParams = "not sending all required parameters"; const cInvalidParams = "sending invalid parameters"; - test.skip(`${testCase} - ${fDeployGo} - ${cOk}`, async (t2: Test) => { - const parameters = { - targetPeerAddresses: ["peer0.org1.example.com:7051"], - tlsRootCertFiles: - "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt", - policyDslSource: "AND('Org1MSP.member','Org2MSP.member')", - channelId: "mychannel", - chainCodeVersion: "1.0.0", - constructorArgs: { Args: ["john", "99"] }, - goSource: { - body: Buffer.from(HELLO_WORLD_CONTRACT_GO_SOURCE).toString("base64"), - filename: "hello-world.go", - }, - moduleName: "hello-world", - targetOrganizations: [org1Env, org2Env], - pinnedDeps: [ - "github.com/Knetic/govaluate@v3.0.0+incompatible", - "github.com/Shopify/sarama@v1.27.0", - "github.com/fsouza/go-dockerclient@v1.6.5", - "github.com/grpc-ecosystem/go-grpc-middleware@v1.2.1", - "github.com/hashicorp/go-version@v1.2.1", - "github.com/hyperledger/fabric@v1.4.8", - "github.com/hyperledger/fabric-amcl@v0.0.0-20200424173818-327c9e2cf77a", - "github.com/miekg/pkcs11@v1.0.3", - "github.com/mitchellh/mapstructure@v1.3.3", - "github.com/onsi/ginkgo@v1.14.1", - "github.com/onsi/gomega@v1.10.2", - "github.com/op/go-logging@v0.0.0-20160315200505-970db520ece7", - "github.com/pkg/errors@v0.9.1", - "github.com/spf13/viper@v1.7.1", - "github.com/stretchr/testify@v1.6.1", - "github.com/sykesm/zap-logfmt@v0.0.3", - "go.uber.org/zap@v1.16.0", - "golang.org/x/crypto@v0.0.0-20200820211705-5c72a883971a", - "golang.org/x/net@v0.0.0-20210503060351-7fd8e65b6420", - "google.golang.org/grpc@v1.31.1", - ], - }; - - const res = await apiClient.deployContractGoSourceV1(parameters); - - t2.equal( - res.status, - 200, - `Endpoint ${fDeployGo}: response.status === 200 OK`, - ); - t2.true( - res.data.success, - "deployContractGoSourceV1 res.data.success === true", - ); - - t2.end(); - }); - test(`${testCase} - ${fDeployGo} - ${cWithoutParams}`, async (t2: Test) => { const parameters = { - // targetPeerAddresses: ["peer0.org1.example.com:7051"], tlsRootCertFiles: "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt", policyDslSource: "AND('Org1MSP.member','Org2MSP.member')", @@ -195,7 +137,7 @@ test(testCase, async (t: Test) => { chainCodeVersion: "1.0.0", constructorArgs: { Args: ["john", "99"] }, goSource: { - body: Buffer.from(HELLO_WORLD_CONTRACT_GO_SOURCE).toString("base64"), + body: Buffer.from("some go source code").toString("base64"), filename: "hello-world.go", }, moduleName: "hello-world", @@ -256,7 +198,7 @@ test(testCase, async (t: Test) => { chainCodeVersion: "1.0.0", constructorArgs: { Args: ["john", "99"] }, goSource: { - body: Buffer.from(HELLO_WORLD_CONTRACT_GO_SOURCE).toString("base64"), + body: Buffer.from("some go source code").toString("base64"), filename: "hello-world.go", }, moduleName: "hello-world", diff --git a/packages/cactus-test-tooling/src/main/typescript/fabric/fabric-test-ledger-v1.ts b/packages/cactus-test-tooling/src/main/typescript/fabric/fabric-test-ledger-v1.ts index 8fba66f734..58033cec1a 100644 --- a/packages/cactus-test-tooling/src/main/typescript/fabric/fabric-test-ledger-v1.ts +++ b/packages/cactus-test-tooling/src/main/typescript/fabric/fabric-test-ledger-v1.ts @@ -375,17 +375,9 @@ export class FabricTestLedgerV1 implements ITestLedger { public async getConnectionProfileOrg1(): Promise { const cInfo = await this.getContainerInfo(); const container = this.getContainer(); - const CCP_JSON_PATH_FABRIC_V1 = - "/fabric-samples/first-network/connection-org1.json"; const CCP_JSON_PATH_FABRIC_V2 = "/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/connection-org1.json"; - const ccpJsonPath = compareVersions.compare( - this.getFabricVersion(), - "2.0", - "<", - ) - ? CCP_JSON_PATH_FABRIC_V1 - : CCP_JSON_PATH_FABRIC_V2; + const ccpJsonPath = CCP_JSON_PATH_FABRIC_V2; const ccpJson = await Containers.pullFile(container, ccpJsonPath); const ccp = JSON.parse(ccpJson); @@ -422,17 +414,11 @@ export class FabricTestLedgerV1 implements ITestLedger { const privatePort = 7050; const hostPort = await Containers.getPublicPort(privatePort, cInfo); const url = `grpcs://localhost:${hostPort}`; - const ORDERER_PEM_PATH_FABRIC_V1 = - "/fabric-samples/first-network/crypto-config/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem"; + const ORDERER_PEM_PATH_FABRIC_V2 = "/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"; - const ordererPemPath = compareVersions.compare( - this.getFabricVersion(), - "2.0", - "<", - ) - ? ORDERER_PEM_PATH_FABRIC_V1 - : ORDERER_PEM_PATH_FABRIC_V2; + + const ordererPemPath = ORDERER_PEM_PATH_FABRIC_V2; const pem = await Containers.pullFile(container, ordererPemPath); ccp.orderers = { @@ -498,16 +484,8 @@ export class FabricTestLedgerV1 implements ITestLedger { const peer1Name = `peer1.${orgName}.example.com`; const cInfo = await this.getContainerInfo(); const container = this.getContainer(); - const CCP_JSON_PATH_FABRIC_V1 = - "/fabric-samples/first-network/connection-" + orgName + ".json"; const CCP_JSON_PATH_FABRIC_V2 = connectionProfilePath; - const ccpJsonPath = compareVersions.compare( - this.getFabricVersion(), - "2.0", - "<", - ) - ? CCP_JSON_PATH_FABRIC_V1 - : CCP_JSON_PATH_FABRIC_V2; + const ccpJsonPath = CCP_JSON_PATH_FABRIC_V2; try { const cId = container.id; this.log.debug(`${fnTag} Pull Fabric CP %s :: %s`, cId, ccpJsonPath); @@ -557,17 +535,9 @@ export class FabricTestLedgerV1 implements ITestLedger { const privatePort = 7050; const hostPort = await Containers.getPublicPort(privatePort, cInfo); const url = `grpcs://localhost:${hostPort}`; - const ORDERER_PEM_PATH_FABRIC_V1 = - "/fabric-samples/first-network/crypto-config/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem"; const ORDERER_PEM_PATH_FABRIC_V2 = "/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"; - const ordererPemPath = compareVersions.compare( - this.getFabricVersion(), - "2.0", - "<", - ) - ? ORDERER_PEM_PATH_FABRIC_V1 - : ORDERER_PEM_PATH_FABRIC_V2; + const ordererPemPath = ORDERER_PEM_PATH_FABRIC_V2; const pem = await Containers.pullFile(container, ordererPemPath); ccp.orderers = { "orderer.example.com": { diff --git a/tools/docker/fabric-all-in-one/README.md b/tools/docker/fabric-all-in-one/README.md index fe3df03156..09e6ebaf9c 100644 --- a/tools/docker/fabric-all-in-one/README.md +++ b/tools/docker/fabric-all-in-one/README.md @@ -12,10 +12,6 @@ An all in one fabric docker image with the `fabric-samples` repo fully embedded. From the project root: ```sh -# Fabric 1.4.X -DOCKER_BUILDKIT=1 docker build ./tools/docker/fabric-all-in-one/ -f ./tools/docker/fabric-all-in-one/Dockerfile_v1.4.x -t faio14x -docker run --detach --privileged --publish-all --name faio14x-testnet faio14x - # Fabric 2.X DOCKER_BUILDKIT=1 docker build ./tools/docker/fabric-all-in-one/ -f ./tools/docker/fabric-all-in-one/Dockerfile_v2.x -t faio2x docker run --detach --privileged --publish-all --name faio2x-testnet faio2x @@ -37,11 +33,6 @@ Example `.vscode/tasks.json` file for building/running the image: { "version": "2.0.0", "tasks": [ - { - "label": "Docker - BUILD and TAG: 1.4.x", - "type": "shell", - "command": "docker build . -f Dockerfile_v1.4.x -t hyperledger/cactus-fabric-all-in-one:1.4.8" - }, { "label": "Docker - BUILD and TAG: 2.x", "type": "shell", @@ -78,28 +69,9 @@ docker cp db676059b79e:/etc/hyperledger/cactus/fabric-aio-image.key ./fabric-aio ssh root@localhost -p 32924 -i fabric-aio-image.key ``` -```sh -DOCKER_BUILDKIT=1 docker build ./tools/docker/fabric-all-in-one/ -f ./tools/docker/fabric-all-in-one/Dockerfile_v1.4.x -t faio14x -docker run --detach --privileged --publish-all --env FABRIC_VERSION=1.4.8 faio14x - -docker ps - -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -c09eb94d94d3 faio14x "/usr/bin/supervisor…" 5 seconds ago Up 4 seconds (health: starting) 0.0.0.0:32990->22/tcp, 0.0.0.0:32989->2375/tcp, 0.0.0.0:32988->2376/tcp, 0.0.0.0:32987->5984/tcp, 0.0.0.0:32986->6984/tcp, 0.0.0.0:32985->7050/tcp, 0.0.0.0:32984->7051/tcp, 0.0.0.0:32983->7054/tcp, 0.0.0.0:32982->7984/tcp, 0.0.0.0:32981->8051/tcp, 0.0.0.0:32980->8054/tcp, 0.0.0.0:32979->8984/tcp, 0.0.0.0:32978->9001/tcp, 0.0.0.0:32977->9051/tcp, 0.0.0.0:32976->10051/tcp funny_jepsen - - -docker cp c09eb94d94d3:/etc/hyperledger/cactus/fabric-aio-image.key ./fabric-aio-image.key -ssh root@localhost -p 32990 -i fabric-aio-image.key -``` ### Running Fabric CLI Container Commands -For Fabric 1.4.x - -```sh -$ docker exec -it --workdir /fabric-samples/fabcar/ dindy docker exec cli peer chaincode query --channelID mychannel --name fabcar --ctor '{"Args": [], "Function": "queryAllCars"}' -[{"Key":"CAR0", "Record":{"colour":"blue","make":"Toyota","model":"Prius","owner":"Tom"}},{"Key":"CAR1", "Record":{"colour":"red","make":"Ford","model":"Mustang","owner":"Brad"}},{"Key":"CAR2", "Record":{"colour":"green","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}},{"Key":"CAR3", "Record":{"colour":"yellow","make":"Volkswagen","model":"Passat","owner":"Max"}},{"Key":"CAR4", "Record":{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}},{"Key":"CAR5", "Record":{"colour":"purple","make":"Peugeot","model":"205","owner":"Michel"}},{"Key":"CAR6", "Record":{"colour":"white","make":"Chery","model":"S22L","owner":"Aarav"}},{"Key":"CAR7", "Record":{"colour":"violet","make":"Fiat","model":"Punto","owner":"Pari"}},{"Key":"CAR8", "Record":{"colour":"indigo","make":"Tata","model":"Nano","owner":"Valeria"}},{"Key":"CAR9", "Record":{"colour":"brown","make":"Holden","model":"Barina","owner":"Shotaro"}}] -``` For Fabric 2.x