Repository: hyperledger/firefly
Pull request #1154 (2023-01-19 17:49:14)

v1.2.0-alpha.1
This PR updates the `manifest.json` with the latest version of each dependency service, the latest CLI, the latest UI, and sets `evmconnect` to be the new default for E2E tests. Ethconnect is still tested, but it now takes a back seat compared to evmconnect.


Patch:
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 8c173fac6..a00dfc388 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -56,71 +56,69 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        blockchain-provider: [geth, fabric]
-        exclude: [ blockchain-provider: geth, blockchain-provider: fabric ]
+        stack-type: [ethereum, fabric]
+        exclude: [stack-type: ethereum, stack-type: fabric]
         include:
-            - blockchain-provider: geth
-              blockchain-connector: ethconnect
-              test-suite: TestEthereumMultipartyE2ESuite
-              database-type: sqlite3
-              token-provider: erc20_erc721
-              multiparty-enabled: true
-
-            - blockchain-provider: geth
-              blockchain-connector: ethconnect
-              test-suite: TestEthereumMultipartyE2ESuite
-              database-type: postgres
-              token-provider: erc20_erc721
-              multiparty-enabled: true
-            
-            - blockchain-provider: geth
-              blockchain-connector: ethconnect
-              test-suite: TestEthereumMultipartyE2ESuite
-              database-type: sqlite3
-              token-provider: erc1155
-              multiparty-enabled: true
-
-            - blockchain-provider: geth
-              blockchain-connector: ethconnect
-              test-suite: TestEthereumMultipartyTokensRemoteNameE2ESuite
-              database-type: postgres
-              token-provider: erc20_erc721
-              multiparty-enabled: true
-
-            - blockchain-provider: fabric
-              blockchain-connector: fabconnect
-              test-suite: TestFabricE2ESuite
-              database-type: sqlite3
-              token-provider: none
-              multiparty-enabled: true
-
-            - blockchain-provider: geth
-              blockchain-connector: ethconnect
-              test-suite: TestEthereumGatewayE2ESuite
-              database-type: sqlite3
-              token-provider: erc20_erc721
-              multiparty-enabled: false
-
-            - blockchain-provider: fabric
-              blockchain-connector: fabconnect
-              test-suite: TestFabricGatewayE2ESuite
-              database-type: sqlite3
-              token-provider: none
-              multiparty-enabled: false
-
-            - blockchain-provider: geth
-              blockchain-connector: evmconnect
-              test-suite: TestEthereumMultipartyE2ESuite
-              database-type: sqlite3
-              token-provider: erc20_erc721
-              multiparty-enabled: true
-
-            - blockchain-provider: geth
-              blockchain-connector: evmconnect
-              test-suite: TestEthereumGatewayE2ESuite
-              database-type: sqlite3
-              token-provider: erc1155
-              multiparty-enabled: false
+          - stack-type: ethereum
+            blockchain-connector: evmconnect
+            test-suite: TestEthereumMultipartyE2ESuite
+            database-type: sqlite3
+            token-provider: erc20_erc721
+            multiparty-enabled: true
+
+          - stack-type: ethereum
+            blockchain-connector: evmconnect
+            test-suite: TestEthereumMultipartyE2ESuite
+            database-type: postgres
+            token-provider: erc20_erc721
+            multiparty-enabled: true
+
+          - stack-type: ethereum
+            blockchain-connector: evmconnect
+            test-suite: TestEthereumMultipartyE2ESuite
+            database-type: sqlite3
+            token-provider: erc1155
+            multiparty-enabled: true
+
+          - stack-type: ethereum
+            blockchain-connector: evmconnect
+            test-suite: TestEthereumMultipartyTokensRemoteNameE2ESuite
+            database-type: postgres
+            token-provider: erc20_erc721
+            multiparty-enabled: true
+
+          - stack-type: fabric
+            test-suite: TestFabricE2ESuite
+            database-type: sqlite3
+            token-provider: none
+            multiparty-enabled: true
+
+          - stack-type: ethereum
+            blockchain-connector: evmconnect
+            test-suite: TestEthereumGatewayE2ESuite
+            database-type: sqlite3
+            token-provider: erc20_erc721
+            multiparty-enabled: false
+
+          - stack-type: fabric
+            test-suite: TestFabricGatewayE2ESuite
+            database-type: sqlite3
+            token-provider: none
+            multiparty-enabled: false
+
+          - stack-type: ethereum
+            blockchain-connector: ethconnect
+            test-suite: TestEthereumMultipartyE2ESuite
+            database-type: sqlite3
+            token-provider: erc20_erc721
+            multiparty-enabled: true
+
+          - stack-type: ethereum
+            blockchain-connector: ethconnect
+            test-suite: TestEthereumGatewayE2ESuite
+            database-type: sqlite3
+            token-provider: erc1155
+            multiparty-enabled: false
 
     steps:
       - uses: actions/checkout@v2
