Repository: hyperledger/firefly
Pull request #938 (2022-08-08 14:09:23)

update integration test to use new e2e suites


Patch:
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 692574034..d039430cf 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -12,16 +12,16 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        test-suite: [TestEthereumE2ESuite, TestFabricE2ESuite]
+        test-suite: [TestEthereumMultipartyE2ESuite, TestEthereumGatewayE2ESuite, TestEthereumMultipartyTokensRemoteNameE2ESuite, TestFabricGatewayE2ESuite, TestFabricMultipartyE2ESuite]
         blockchain-provider: [geth, besu, fabric]
         database-type: [sqlite3, postgres]
         exclude:
           - blockchain-provider: geth
-            test-suite: TestFabricE2ESuite
+            test-suite: [TestFabricGatewayE2ESuite, TestFabricMultipartyE2ESuite]
           - blockchain-provider: besu
-            test-suite: TestFabricE2ESuite
+            test-suite: [TestFabricGatewayE2ESuite, TestFabricMultipartyE2ESuite]
           - blockchain-provider: fabric
-            test-suite: TestEthereumE2ESuite
+            test-suite: [TestEthereumMultipartyE2ESuite, TestEthereumGatewayE2ESuite, TestEthereumMultipartyTokensRemoteNameE2ESuite]
       fail-fast: false
     steps:
       - uses: actions/checkout@v2