@@ -144,7 +142,7 @@ jobs:
         env:
           BUILD_FIREFLY: false
           TEST_SUITE: ${{ matrix.test-suite }}
-          BLOCKCHAIN_PROVIDER: ${{ matrix.blockchain-provider }}
+          STACK_TYPE: ${{ matrix.stack-type }}
           BLOCKCHAIN_CONNECTOR: ${{ matrix.blockchain-connector }}
           TOKENS_PROVIDER: ${{ matrix.token-provider }}
           DATABASE_TYPE: ${{ matrix.database-type }}
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 0433f262c..2a7003325 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -12,26 +12,33 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        test-suite: [TestEthereumMultipartyE2ESuite, TestEthereumGatewayE2ESuite, TestEthereumMultipartyTokensRemoteNameE2ESuite, TestFabricGatewayE2ESuite, TestFabricMultipartyE2ESuite]
-        blockchain-provider: [geth, besu, fabric]
+        test-suite:
+          [
+            TestEthereumMultipartyE2ESuite,
+            TestEthereumGatewayE2ESuite,
+            TestEthereumMultipartyTokensRemoteNameE2ESuite,
+            TestFabricGatewayE2ESuite,
+            TestFabricMultipartyE2ESuite,
+          ]
+        blockchain-node: [geth, besu, fabric]
         database-type: [sqlite3, postgres]
         exclude:
           - test-suite: TestEthereumGatewayE2ESuite
-            blockchain-provider: fabric
+            blockchain-node: fabric
           - test-suite: TestEthereumMultipartyE2ESuite
-            blockchain-provider: fabric
+            blockchain-node: fabric
           - test-suite: TestEthereumMultipartyTokensRemoteNameE2ESuite
-            blockchain-provider: fabric
+            blockchain-node: fabric
           - test-suite: TestEthereumMultipartyTokensRemoteNameE2ESuite
-            blockchain-provider: fabric
+            blockchain-node: fabric
           - test-suite: TestFabricGatewayE2ESuite
-            blockchain-provider: geth
+            blockchain-node: geth
           - test-suite: TestFabricGatewayE2ESuite
-            blockchain-provider: besu
+            blockchain-node: besu
           - test-suite: TestFabricMultipartyE2ESuite
-            blockchain-provider: geth
+            blockchain-node: geth
           - test-suite: TestFabricMultipartyE2ESuite
-            blockchain-provider: besu
+            blockchain-node: besu
       fail-fast: false
     steps:
       - uses: actions/checkout@v2
@@ -54,8 +61,9 @@ jobs:
       - name: Run E2E tests
         env:
           TEST_SUITE: ${{ matrix.test-suite }}
-          BLOCKCHAIN_PROVIDER: ${{ matrix.blockchain-provider }}
+          STACK_TYPE: ${{ matrix.stack-type }}
           DATABASE_TYPE: ${{ matrix.database-type }}
+          BLOCKCHAIN_NODE: ${{ matrix.blockchain-node }}
           BUILD_FIREFLY: false
           RESTART: true
         run: ./test/e2e/run.sh
@@ -90,7 +98,7 @@ jobs:
       - name: Run E2E tests
         env:
           TEST_SUITE: TestEthereumV1MigrationE2ESuite
-          BLOCKCHAIN_PROVIDER: geth
+          STACK_TYPE: ethereum
           DATABASE_TYPE: postgres
           BUILD_FIREFLY: false
           RESTART: false
diff --git a/internal/database/sqlcommon/pin_sql.go b/internal/database/sqlcommon/pin_sql.go
index e0815f8ba..794073b29 100644
--- a/internal/database/sqlcommon/pin_sql.go
+++ b/internal/database/sqlcommon/pin_sql.go
@@ -1,4 +1,4 @@
-// Copyright © 2022 Kaleido, Inc.
+// Copyright © 2023 Kaleido, Inc.
 //
 // SPDX-License-Identifier: Apache-2.0
 //
@@ -93,13 +93,13 @@ func (s *SQLCommon) UpsertPin(ctx context.Context, pin *core.Pin) (err error) {
 }
 
 func (s *SQLCommon) attemptPinInsert(ctx context.Context, tx *dbsql.TXWrapper, pin *core.Pin) (err error) {
-	pin.Sequence, err = s.InsertTx(ctx, pinsTable, tx,
+	requestConflictEmptyResult := true
+	pin.Sequence, err = s.InsertTxExt(ctx, pinsTable, tx,
 		s.setPinInsertValues(sq.Insert(pinsTable).Columns(pinColumns...), pin),
 		func() {
 			log.L(ctx).Debugf("Triggering creation event for pin %d", pin.Sequence)
 			s.callbacks.OrderedCollectionNSEvent(database.CollectionPins, core.ChangeEventTypeCreated, pin.Namespace, pin.Sequence)
-		},
-	)
+		}, requestConflictEmptyResult)
 	return err
 }
 
diff --git a/internal/orchestrator/data_query.go b/internal/orchestrator/data_query.go
index e97e1bee8..b860dd434 100644
--- a/internal/orchestrator/data_query.go
+++ b/internal/orchestrator/data_query.go
@@ -128,8 +128,8 @@ func (or *orchestrator) GetOperationByID(ctx context.Context, id string) (*core.
 	return or.operations.GetOperationByIDCached(ctx, u)
 }
 