diff --git a/.gitignore b/.gitignore
index 7ffcc3678..b275434dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,4 +16,3 @@ __debug*
 !deploy/charts/firefly
 containerlogs
 .vscode/*.log
-.idea
\ No newline at end of file
diff --git a/docs/tutorials/fabric_remote.md b/docs/tutorials/fabric_remote.md
index 5cc89b9c0..53126ca66 100644
--- a/docs/tutorials/fabric_remote.md
+++ b/docs/tutorials/fabric_remote.md
@@ -34,7 +34,7 @@ Choose a stack name. For this guide, I will choose the name `my-remote-fabric`,
 stack name: my-remote-fabric
 ```
 
-For this guide, we will be creating only one supernode for one of the organizations in our fabric network and using that organizational identity to interact with the chaincode. You can create multiple supernodes for different organizations in your fabric network by passing here the number of members in your stack.
+For this guide, we will be creating only one supernode for one of the organizations in our fabric netwok and using that organizational identity to interact with the chaincode. You can create multiple supernodes for different organizations in your fabric network by passing here the number of members in your stack.
 
 ```
 number of members: 1
@@ -64,11 +64,11 @@ Now that you have created a stack, let's open it up in your favourite code edito
 
 ### Add msp folder representing your fabric identity
 
-In `$HOME/.firefly/stacks/my-remote-fabric`, you need to add a msp folder. This msp folder essentially describes the fabric organizational identity which will be interacting with your chaincode. Inside the msp folder, you must have all the certificates and the private key to be used by firefly to query/invoke your chaincode.
+In `$HOME/.firefly/stacks/my-remote-fabric`, you need to add an msp folder. This msp folder essentially describes the fabric organizational identiy which will be interacting with your chaincode. Inside the msp folder, you must have all the certifactes and the private key to be used by firefly to query/invoke your chaincode.
 
 You should be having this msp folder for an organizational identity from when you would have set up your fabric network. For more details, please refer to [Hyperledger Fabric Documentation for MSP](https://hyperledger-fabric.readthedocs.io/en/latest/msp.html).
 
-Now, you need to mount this msp directory as a docker volume in your fabconnect service.
+Now, you need to mount this msp directory as a docker volume in your fabconnect serivce.
 
 > **NOTE:** All docker-compose.yml related changes should be done in docker-compose.override.yml.
 
@@ -228,7 +228,7 @@ ff start my-remote-fabric
 
 This may take a minute or two and in the background the FireFly CLI will do the following for you:
 
-- Download Docker images for all the components of the Supernode
+- Download Docker images for all of the components of the Supernode
 - Set up configuration between all the components
 - Deploy FireFly's `BatchPin` smart contract to our remote fabric network
 - Register an identity for each member and node in our remote fabric network
diff --git a/go.mod b/go.mod
index 74d25addb..7388d6d74 100644
--- a/go.mod
+++ b/go.mod
@@ -13,7 +13,7 @@ require (
 	github.com/golang-migrate/migrate/v4 v4.15.2
 	github.com/gorilla/mux v1.8.0
 	github.com/gorilla/websocket v1.5.0
-	github.com/hyperledger/firefly-common v0.1.16
+	github.com/hyperledger/firefly-common v0.1.15
 	github.com/hyperledger/firefly-signer v0.9.12
 	github.com/jarcoal/httpmock v1.1.0
 	github.com/karlseguin/ccache v2.0.3+incompatible
@@ -24,8 +24,8 @@ require (
 	github.com/santhosh-tekuri/jsonschema/v5 v5.0.0
 	github.com/sirupsen/logrus v1.8.1
 	github.com/spf13/cobra v1.4.0
-	github.com/spf13/viper v1.12.1-0.20220712161005-5247643f0235
-	github.com/stretchr/testify v1.8.0
+	github.com/spf13/viper v1.12.0
+	github.com/stretchr/testify v1.7.1
 	gitlab.com/hfuss/mux-prometheus v0.0.4
 	golang.org/x/net v0.0.0-20220531201128-c960675eff93
 	golang.org/x/text v0.3.7
@@ -59,7 +59,7 @@ require (
 	github.com/mitchellh/mapstructure v1.5.0 // indirect
 	github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
 	github.com/pelletier/go-toml v1.9.5 // indirect
-	github.com/pelletier/go-toml/v2 v2.0.2 // indirect
+	github.com/pelletier/go-toml/v2 v2.0.1 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/prometheus/client_model v0.2.0 // indirect
@@ -70,7 +70,7 @@ require (
 	github.com/spf13/cast v1.5.0 // indirect
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
-	github.com/stretchr/objx v0.4.0 // indirect
+	github.com/stretchr/objx v0.2.0 // indirect
 	github.com/subosito/gotenv v1.4.0 // indirect
 	github.com/wayneashleyberry/terminal-dimensions v1.0.0 // indirect
 	github.com/wsxiaoys/terminal v0.0.0-20160513160801-0940f3fc43a0 // indirect
diff --git a/go.sum b/go.sum
index 45a2ab97d..1cacd7213 100644
--- a/go.sum
+++ b/go.sum
@@ -727,8 +727,8 @@ github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpT
 github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/hyperledger/firefly-common v0.1.13/go.mod h1:2NqPi5Ud9H6rSlZXkLbotxW7z4EAD89p3/8oNOpm9Gs=
-github.com/hyperledger/firefly-common v0.1.16 h1:21xidDEKrJhtGdBSRqHN4PfDi7aYxF0HOFuAa04V1AE=
-github.com/hyperledger/firefly-common v0.1.16/go.mod h1:MNbaI2spBsdZYOub6Duj9xueE7Qyu9itOmJ4vE8tjYw=
+github.com/hyperledger/firefly-common v0.1.15 h1:hOAMSz+YuGP1ulLstVFoWxrCAB+0OrbnfUO3v4etvEw=
+github.com/hyperledger/firefly-common v0.1.15/go.mod h1:MNbaI2spBsdZYOub6Duj9xueE7Qyu9itOmJ4vE8tjYw=
 github.com/hyperledger/firefly-signer v0.9.12 h1:pCPiGHx1+MbTsIQuRkoQmfWxvpcvtGHVavls0NnH0po=
 github.com/hyperledger/firefly-signer v0.9.12/go.mod h1:GPQRUZOFOAjkLmg8GDjZUjEdUD0gcar+CSVhwltIwyw=
 github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
@@ -1050,9 +1050,8 @@ github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrap
 github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
 github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
 github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
+github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU=
 github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
-github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw=
-github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI=
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
 github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
@@ -1194,17 +1193,15 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
 github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
+github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ=
 github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI=
-github.com/spf13/viper v1.12.1-0.20220712161005-5247643f0235 h1:azjn5/lAGpcMny6s1fW/y6rXTu2YUOA+a2C6wKpgpkw=
-github.com/spf13/viper v1.12.1-0.20220712161005-5247643f0235/go.mod h1:f40df4ovE8V1ot0NXmYP1zUDS+X1D5AXGviq9fCJqZU=
 github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
 github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
 github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
 github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
-github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -1212,10 +1209,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
-github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs=
 github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs=
diff --git a/internal/assets/token_pool.go b/internal/assets/token_pool.go
index d0d532390..8dd4ba65b 100644
--- a/internal/assets/token_pool.go
+++ b/internal/assets/token_pool.go
@@ -81,7 +81,7 @@ func (am *assetManager) createTokenPoolInternal(ctx context.Context, pool *core.
 
 		op = core.NewOperation(
 			plugin,
-			am.namespace,
+			pool.Namespace,
 			txid,
 			core.OpTypeTokenCreatePool)
 		if err = txcommon.AddTokenPoolCreateInputs(op, pool); err == nil {
@@ -119,7 +119,7 @@ func (am *assetManager) ActivateTokenPool(ctx context.Context, pool *core.TokenP
 
 		op = core.NewOperation(
 			plugin,
-			am.namespace,
+			pool.Namespace,
 			pool.TX.ID,
 			core.OpTypeTokenActivatePool)
 		txcommon.AddTokenPoolActivateInputs(op, pool.ID)
diff --git a/internal/blockchain/ethereum/config.go b/internal/blockchain/ethereum/config.go
index 7e6289ca5..edb11479d 100644
--- a/internal/blockchain/ethereum/config.go
+++ b/internal/blockchain/ethereum/config.go
@@ -54,6 +54,13 @@ const (
 	// EthconnectConfigFromBlockDeprecated is the configuration of the first block to listen to when creating the listener for the FireFly contract
 	EthconnectConfigFromBlockDeprecated = "fromBlock"
 
+	// FireFlyContractConfigKey is a sub-key in the config to contain the info on the deployed FireFly contract
+	FireFlyContractConfigKey = "fireflyContract"
+	// FireFlyContractAddress is the ethereum address of the FireFly contract
+	FireFlyContractAddress = "address"
+	// FireFlyContractFromBlock is the configuration of the first block to listen to when creating the listener
+	FireFlyContractFromBlock = "fromBlock"
+
 	// AddressResolverConfigKey is a sub-key in the config to contain an address resolver config.
 	AddressResolverConfigKey = "addressResolver"
 	// AddressResolverRetainOriginal when true the original pre-resolved string is retained after the lookup, and passed down to Ethconnect as the from address
diff --git a/internal/blockchain/ethereum/ethereum.go b/internal/blockchain/ethereum/ethereum.go
index 86c2d1210..c7033c1f8 100644
--- a/internal/blockchain/ethereum/ethereum.go
+++ b/internal/blockchain/ethereum/ethereum.go
@@ -341,13 +341,8 @@ func (e *Ethereum) handleReceipt(ctx context.Context, reply fftypes.JSONObject)
 		l.Errorf("Reply cannot be processed - missing fields: %+v", reply)
 		return
 	}
-	var updateType core.OpStatus
-	switch replyType {
-	case "TransactionSuccess":
-		updateType = core.OpStatusSucceeded
-	case "TransactionUpdate":
-		updateType = core.OpStatusPending
-	default:
+	updateType := core.OpStatusSucceeded
+	if replyType != "TransactionSuccess" {
 		updateType = core.OpStatusFailed
 	}
 	l.Infof("Received operation update: status=%s request=%s tx=%s message=%s", updateType, requestID, txHash, message)
@@ -385,10 +380,6 @@ func (e *Ethereum) handleMessageBatch(ctx context.Context, messages []interface{
 				return err
 			}
 
-			firstColon := strings.Index(signature, ":")
-			if firstColon >= 0 {
-				signature = signature[firstColon+1:]
-			}
 			switch signature {
 			case broadcastBatchEventSignature:
 				if err := e.handleBatchPinEvent(eventCtx, location, subInfo, msgJSON); err != nil {
diff --git a/internal/blockchain/fabric/config.go b/internal/blockchain/fabric/config.go
index cf1d4588d..9cb24a47d 100644
--- a/internal/blockchain/fabric/config.go
+++ b/internal/blockchain/fabric/config.go
@@ -49,6 +49,13 @@ const (
 	FabconnectPrefixLong = "prefixLong"
 	// FabconnectConfigChaincodeDeprecated is the Fabric Firefly chaincode deployed to the Firefly channels
 	FabconnectConfigChaincodeDeprecated = "chaincode"
+
+	// FireFlyContractConfigKey is a sub-key in the config to contain the info on the deployed FireFly contract
+	FireFlyContractConfigKey = "fireflyContract"
+	// FireFlyContractChaincode is the Fabric Firefly chaincode deployed to the Firefly channels
+	FireFlyContractChaincode = "chaincode"
+	// FireFlyContractFromBlock is the configuration of the first block to listen to when creating the listener
+	FireFlyContractFromBlock = "fromBlock"
 )
 
 func (f *Fabric) InitConfig(config config.Section) {
diff --git a/internal/broadcast/manager.go b/internal/broadcast/manager.go
index cb248d19e..46be34e9e 100644
--- a/internal/broadcast/manager.go
+++ b/internal/broadcast/manager.go
@@ -129,7 +129,7 @@ func (bm *broadcastManager) dispatchBatch(ctx context.Context, state *batch.Disp
 	// Upload the batch itself
 	op := core.NewOperation(
 		bm.sharedstorage,
-		bm.namespace.LocalName,
+		state.Persisted.Namespace,
 		state.Persisted.TX.ID,
 		core.OpTypeSharedStorageUploadBatch)
 	addUploadBatchInputs(op, state.Persisted.ID)
@@ -157,13 +157,10 @@ func (bm *broadcastManager) uploadBlobs(ctx context.Context, tx *fftypes.UUID, d
 
 			op := core.NewOperation(
 				bm.sharedstorage,
-				bm.namespace.LocalName,
+				d.Namespace,
 				tx,
 				core.OpTypeSharedStorageUploadBlob)
 			addUploadBlobInputs(op, d.ID)
-			if err := bm.operations.AddOrReuseOperation(ctx, op); err != nil {
-				return err
-			}
 
 			blob, err := bm.database.GetBlobMatchingHash(ctx, d.Blob.Hash)
 			if err != nil {
diff --git a/internal/coremsgs/en_config_descriptions.go b/internal/coremsgs/en_config_descriptions.go
index 4c8ec45d2..c9c062fbd 100644
--- a/internal/coremsgs/en_config_descriptions.go
+++ b/internal/coremsgs/en_config_descriptions.go
@@ -329,4 +329,6 @@ var (
 	ConfigPluginsAuth     = ffc("config.plugins.auth", "Authorization plugin configuration", i18n.MapStringStringType)
 	ConfigPluginsAuthName = ffc("config.plugins.auth[].name", "The name of the auth plugin to use", i18n.StringType)
 	ConfigPluginsAuthType = ffc("config.plugins.auth[].type", "The type of the auth plugin to use", i18n.StringType)
+
+	ConfigGlobalAuthBasicPasswordFile = ffc("config.global.basic.passwordfile", "The path to a .htpasswd file to use for authenticating requests. Passwords should be hashed with bcrypt.", i18n.StringType)
 )
diff --git a/internal/database/sqlite3/sqlite3.go b/internal/database/sqlite3/sqlite3.go
index b8624b593..ecbbaa46a 100644
--- a/internal/database/sqlite3/sqlite3.go
+++ b/internal/database/sqlite3/sqlite3.go
@@ -42,10 +42,7 @@ type SQLite3 struct {
 }
 
 func connHook(conn *sqlite3.SQLiteConn) error {
-	_, err := conn.Exec(`
-		PRAGMA case_sensitive_like=ON;
-		PRAGMA busy_timeout=1000;
-	`, nil)
+	_, err := conn.Exec("PRAGMA case_sensitive_like=ON;", nil)
 	return err
 }
 
diff --git a/internal/multiparty/manager.go b/internal/multiparty/manager.go
index 7d5c860f6..7a03e677b 100644
--- a/internal/multiparty/manager.go
+++ b/internal/multiparty/manager.go
@@ -230,7 +230,7 @@ func (mm *multipartyManager) SubmitNetworkAction(ctx context.Context, signingKey
 func (mm *multipartyManager) SubmitBatchPin(ctx context.Context, batch *core.BatchPersisted, contexts []*fftypes.Bytes32, payloadRef string) error {
 	op := core.NewOperation(
 		mm.blockchain,
-		mm.namespace.LocalName,
+		batch.Namespace,
 		batch.TX.ID,
 		core.OpTypeBlockchainPinBatch)
 	addBatchPinInputs(op, batch.ID, contexts, payloadRef)
diff --git a/internal/privatemessaging/privatemessaging.go b/internal/privatemessaging/privatemessaging.go
index b4b57ddbe..3e3cff64e 100644
--- a/internal/privatemessaging/privatemessaging.go
+++ b/internal/privatemessaging/privatemessaging.go
@@ -215,7 +215,7 @@ func (pm *privateMessaging) prepareBlobTransfers(ctx context.Context, data core.
 
 				op := core.NewOperation(
 					pm.exchange,
-					pm.namespace.LocalName,
+					d.Namespace,
 					txid,
 					core.OpTypeDataExchangeSendBlob)
 				addTransferBlobInputs(op, node.ID, blob.Hash)
@@ -291,7 +291,7 @@ func (pm *privateMessaging) sendData(ctx context.Context, tw *core.TransportWrap
 
 			op := core.NewOperation(
 				pm.exchange,
-				pm.namespace.LocalName,
+				batch.Namespace,
 				batch.Payload.TX.ID,
 				core.OpTypeDataExchangeSendBatch)
 			addBatchSendInputs(op, node.ID, batch.Group, batch.ID)


Test patch:
diff --git a/internal/blockchain/ethereum/ethereum_test.go b/internal/blockchain/ethereum/ethereum_test.go
index cf31eb09e..0aa7292fd 100644
--- a/internal/blockchain/ethereum/ethereum_test.go
+++ b/internal/blockchain/ethereum/ethereum_test.go
@@ -326,6 +326,7 @@ func TestInitNewConfig(t *testing.T) {
 	utEthconnectConf.Set(ffresty.HTTPConfigURL, "http://localhost:12345")
 	utEthconnectConf.Set(ffresty.HTTPCustomClient, mockedClient)
 	utEthconnectConf.Set(EthconnectConfigTopic, "topic1")
+	utConfig.AddKnownKey(FireFlyContractConfigKey+".0."+FireFlyContractAddress, "0x71C7656EC7ab88b098defB751B7401B5f6d8976F")
 
 	err := e.Init(e.ctx, utConfig, e.metrics)
 	assert.Equal(t, 2, httpmock.GetTotalCallCount())
@@ -350,6 +351,7 @@ func TestInitNewConfigBadIndex(t *testing.T) {
 	utEthconnectConf.Set(ffresty.HTTPConfigURL, "http://localhost:12345")
 	utEthconnectConf.Set(ffresty.HTTPCustomClient, mockedClient)
 	utEthconnectConf.Set(EthconnectConfigTopic, "topic1")
+	utConfig.AddKnownKey(FireFlyContractConfigKey+".0."+FireFlyContractAddress, "")
 
 	err := e.Init(e.ctx, utConfig, e.metrics)
 	assert.NoError(t, err)
@@ -379,6 +381,7 @@ func TestInitNetworkVersionNotFound(t *testing.T) {
 	utEthconnectConf.Set(ffresty.HTTPConfigURL, "http://localhost:12345")
 	utEthconnectConf.Set(ffresty.HTTPCustomClient, mockedClient)
 	utEthconnectConf.Set(EthconnectConfigTopic, "topic1")
+	utConfig.AddKnownKey(FireFlyContractConfigKey+".0."+FireFlyContractAddress, "0x71C7656EC7ab88b098defB751B7401B5f6d8976F")
 
 	err := e.Init(e.ctx, utConfig, e.metrics)
 	assert.NoError(t, err)
@@ -972,7 +975,7 @@ func TestHandleMessageBatchPinOK(t *testing.T) {
 			]
     },
 		"subId": "sb-b5b97a4e-a317-4053-6400-1474650efcb5",
-		"signature": "0x1C197604587F046FD40684A8f21f4609FB811A7b:BatchPin(address,uint256,string,bytes32,bytes32,string,bytes32[])",
+		"signature": "BatchPin(address,uint256,string,bytes32,bytes32,string,bytes32[])",
 		"logIndex": "50",
 		"timestamp": "1620576488"
   },
@@ -1059,7 +1062,7 @@ func TestHandleMessageBatchPinOK(t *testing.T) {
 		"address":          "0x1C197604587F046FD40684A8f21f4609FB811A7b",
 		"blockNumber":      "38011",
 		"logIndex":         "50",
-		"signature":        "0x1C197604587F046FD40684A8f21f4609FB811A7b:BatchPin(address,uint256,string,bytes32,bytes32,string,bytes32[])",
+		"signature":        "BatchPin(address,uint256,string,bytes32,bytes32,string,bytes32[])",
 		"subId":            "sb-b5b97a4e-a317-4053-6400-1474650efcb5",
 		"transactionHash":  "0xc26df2bf1a733e9249372d61eb11bd8662d26c8129df76890b1beb2f6fa72628",
 		"transactionIndex": "0x0",
@@ -1349,90 +1352,6 @@ func TestHandleReceiptTXSuccess(t *testing.T) {
 	em.AssertExpectations(t)
 }
 
-func TestHandleReceiptTXUpdateEVMConnect(t *testing.T) {
-	em := &coremocks.OperationCallbacks{}
-	wsm := &wsmocks.WSClient{}
-	e := &Ethereum{
-		ctx:       context.Background(),
-		topic:     "topic1",
-		callbacks: common.NewBlockchainCallbacks(),
-		wsconn:    wsm,
-	}
-	e.SetOperationHandler("ns1", em)
-
-	var reply fftypes.JSONObject
-	operationID := fftypes.NewUUID()
-	data := fftypes.JSONAnyPtr(`{
-		"created": "2022-08-03T18:55:42.671166Z",
-		"errorHistory": null,
-		"firstSubmit": "2022-08-03T18:55:42.762254Z",
-		"gas": "48049",
-		"gasPrice": 0,
-		"headers": {
-			"requestId": "ns1:` + operationID.String() + `",
-			"type": "TransactionUpdate"
-		},
-		"id": "ns1:` + operationID.String() + `",
-		"lastSubmit": "2022-08-03T18:55:42.762254Z",
-		"nonce": "1",
-		"policyInfo": null,
-		"receipt": {
-			"blockHash": "0x972713d879efd32573fe4d88ed0cde94a094367d50f7e5bc8262dd41fe07d9e6",
-			"blockNumber": "3",
-			"extraInfo": {
-				"blockHash": "0x972713d879efd32573fe4d88ed0cde94a094367d50f7e5bc8262dd41fe07d9e6",
-				"blockNumber": "0x3",
-				"contractAddress": null,
-				"cumulativeGasUsed": "0x7d21",
-				"from": "0x081afaa6792a524ff2fb0654e615d19f9a600e57",
-				"gasUsed": "0x7d21",
-				"logs": [
-					{
-						"address": "0x9da7ecba282387ecd696dd9aecfc14efeb5f5fce",
-						"blockHash": "0x972713d879efd32573fe4d88ed0cde94a094367d50f7e5bc8262dd41fe07d9e6",
-						"blockNumber": "0x3",
-						"data": "0x000000000000000000000000081afaa6792a524ff2fb0654e615d19f9a600e570000000000000000000000000000000000000000000000000000000062eac4ae00000000000000000000000000000000000000000000000000000000000000e05fbe3d02be9341f492917ec5aecfb151d243287ac95c49f780a4259ab53a8d14ec218052055a2b541712ab3246354c36f3aa189e1f31a7a8b33cbf957014d2e6000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002e516d50535551486f5852617553346a5434544b55356f414167616d334d4132315642575777634c6e66536e35696d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018319d70666de18ed7d1c17e1bbd8ac0b16716fbe2059a8ae356a09d3bd067e14",
-						"logIndex": "0x0",
-						"removed": false,
-						"topics": [
-							"0x805721bc246bccc732581be0c0aa2dd8f7ec93e97ba4b307be84428c98b0a12f"
-						],
-						"transactionHash": "0x929c898a46762d91e9f4b0b8e2800863dcf4a40f694109dc4cd19dbd334fa4cc",
-						"transactionIndex": "0x0"
-					}
-				],
-				"status": "0x1",
-				"to": "0x9da7ecba282387ecd696dd9aecfc14efeb5f5fce",
-				"transactionHash": "0x929c898a46762d91e9f4b0b8e2800863dcf4a40f694109dc4cd19dbd334fa4cc",
-				"transactionIndex": "0x0"
-			},
-			"success": true,
-			"transactionIndex": "0"
-		},
-		"sequenceId": "dfd7c5e6-135d-11ed-80ff-b67a78953577",
-		"status": "Succeeded",
-		"transactionData": "0x48ce1dcc5fbe3d02be9341f492917ec5aecfb151d243287ac95c49f780a4259ab53a8d14ec218052055a2b541712ab3246354c36f3aa189e1f31a7a8b33cbf957014d2e6000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000002e516d50535551486f5852617553346a5434544b55356f414167616d334d4132315642575777634c6e66536e35696d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018319d70666de18ed7d1c17e1bbd8ac0b16716fbe2059a8ae356a09d3bd067e14",
-		"transactionHash": "0x929c898a46762d91e9f4b0b8e2800863dcf4a40f694109dc4cd19dbd334fa4cc",
-		"transactionHeaders": {
-			"from": "0x081afaa6792a524ff2fb0654e615d19f9a600e57",
-			"to": "0x9da7ecba282387ecd696dd9aecfc14efeb5f5fce"
-		},
-		"updated": "2022-08-03T18:55:43.781941Z"
-	}`)
-
-	em.On("OperationUpdate", e, mock.MatchedBy(func(update *core.OperationUpdate) bool {
-		return update.NamespacedOpID == "ns1:"+operationID.String() &&
-			update.Status == core.OpStatusPending &&
-			update.BlockchainTXID == "0x929c898a46762d91e9f4b0b8e2800863dcf4a40f694109dc4cd19dbd334fa4cc"
-	})).Return(nil)
-
-	err := json.Unmarshal(data.Bytes(), &reply)
-	assert.NoError(t, err)
-	e.handleReceipt(context.Background(), reply)
-
-	em.AssertExpectations(t)
-}
-
 func TestHandleBadPayloadsAndThenReceiptFailure(t *testing.T) {
 	e, cancel := newTestEthereum()
 	defer cancel()
@@ -2997,6 +2916,7 @@ func TestAddAndRemoveFireflySubscription(t *testing.T) {
 	utEthconnectConf.Set(ffresty.HTTPConfigURL, "http://localhost:12345")
 	utEthconnectConf.Set(ffresty.HTTPCustomClient, mockedClient)
 	utEthconnectConf.Set(EthconnectConfigTopic, "topic1")
+	utConfig.AddKnownKey(FireFlyContractConfigKey+".0."+FireFlyContractAddress, "0x71C7656EC7ab88b098defB751B7401B5f6d8976F")
 
 	err := e.Init(e.ctx, utConfig, e.metrics)
 	assert.NoError(t, err)
@@ -3039,6 +2959,7 @@ func TestAddFireflySubscriptionV1(t *testing.T) {
 	utEthconnectConf.Set(ffresty.HTTPConfigURL, "http://localhost:12345")
 	utEthconnectConf.Set(ffresty.HTTPCustomClient, mockedClient)
 	utEthconnectConf.Set(EthconnectConfigTopic, "topic1")
+	utConfig.AddKnownKey(FireFlyContractConfigKey+".0."+FireFlyContractAddress, "0x71C7656EC7ab88b098defB751B7401B5f6d8976F")
 
 	err := e.Init(e.ctx, utConfig, e.metrics)
 	assert.NoError(t, err)
@@ -3076,6 +2997,7 @@ func TestAddFireflySubscriptionQuerySubsFail(t *testing.T) {
 	utEthconnectConf.Set(ffresty.HTTPConfigURL, "http://localhost:12345")
 	utEthconnectConf.Set(ffresty.HTTPCustomClient, mockedClient)
 	utEthconnectConf.Set(EthconnectConfigTopic, "topic1")
+	utConfig.AddKnownKey(FireFlyContractConfigKey+".0."+FireFlyContractAddress, "0x71C7656EC7ab88b098defB751B7401B5f6d8976F")
 
 	err := e.Init(e.ctx, utConfig, e.metrics)
 	assert.NoError(t, err)
@@ -3113,6 +3035,7 @@ func TestAddFireflySubscriptionCreateError(t *testing.T) {
 	utEthconnectConf.Set(ffresty.HTTPConfigURL, "http://localhost:12345")
 	utEthconnectConf.Set(ffresty.HTTPCustomClient, mockedClient)
 	utEthconnectConf.Set(EthconnectConfigTopic, "topic1")
+	utConfig.AddKnownKey(FireFlyContractConfigKey+".0."+FireFlyContractAddress, "0x71C7656EC7ab88b098defB751B7401B5f6d8976F")
 
 	err := e.Init(e.ctx, utConfig, e.metrics)
 	assert.NoError(t, err)
@@ -3149,6 +3072,7 @@ func TestAddFireflySubscriptionGetVersionError(t *testing.T) {
 	utEthconnectConf.Set(ffresty.HTTPConfigURL, "http://localhost:12345")
 	utEthconnectConf.Set(ffresty.HTTPCustomClient, mockedClient)
 	utEthconnectConf.Set(EthconnectConfigTopic, "topic1")
+	utConfig.AddKnownKey(FireFlyContractConfigKey+".0."+FireFlyContractAddress, "0x71C7656EC7ab88b098defB751B7401B5f6d8976F")
 
 	err := e.Init(e.ctx, utConfig, e.metrics)
 	assert.NoError(t, err)
diff --git a/internal/blockchain/fabric/fabric_test.go b/internal/blockchain/fabric/fabric_test.go
index 8e2f373de..fe038adbc 100644
--- a/internal/blockchain/fabric/fabric_test.go
+++ b/internal/blockchain/fabric/fabric_test.go
@@ -469,6 +469,7 @@ func TestInitNewConfig(t *testing.T) {
 	utFabconnectConf.Set(ffresty.HTTPCustomClient, mockedClient)
 	utFabconnectConf.Set(FabconnectConfigSigner, "signer001")
 	utFabconnectConf.Set(FabconnectConfigTopic, "topic1")
+	utConfig.AddKnownKey(FireFlyContractConfigKey+".0."+FireFlyContractChaincode, "firefly")
 
 	err := e.Init(e.ctx, utConfig, &metricsmocks.Manager{})
 	assert.NoError(t, err)
diff --git a/internal/broadcast/manager_test.go b/internal/broadcast/manager_test.go
index 45ab6144f..f879f8c89 100644
--- a/internal/broadcast/manager_test.go
+++ b/internal/broadcast/manager_test.go
@@ -168,7 +168,7 @@ func TestBroadcastMessageBad(t *testing.T) {
 
 }
 
-func TestDispatchBatchBlobsFail(t *testing.T) {
+func TestDispatchBatchBlobsFaill(t *testing.T) {
 	bm, cancel := newTestBroadcast(t)
 	defer cancel()
 
@@ -182,9 +182,6 @@ func TestDispatchBatchBlobsFail(t *testing.T) {
 		Pins: []*fftypes.Bytes32{fftypes.NewRandB32()},
 	}
 
-	mom := bm.operations.(*operationmocks.Manager)
-	mom.On("AddOrReuseOperation", mock.Anything, mock.Anything).Return(nil)
-
 	mdi := bm.database.(*databasemocks.Plugin)
 	mdi.On("GetBlobMatchingHash", bm.ctx, blobHash).Return(nil, fmt.Errorf("pop"))
 
@@ -192,7 +189,6 @@ func TestDispatchBatchBlobsFail(t *testing.T) {
 	assert.EqualError(t, err, "pop")
 
 	mdi.AssertExpectations(t)
-	mom.AssertExpectations(t)
 }
 
 func TestDispatchBatchInsertOpFail(t *testing.T) {
@@ -317,7 +313,6 @@ func TestUploadBlobsPublishFail(t *testing.T) {
 
 	ctx := context.Background()
 	mdi.On("GetBlobMatchingHash", ctx, blob.Hash).Return(blob, nil)
-	mom.On("AddOrReuseOperation", mock.Anything, mock.Anything).Return(nil)
 	mom.On("RunOperation", mock.Anything, mock.MatchedBy(func(op *core.PreparedOperation) bool {
 		data := op.Data.(uploadBlobData)
 		return op.Type == core.OpTypeSharedStorageUploadBlob && data.Blob == blob
@@ -353,9 +348,6 @@ func TestUploadBlobsGetBlobFail(t *testing.T) {
 	ctx := context.Background()
 	mdi.On("GetBlobMatchingHash", ctx, blob.Hash).Return(nil, fmt.Errorf("pop"))
 
-	mom := bm.operations.(*operationmocks.Manager)
-	mom.On("AddOrReuseOperation", mock.Anything, mock.Anything).Return(nil)
-
 	err := bm.uploadBlobs(ctx, fftypes.NewUUID(), core.DataArray{
 		{
 			ID: dataID,
@@ -367,7 +359,6 @@ func TestUploadBlobsGetBlobFail(t *testing.T) {
 	assert.Regexp(t, "pop", err)
 
 	mdi.AssertExpectations(t)
-	mom.AssertExpectations(t)
 
 }
 
@@ -385,9 +376,6 @@ func TestUploadBlobsGetBlobNotFound(t *testing.T) {
 	ctx := context.Background()
 	mdi.On("GetBlobMatchingHash", ctx, blob.Hash).Return(nil, nil)
 
-	mom := bm.operations.(*operationmocks.Manager)
-	mom.On("AddOrReuseOperation", mock.Anything, mock.Anything).Return(nil)
-
 	err := bm.uploadBlobs(ctx, fftypes.NewUUID(), core.DataArray{
 		{
 			ID: dataID,
@@ -399,34 +387,5 @@ func TestUploadBlobsGetBlobNotFound(t *testing.T) {
 	assert.Regexp(t, "FF10239", err)
 
 	mdi.AssertExpectations(t)
-	mom.AssertExpectations(t)
-
-}
-
-func TestUploadBlobsGetBlobInsertOpFail(t *testing.T) {
-	bm, cancel := newTestBroadcast(t)
-	defer cancel()
-
-	blob := &core.Blob{
-		Hash:       fftypes.NewRandB32(),
-		PayloadRef: "blob/1",
-	}
-	dataID := fftypes.NewUUID()
-	ctx := context.Background()
-
-	mom := bm.operations.(*operationmocks.Manager)
-	mom.On("AddOrReuseOperation", mock.Anything, mock.Anything).Return(fmt.Errorf("pop"))
-
-	err := bm.uploadBlobs(ctx, fftypes.NewUUID(), core.DataArray{
-		{
-			ID: dataID,
-			Blob: &core.BlobRef{
-				Hash: blob.Hash,
-			},
-		},
-	})
-	assert.EqualError(t, err, "pop")
-
-	mom.AssertExpectations(t)
 
 }
diff --git a/test/e2e/run.sh b/test/e2e/run.sh
index e77a2774e..145e46ff5 100755
--- a/test/e2e/run.sh
+++ b/test/e2e/run.sh
@@ -7,6 +7,7 @@ set -o pipefail
 CWD=$(dirname "$0")
 CLI="ff -v --ansi never"
 CLI_VERSION=$(cat $CWD/../../manifest.json | jq -r .cli.tag)
+STACKS_DIR=~/.firefly/stacks
 
 create_accounts() {
   if [ "$TEST_SUITE" == "TestEthereumMultipartyE2ESuite" ]; then
@@ -35,21 +36,46 @@ checkOk() {
   mkdir -p "${WORKDIR}/containerlogs"
   $CLI logs $STACK_NAME > "${WORKDIR}/containerlogs/logs.txt"
   if [ $rc -eq 0 ]; then rc=$?; fi
+
   if [ $rc -ne 0 ]; then exit $rc; fi
 }
 
-STACK_NAME=${STACK_NAME:-firefly_e2e}
-STACKS_DIR=${STACKS_DIR:-~/.firefly/stacks}
-STACK_DIR=${STACK_DIR:-$STACKS_DIR/$STACK_NAME}
+if [ -z "${STACK_NAME}" ]; then
+  STACK_NAME=firefly_e2e
+fi
+
+if [ -z "${DOWNLOAD_CLI}" ]; then
+  DOWNLOAD_CLI=true
+fi
 
-DOWNLOAD_CLI=${DOWNLOAD_CLI:-true}
-CREATE_STACK=${CREATE_STACK:-true}
-BUILD_FIREFLY=${BUILD_FIREFLY:-true}
-MULTIPARTY_ENABLED=${MULTIPARTY_ENABLED:-true}
+if [ -z "${CREATE_STACK}" ]; then
+  CREATE_STACK=true
+fi
 
-DATABASE_TYPE=${DATABASE_TYPE:-sqlite3}
-BLOCKCHAIN_PROVIDER=${BLOCKCHAIN_PROVIDER:-geth}
-TOKENS_PROVIDER=${TOKENS_PROVIDER:-erc20_erc721}
+if [ -z "${BUILD_FIREFLY}" ]; then
+  BUILD_FIREFLY=true
+fi
+
+if [ -z "${DATABASE_TYPE}" ]; then
+  # Can also set to "postgres"
+  DATABASE_TYPE=sqlite3
+fi
+
+if [ -z "${MULTIPARTY_ENABLED}" ]; then
+  MULTIPARTY_ENABLED=true
+fi
+
+if [ -z "${STACK_DIR}" ]; then
+  STACK_DIR=$STACKS_DIR/$STACK_NAME
+fi
+
+if [ -z "${BLOCKCHAIN_PROVIDER}" ]; then
+  BLOCKCHAIN_PROVIDER=geth
+fi
+
+if [ -z "${TOKENS_PROVIDER}" ]; then
+  TOKENS_PROVIDER=erc20_erc721
+fi
 
 if [ -z "${TEST_SUITE}" ]; then
   if [ "${BLOCKCHAIN_PROVIDER}" == "fabric" ]; then
@@ -69,6 +95,10 @@ fi
 
 cd $CWD
 
+if [ "$CREATE_STACK" == "true" ]; then
+  $CLI remove -f $STACK_NAME
+fi
+
 if [ "$BUILD_FIREFLY" == "true" ]; then
   make -C ../.. docker
   checkOk $?
@@ -80,7 +110,6 @@ if [ "$DOWNLOAD_CLI" == "true" ]; then
 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 --token-providers $TOKENS_PROVIDER --manifest ../../manifest.json $EXTRA_INIT_ARGS --sandbox-enabled=false --multiparty=$MULTIPARTY_ENABLED
   checkOk $?