-func (or *orchestrator) GetOperationByIDWithStatus(ctx context.Context, id string) (*core.OperationWithDetail, error) {
-	var enrichedOperation *core.OperationWithDetail
+func (or *orchestrator) GetOperationByIDWithStatus(ctx context.Context, id string) (*core.OperationWithDetailedStatus, error) {
+	var enrichedOperation *core.OperationWithDetailedStatus
 	u, err := fftypes.ParseUUID(ctx, id)
 	if err != nil {
 		return nil, err
@@ -143,7 +143,7 @@ func (or *orchestrator) GetOperationByIDWithStatus(ctx context.Context, id strin
 	if op.IsBlockchainOperation() || op.IsTokenOperation() {
 		status, err := or.blockchain().GetTransactionStatus(ctx, op)
 		if err != nil {
-			status = core.OperationDetailError{
+			status = core.OperationDetailedStatusError{
 				StatusError: err.Error(),
 			}
 		}
@@ -151,17 +151,17 @@ func (or *orchestrator) GetOperationByIDWithStatus(ctx context.Context, id strin
 		// Not all blockchain plugins will necessarily implement GetTransactionStatus()
 		// so check if we get any extra status back
 		if status != nil {
-			enrichedOperation = &core.OperationWithDetail{
-				Operation: *op,
-				Detail:    status,
+			enrichedOperation = &core.OperationWithDetailedStatus{
+				Operation:      *op,
+				DetailedStatus: status,
 			}
 		} else {
-			enrichedOperation = &core.OperationWithDetail{
+			enrichedOperation = &core.OperationWithDetailedStatus{
 				Operation: *op,
 			}
 		}
 	} else {
-		enrichedOperation = &core.OperationWithDetail{
+		enrichedOperation = &core.OperationWithDetailedStatus{
 			Operation: *op,
 		}
 	}
diff --git a/internal/orchestrator/orchestrator.go b/internal/orchestrator/orchestrator.go
index c744e5afc..1d716fd25 100644
--- a/internal/orchestrator/orchestrator.go
+++ b/internal/orchestrator/orchestrator.go
@@ -105,7 +105,7 @@ type Orchestrator interface {
 	GetDatatypeByName(ctx context.Context, name, version string) (*core.Datatype, error)
 	GetDatatypes(ctx context.Context, filter ffapi.AndFilter) ([]*core.Datatype, *ffapi.FilterResult, error)
 	GetOperationByID(ctx context.Context, id string) (*core.Operation, error)
-	GetOperationByIDWithStatus(ctx context.Context, id string) (*core.OperationWithDetail, error)
+	GetOperationByIDWithStatus(ctx context.Context, id string) (*core.OperationWithDetailedStatus, error)
 	GetOperations(ctx context.Context, filter ffapi.AndFilter) ([]*core.Operation, *ffapi.FilterResult, error)
 	GetEventByID(ctx context.Context, id string) (*core.Event, error)
 	GetEventByIDWithReference(ctx context.Context, id string) (*core.EnrichedEvent, error)
diff --git a/manifest.json b/manifest.json
index db31d6ae3..e971d1c31 100644
--- a/manifest.json
+++ b/manifest.json
@@ -6,33 +6,33 @@
   },
   "evmconnect": {
     "image": "ghcr.io/hyperledger/firefly-evmconnect",
-    "tag": "v1.1.11",
-    "sha": "a6fa5e764da7103e628fab1ca6cbc7fbcf9b9f47f5ea016981b7947e77d3e74e"
+    "tag": "v1.1.10-20221220-30",
+    "sha": "3366c4061573145b3e941768b11c3a27f18c7aa0e8540a13ffa56526193a4248"
   },
   "fabconnect": {
     "image": "ghcr.io/hyperledger/firefly-fabconnect",
-    "tag": "v.0.9.16",
-    "sha": "4f4798ee34eee0b67886f1baa37f4d50a33e2932c94312f189fe5f015f6564a4"
+    "tag": "null-20230119-30",
+    "sha": "d46b3408ff1a1c4730633c217fa41f78097f76caf5ca884ede8932cbafa83476"
   },
   "dataexchange-https": {
     "image": "ghcr.io/hyperledger/firefly-dataexchange-https",
-    "tag": "v1.1.0",
-    "sha": "9b191cf693a5b4a3b0bff48aac36fa76cf040d94033607a240cbd83e4fd2942c"
+    "tag": "v1.2.0",
+    "sha": "4ac765f7a07b9d17ab5648b3c789875791db364659c975a23626ec5921f11ce4"
   },
   "tokens-erc1155": {
     "image": "ghcr.io/hyperledger/firefly-tokens-erc1155",
-    "tag": "v1.2.0",
-    "sha": "9a7135b4d3352992832629ff644cf1a6526fef9de716711dbf00a7bf842184a6"
+    "tag": "v1.2.0-20230119-56",
+    "sha": "e025a9e07e0066a8b9dd568a28ae629c6fee3e498337a823699c4d459442d4ad"
   },
   "tokens-erc20-erc721": {
     "image": "ghcr.io/hyperledger/firefly-tokens-erc20-erc721",
-    "tag": "v1.2.0",
-    "sha": "88fbaee7d7b24682bea8fe0c00d9baa50c9a3bcc86aaed828a1f5e8ac205985a"
+    "tag": "v1.2.0-20230119-76",
+    "sha": "f65438c9da16f39389dbf0c36eda103670cc8559a58d72fd6b0fe6299623628e"
   },
   "signer": {
     "image": "ghcr.io/hyperledger/firefly-signer",
-    "tag": "v1.1.5",
-    "sha": "4ee8549d12339f6d4224a277faf143da1749a51a5994e074224c95e3cce64670"
+    "tag": "v1.1.4-20230105-28",
+    "sha": "a4a26b9ce921e908e827d63219fca02e1d56da3a64e14dc396279a4818ae1083"
   },
   "build": {
     "firefly-builder": {
@@ -50,10 +50,10 @@
     }
   },
   "ui": {
-    "tag": "v1.1.5",
-    "release": "v1.1.5"
+    "tag": "v1.2.0-alpha.1",
+    "release": "v1.2.0-alpha.1"
   },
   "cli": {
-    "tag": "v1.1.2"
+    "tag": "v1.2.0-alpha.1"
   }
-}
\ No newline at end of file
+}
diff --git a/mocks/orchestratormocks/orchestrator.go b/mocks/orchestratormocks/orchestrator.go
index 9991e7670..8b265666d 100644
--- a/mocks/orchestratormocks/orchestrator.go
+++ b/mocks/orchestratormocks/orchestrator.go
@@ -866,15 +866,15 @@ func (_m *Orchestrator) GetOperationByID(ctx context.Context, id string) (*core.
 }
 
 // GetOperationByIDWithStatus provides a mock function with given fields: ctx, id
-func (_m *Orchestrator) GetOperationByIDWithStatus(ctx context.Context, id string) (*core.OperationWithDetail, error) {
+func (_m *Orchestrator) GetOperationByIDWithStatus(ctx context.Context, id string) (*core.OperationWithDetailedStatus, error) {
 	ret := _m.Called(ctx, id)
 
-	var r0 *core.OperationWithDetail
-	if rf, ok := ret.Get(0).(func(context.Context, string) *core.OperationWithDetail); ok {
+	var r0 *core.OperationWithDetailedStatus
+	if rf, ok := ret.Get(0).(func(context.Context, string) *core.OperationWithDetailedStatus); ok {
 		r0 = rf(ctx, id)
 	} else {
 		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*core.OperationWithDetail)
+			r0 = ret.Get(0).(*core.OperationWithDetailedStatus)
 		}
 	}
 
diff --git a/pkg/core/operation.go b/pkg/core/operation.go
index 91b8f0fc7..1a8a49cdd 100644
--- a/pkg/core/operation.go
+++ b/pkg/core/operation.go
@@ -1,4 +1,4 @@
-// Copyright © 2023 Kaleido, Inc.
+// Copyright © 2022 Kaleido, Inc.
 //
 // SPDX-License-Identifier: Apache-2.0
 //
@@ -180,11 +180,11 @@ type OperationUpdate struct {
 	OnComplete     func()
 }
 
-type OperationDetailError struct {
-	StatusError string `ffstruct:"OperationDetail" json:"error,omitempty"`
+type OperationDetailedStatusError struct {
+	StatusError string `ffstruct:"OperationDetailedStatusError" json:"error,omitempty"`
 }
 
-type OperationWithDetail struct {
+type OperationWithDetailedStatus struct {
 	Operation
-	Detail interface{} `ffstruct:"OperationWithDetail" json:"detail,omitempty" ffexcludeinput:"true"`
+	DetailedStatus interface{} `ffstruct:"OperationWithDetailedStatus" json:"detailedStatus,omitempty" ffexcludeinput:"true"`
 }


Test patch:
diff --git a/internal/apiserver/route_get_op_by_id_test.go b/internal/apiserver/route_get_op_by_id_test.go
index a92d6adc3..aa23b20aa 100644
--- a/internal/apiserver/route_get_op_by_id_test.go
+++ b/internal/apiserver/route_get_op_by_id_test.go
@@ -47,7 +47,7 @@ func TestGetOperationByIDFetchStatus(t *testing.T) {
 	res := httptest.NewRecorder()
 
 	o.On("GetOperationByIDWithStatus", mock.Anything, "abcd12345").
-		Return(&core.OperationWithDetail{}, nil)
+		Return(&core.OperationWithDetailedStatus{}, nil)
 	r.ServeHTTP(res, req)
 
 	assert.Equal(t, 200, res.Result().StatusCode)
diff --git a/internal/orchestrator/data_query_test.go b/internal/orchestrator/data_query_test.go
index b748fb3be..3c8a653e0 100644
--- a/internal/orchestrator/data_query_test.go
+++ b/internal/orchestrator/data_query_test.go
@@ -568,7 +568,7 @@ func TestGetOperationByIDWithStatus(t *testing.T) {
 	assert.Nil(t, err)
 	assert.NotNil(t, opStatus)
 	var expectedTxnStatus = &txnStatus{TxnId: "abc123"}
-	assert.Equal(t, expectedTxnStatus, opStatus.Detail)
+	assert.Equal(t, expectedTxnStatus, opStatus.DetailedStatus)
 }
 
 func TestGetOperationByIDWithGoodEmptyStatus(t *testing.T) {
@@ -585,7 +585,7 @@ func TestGetOperationByIDWithGoodEmptyStatus(t *testing.T) {
 	opStatus, err := or.GetOperationByIDWithStatus(context.Background(), u.String())
 	assert.Nil(t, err)
 	assert.NotNil(t, opStatus)
-	assert.Equal(t, nil, opStatus.Detail)
+	assert.Equal(t, nil, opStatus.DetailedStatus)
 }
 
 func TestGetOperationByIDWithStatusWrongOpType(t *testing.T) {
@@ -601,7 +601,7 @@ func TestGetOperationByIDWithStatusWrongOpType(t *testing.T) {
 	opStatus, err := or.GetOperationByIDWithStatus(context.Background(), u.String())
 	assert.Nil(t, err)
 	assert.NotNil(t, opStatus)
-	assert.Equal(t, nil, opStatus.Detail)
+	assert.Equal(t, nil, opStatus.DetailedStatus)
 }
 
 func TestGetOperationIDWithStatusBadID(t *testing.T) {
@@ -635,7 +635,7 @@ func TestGetOperationByIDWithStatusError(t *testing.T) {
 	opStatus, err := or.GetOperationByIDWithStatus(context.Background(), u.String())
 	assert.Nil(t, err)
 	assert.NotNil(t, opStatus)
-	assert.Regexp(t, "pop", opStatus.Detail)
+	assert.Regexp(t, "pop", opStatus.DetailedStatus)
 }
 
 func TestGetEventByID(t *testing.T) {
diff --git a/test/e2e/run.sh b/test/e2e/run.sh
index 5a2fb8e10..89895fe46 100755
--- a/test/e2e/run.sh
+++ b/test/e2e/run.sh
@@ -48,7 +48,7 @@ BUILD_FIREFLY=${BUILD_FIREFLY:-true}
 MULTIPARTY_ENABLED=${MULTIPARTY_ENABLED:-true}
 
 DATABASE_TYPE=${DATABASE_TYPE:-sqlite3}
-BLOCKCHAIN_PROVIDER=${BLOCKCHAIN_PROVIDER:-geth}
+STACK_TYPE=${STACK_TYPE:-ethereum}
 TOKENS_PROVIDER=${TOKENS_PROVIDER:-erc20_erc721}
 
 BLOCKCHAIN_CONNECTOR_FLAG=""
@@ -56,8 +56,13 @@ if [ -n "${BLOCKCHAIN_CONNECTOR}" ]; then
   BLOCKCHAIN_CONNECTOR_FLAG="--blockchain-connector ${BLOCKCHAIN_CONNECTOR}"
 fi
 
+BLOCKCHAIN_NODE_FLAG=""
+if [ -n "${BLOCKCHAIN_NODE}" ]; then
+  BLOCKCHAIN_CONNECTOR_FLAG="--blockchain-node ${BLOCKCHAIN_NODE}"
+fi
+
 if [ -z "${TEST_SUITE}" ]; then
-  if [ "${BLOCKCHAIN_PROVIDER}" == "fabric" ]; then
+  if [ "${STACK_TYPE}" == "fabric" ]; then
     if [ "${MULTIPARTY_ENABLED}" == "true" ]; then
       TEST_SUITE=TestFabricMultipartyE2ESuite
     else
@@ -86,7 +91,7 @@ fi
 
 if [ "$CREATE_STACK" == "true" ]; then
   $CLI remove -f $STACK_NAME
-  $CLI init --prometheus-enabled --database $DATABASE_TYPE $STACK_NAME 2 --blockchain-provider $BLOCKCHAIN_PROVIDER $BLOCKCHAIN_CONNECTOR_FLAG --token-providers $TOKENS_PROVIDER --manifest ../../manifest.json $EXTRA_INIT_ARGS --sandbox-enabled=false --multiparty=$MULTIPARTY_ENABLED
+  $CLI init $STACK_TYPE --prometheus-enabled --database $DATABASE_TYPE $STACK_NAME 2 $BLOCKCHAIN_CONNECTOR_FLAG $BLOCKCHAIN_NODE_FLAG --token-providers $TOKENS_PROVIDER --manifest ../../manifest.json $EXTRA_INIT_ARGS --sandbox-enabled=false --multiparty=$MULTIPARTY_ENABLED
   checkOk $?
 
   $CLI pull $STACK_NAME -r 3