From 1c4824fabbaeca30a43a9949616a2d7c0db528bc Mon Sep 17 00:00:00 2001 From: Alex Shorsher Date: Tue, 2 Aug 2022 11:11:13 -0400 Subject: [PATCH 1/7] move `keynormalization` config under namespaces Signed-off-by: Alex Shorsher --- docs/reference/config.md | 8 +++++++- internal/assets/manager.go | 6 ++---- internal/assets/manager_test.go | 4 ++-- internal/coreconfig/coreconfig.go | 4 +++- internal/coremsgs/en_config_descriptions.go | 3 ++- internal/namespace/config.go | 2 ++ internal/namespace/manager.go | 6 ++++++ internal/orchestrator/orchestrator.go | 3 ++- 8 files changed, 26 insertions(+), 10 deletions(-) diff --git a/docs/reference/config.md b/docs/reference/config.md index e1009783d0..8d2f815374 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -30,7 +30,7 @@ nav_order: 2 |Key|Description|Type|Default Value| |---|-----------|----|-------------| -|keyNormalization|Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization|`string`|`` +|keynormalization|Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization|`string`|`` ## batch.cache @@ -622,6 +622,12 @@ nav_order: 2 |plugins|The list of plugins for this namespace|`string`|`` |remotename|The namespace name to be sent in plugin calls, if it differs from namespace name|`string`|`` +## namespaces.predefined[].assets.manager + +|Key|Description|Type|Default Value| +|---|-----------|----|-------------| +|keynormalization|Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization|`string`|`` + ## namespaces.predefined[].multiparty |Key|Description|Type|Default Value| diff --git a/internal/assets/manager.go b/internal/assets/manager.go index 2d92284393..fc05916fe3 100644 --- a/internal/assets/manager.go +++ b/internal/assets/manager.go @@ -19,11 +19,9 @@ package assets import ( "context" - "github.com/hyperledger/firefly-common/pkg/config" "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/broadcast" - "github.com/hyperledger/firefly/internal/coreconfig" "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/internal/identity" "github.com/hyperledger/firefly/internal/metrics" @@ -84,7 +82,7 @@ type assetManager struct { keyNormalization int } -func NewAssetManager(ctx context.Context, ns string, di database.Plugin, ti map[string]tokens.Plugin, im identity.Manager, sa syncasync.Bridge, bm broadcast.Manager, pm privatemessaging.Manager, mm metrics.Manager, om operations.Manager, txHelper txcommon.Helper) (Manager, error) { +func NewAssetManager(ctx context.Context, ns, keyNormalization string, di database.Plugin, ti map[string]tokens.Plugin, im identity.Manager, sa syncasync.Bridge, bm broadcast.Manager, pm privatemessaging.Manager, mm metrics.Manager, om operations.Manager, txHelper txcommon.Helper) (Manager, error) { if di == nil || im == nil || sa == nil || ti == nil || mm == nil || om == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "AssetManager") } @@ -98,7 +96,7 @@ func NewAssetManager(ctx context.Context, ns string, di database.Plugin, ti map[ broadcast: bm, messaging: pm, tokens: ti, - keyNormalization: identity.ParseKeyNormalizationConfig(config.GetString(coreconfig.AssetManagerKeyNormalization)), + keyNormalization: identity.ParseKeyNormalizationConfig(keyNormalization), metrics: mm, operations: om, } diff --git a/internal/assets/manager_test.go b/internal/assets/manager_test.go index 6cae98b09d..851cf54ffa 100644 --- a/internal/assets/manager_test.go +++ b/internal/assets/manager_test.go @@ -63,7 +63,7 @@ func newTestAssetsCommon(t *testing.T, metrics bool) (*assetManager, func()) { mom.On("RegisterHandler", mock.Anything, mock.Anything, mock.Anything) mti.On("Name").Return("ut").Maybe() ctx, cancel := context.WithCancel(context.Background()) - a, err := NewAssetManager(ctx, "ns1", mdi, map[string]tokens.Plugin{"magic-tokens": mti}, mim, msa, mbm, mpm, mm, mom, txHelper) + a, err := NewAssetManager(ctx, "ns1", "blockchain_plugin", mdi, map[string]tokens.Plugin{"magic-tokens": mti}, mim, msa, mbm, mpm, mm, mom, txHelper) rag := mdi.On("RunAsGroup", mock.Anything, mock.Anything).Maybe() rag.RunFn = func(a mock.Arguments) { rag.ReturnArguments = mock.Arguments{a[1].(func(context.Context) error)(a[0].(context.Context))} @@ -75,7 +75,7 @@ func newTestAssetsCommon(t *testing.T, metrics bool) (*assetManager, func()) { } func TestInitFail(t *testing.T) { - _, err := NewAssetManager(context.Background(), "", nil, nil, nil, nil, nil, nil, nil, nil, nil) + _, err := NewAssetManager(context.Background(), "", "", nil, nil, nil, nil, nil, nil, nil, nil, nil) assert.Regexp(t, "FF10128", err) } diff --git a/internal/coreconfig/coreconfig.go b/internal/coreconfig/coreconfig.go index 6e04aa28dc..e600a81fd8 100644 --- a/internal/coreconfig/coreconfig.go +++ b/internal/coreconfig/coreconfig.go @@ -41,6 +41,8 @@ const ( NamespacePlugins = "plugins" // NamespaceDefaultKey is the default signing key for blockchain transactions within this namespace NamespaceDefaultKey = "defaultkey" + // NamespaceAssetKeyNormalization mechanism to normalize keys before using them. Valid options: "blockchain_plugin" - use blockchain plugin (default), "none" - do not attempt normalization + NamespaceAssetKeyNormalization = "assets.manager.keynormalization" // NamespaceMultiparty contains the multiparty configuration for a namespace NamespaceMultiparty = "multiparty" // NamespaceMultipartyEnabled specifies if multi-party mode is enabled for a namespace @@ -287,7 +289,7 @@ var ( // TransactionCacheTTL TransactionCacheTTL = ffc("transaction.cache.ttl") // AssetManagerKeyNormalization mechanism to normalize keys before using them. Valid options: "blockchain_plugin" - use blockchain plugin (default), "none" - do not attempt normalization - AssetManagerKeyNormalization = ffc("asset.manager.keyNormalization") + AssetManagerKeyNormalization = ffc("asset.manager.keynormalization") // UIEnabled set to false to disable the UI (default is true, so UI will be enabled if ui.path is valid) UIEnabled = ffc("ui.enabled") // UIPath the path on which to serve the UI diff --git a/internal/coremsgs/en_config_descriptions.go b/internal/coremsgs/en_config_descriptions.go index cd26b52836..915edb74ba 100644 --- a/internal/coremsgs/en_config_descriptions.go +++ b/internal/coremsgs/en_config_descriptions.go @@ -41,7 +41,7 @@ var ( ConfigAPIDefaultFilterLimit = ffc("config.api.defaultFilterLimit", "The maximum number of rows to return if no limit is specified on an API request", i18n.IntType) ConfigAPIMaxFilterLimit = ffc("config.api.maxFilterLimit", "The largest value of `limit` that an HTTP client can specify in a request", i18n.IntType) ConfigAPIRequestMaxTimeout = ffc("config.api.requestMaxTimeout", "The maximum amount of time that an HTTP client can specify in a `Request-Timeout` header to keep a specific request open", i18n.TimeDurationType) - ConfigAssetManagerKeyNormalization = ffc("config.asset.manager.keyNormalization", "Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization", i18n.StringType) + ConfigAssetManagerKeyNormalization = ffc("config.asset.manager.keynormalization", "Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization (deprecated - namespace.predefined[].assets.manager.keynormalization)", i18n.StringType) ConfigBatchManagerMinimumPollDelay = ffc("config.batch.manager.minimumPollDelay", "The minimum time the batch manager waits between polls on the DB - to prevent thrashing", i18n.TimeDurationType) ConfigBatchManagerPollTimeout = ffc("config.batch.manager.pollTimeout", "How long to wait without any notifications of new messages before doing a page query", i18n.TimeDurationType) @@ -257,6 +257,7 @@ var ( ConfigNamespacesPredefinedPlugins = ffc("config.namespaces.predefined[].plugins", "The list of plugins for this namespace", i18n.StringType) ConfigNamespacesPredefinedRemoteName = ffc("config.namespaces.predefined[].remotename", "The namespace name to be sent in plugin calls, if it differs from namespace name", i18n.StringType) ConfigNamespacesPredefinedDefaultKey = ffc("config.namespaces.predefined[].defaultkey", "A default signing key for blockchain transactions within this namespace", i18n.StringType) + ConfigNamespacesPredefinedKeyNormalization = ffc("config.namespaces.predefined[].assets.manager.keynormalization", "Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization", i18n.StringType) ConfigNamespacesMultipartyEnabled = ffc("config.namespaces.predefined[].multiparty.enabled", "Enables multi-party mode for this namespace (defaults to true if an org name or key is configured, either here or at the root level)", i18n.BooleanType) ConfigNamespacesMultipartyOrgName = ffc("config.namespaces.predefined[].multiparty.org.name", "A short name for the local root organization within this namespace", i18n.StringType) ConfigNamespacesMultipartyOrgDesc = ffc("config.namespaces.predefined[].multiparty.org.description", "A description for the local root organization within this namespace", i18n.StringType) diff --git a/internal/namespace/config.go b/internal/namespace/config.go index 1a89094644..c8d57abcd3 100644 --- a/internal/namespace/config.go +++ b/internal/namespace/config.go @@ -39,6 +39,7 @@ func InitConfig(withDefaults bool) { namespacePredefined.AddKnownKey(coreconfig.NamespaceRemoteName) namespacePredefined.AddKnownKey(coreconfig.NamespacePlugins) namespacePredefined.AddKnownKey(coreconfig.NamespaceDefaultKey) + namespacePredefined.AddKnownKey(coreconfig.NamespaceAssetKeyNormalization) multipartyConf := namespacePredefined.SubSection(coreconfig.NamespaceMultiparty) multipartyConf.AddKnownKey(coreconfig.NamespaceMultipartyEnabled) @@ -55,5 +56,6 @@ func InitConfig(withDefaults bool) { if withDefaults { namespaceConfig.AddKnownKey(NamespacePredefined+".0."+coreconfig.NamespaceName, "default") namespaceConfig.AddKnownKey(NamespacePredefined+".0."+coreconfig.NamespaceDescription, "Default predefined namespace") + namespaceConfig.AddKnownKey(NamespacePredefined+".0."+coreconfig.NamespaceAssetKeyNormalization, "blockchain_plugin") } } diff --git a/internal/namespace/manager.go b/internal/namespace/manager.go index 07e22cad9e..2dca5d5a0f 100644 --- a/internal/namespace/manager.go +++ b/internal/namespace/manager.go @@ -791,6 +791,11 @@ func (nm *namespaceManager) loadNamespace(ctx context.Context, name string, inde remoteName = name } + keyNormalization := conf.GetString(coreconfig.NamespaceAssetKeyNormalization) + if keyNormalization == "" { + keyNormalization = config.GetString(coreconfig.AssetManagerKeyNormalization) + } + multipartyConf := conf.SubSection(coreconfig.NamespaceMultiparty) // If any multiparty org information is configured (here or at the root), assume multiparty mode by default orgName := multipartyConf.GetString(coreconfig.NamespaceMultipartyOrgName) @@ -859,6 +864,7 @@ func (nm *namespaceManager) loadNamespace(ctx context.Context, name string, inde config := orchestrator.Config{ DefaultKey: conf.GetString(coreconfig.NamespaceDefaultKey), TokenRemoteNames: nm.tokenRemoteNames, + KeyNormalization: keyNormalization, } if multipartyEnabled.(bool) { contractsConf := multipartyConf.SubArray(coreconfig.NamespaceMultipartyContract) diff --git a/internal/orchestrator/orchestrator.go b/internal/orchestrator/orchestrator.go index 5f44e3b0d1..21ed04f270 100644 --- a/internal/orchestrator/orchestrator.go +++ b/internal/orchestrator/orchestrator.go @@ -170,6 +170,7 @@ type Plugins struct { type Config struct { DefaultKey string + KeyNormalization string Multiparty multiparty.Config TokenRemoteNames map[string]string } @@ -449,7 +450,7 @@ func (or *orchestrator) initManagers(ctx context.Context) (err error) { } if or.assets == nil { - or.assets, err = assets.NewAssetManager(ctx, or.namespace.LocalName, or.database(), or.tokens(), or.identity, or.syncasync, or.broadcast, or.messaging, or.metrics, or.operations, or.txHelper) + or.assets, err = assets.NewAssetManager(ctx, or.namespace.LocalName, or.config.KeyNormalization, or.database(), or.tokens(), or.identity, or.syncasync, or.broadcast, or.messaging, or.metrics, or.operations, or.txHelper) if err != nil { return err } From ba790af44d986409aa358d02227cb7b8f888fad9 Mon Sep 17 00:00:00 2001 From: Alex Shorsher Date: Tue, 2 Aug 2022 13:54:59 -0400 Subject: [PATCH 2/7] add e2e tests for tokens-only namespaces Signed-off-by: Alex Shorsher --- test/e2e/gateway/common.go | 37 ++++++ test/e2e/gateway/tokens_only.go | 144 ++++++++++++++++++++++ test/e2e/runners/ethereum_gateway_test.go | 1 + test/e2e/stack.go | 1 + 4 files changed, 183 insertions(+) create mode 100644 test/e2e/gateway/tokens_only.go diff --git a/test/e2e/gateway/common.go b/test/e2e/gateway/common.go index 8f1fef2b96..f22a09c6df 100644 --- a/test/e2e/gateway/common.go +++ b/test/e2e/gateway/common.go @@ -20,15 +20,19 @@ import ( "crypto/rand" "encoding/base64" "fmt" + "io/ioutil" "net/http" "os" "testing" "time" + "github.com/go-resty/resty/v2" "github.com/gorilla/websocket" "github.com/hyperledger/firefly/test/e2e" "github.com/hyperledger/firefly/test/e2e/client" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v2" ) const ( @@ -124,3 +128,36 @@ func randomName(t *testing.T) string { assert.NoError(t, err) return fmt.Sprintf("e2e_%x", b) } + +func readConfig(t *testing.T, configFile string) map[string]interface{} { + yfile, err := ioutil.ReadFile(configFile) + assert.NoError(t, err) + data := make(map[string]interface{}) + err = yaml.Unmarshal(yfile, &data) + assert.NoError(t, err) + return data +} + +func writeConfig(t *testing.T, configFile string, data map[string]interface{}) { + out, err := yaml.Marshal(data) + assert.NoError(t, err) + f, err := os.Create(configFile) + assert.NoError(t, err) + _, err = f.Write(out) + assert.NoError(t, err) + f.Close() +} + +func addNamespace(data map[string]interface{}, ns map[string]interface{}) { + namespaces := data["namespaces"].(map[interface{}]interface{}) + predefined := namespaces["predefined"].([]interface{}) + namespaces["predefined"] = append(predefined, ns) +} + +func resetFireFly(t *testing.T, client *resty.Client) { + resp, err := client.R(). + SetBody(map[string]interface{}{}). + Post("/reset") + require.NoError(t, err) + assert.Equal(t, 204, resp.StatusCode()) +} diff --git a/test/e2e/gateway/tokens_only.go b/test/e2e/gateway/tokens_only.go new file mode 100644 index 0000000000..df1017d4e8 --- /dev/null +++ b/test/e2e/gateway/tokens_only.go @@ -0,0 +1,144 @@ +// Copyright © 2022 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gateway + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/hyperledger/firefly-common/pkg/fftypes" + "github.com/hyperledger/firefly/pkg/core" + "github.com/hyperledger/firefly/test/e2e" + "github.com/hyperledger/firefly/test/e2e/client" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +type TokensOnlyTestSuite struct { + suite.Suite + testState *testState + connector string + db string + key string + adminHost1 string + configFile1 string +} + +func (suite *TokensOnlyTestSuite) SetupSuite() { + suite.testState = beforeE2ETest(suite.T()) + stack := e2e.ReadStack(suite.T()) + stackState := e2e.ReadStackState(suite.T()) + + adminProtocol1 := schemeHTTP + if stack.Members[0].UseHTTPS { + adminProtocol1 = schemeHTTPS + } + suite.adminHost1 = fmt.Sprintf("%s://%s:%d", adminProtocol1, stack.Members[0].FireflyHostname, stack.Members[0].ExposedAdminPort) + + stackDir := os.Getenv("STACK_DIR") + if stackDir == "" { + suite.T().Fatal("STACK_DIR must be set") + } + suite.configFile1 = filepath.Join(stackDir, "runtime", "config", "firefly_core_0.yml") + + suite.connector = stack.TokenProviders[0] + suite.db = stack.Database + account := stackState.Accounts[0].(map[string]interface{}) + suite.key = account["address"].(string) +} + +func (suite *TokensOnlyTestSuite) BeforeTest(suiteName, testName string) { + suite.testState = beforeE2ETest(suite.T()) +} + +func (suite *TokensOnlyTestSuite) AfterTest(suiteName, testName string) { + e2e.VerifyAllOperationsSucceeded(suite.T(), []*client.FireFlyClient{suite.testState.client1}, suite.testState.startTime) +} + +func (suite *TokensOnlyTestSuite) TestTokensOnlyNamespaces() { + defer suite.testState.Done() + testNamespace := randomName(suite.T()) + suite.T().Logf("Test namespace: %s", testNamespace) + + namespaceInfo := map[string]interface{}{ + "name": testNamespace, + "assets": map[string]interface{}{ + "manager": map[string]interface{}{ + "keynormalization": "none", + }, + }, + "plugins": []string{"database0", suite.connector}, + } + + // Add the new namespace + data1 := readConfig(suite.T(), suite.configFile1) + addNamespace(data1, namespaceInfo) + writeConfig(suite.T(), suite.configFile1, data1) + + admin1 := client.NewResty(suite.T()) + admin1.SetBaseURL(suite.adminHost1 + "/spi/v1") + + resetFireFly(suite.T(), admin1) + e2e.PollForUp(suite.T(), suite.testState.client1) + + client1 := client.NewFireFly(suite.T(), suite.testState.client1.Hostname, testNamespace) + eventNames := "token_pool_confirmed|token_transfer_confirmed" + queryString := fmt.Sprintf("namespace=%s&ephemeral&autoack&filter.events=%s", testNamespace, eventNames) + received1 := e2e.WsReader(client1.WebSocket(suite.T(), queryString, nil)) + + // Attempt async token operations on new namespace + poolName := fmt.Sprintf("pool_%s", randomName(suite.T())) + suite.T().Logf("Pool name: %s", poolName) + + pool := &core.TokenPool{ + Name: poolName, + Key: suite.key, + Type: core.TokenTypeFungible, + } + poolResp := client1.CreateTokenPool(suite.T(), pool, false) + poolID := poolResp.ID + + e2e.WaitForEvent(suite.T(), received1, core.EventTypePoolConfirmed, poolID) + pools := client1.GetTokenPools(suite.T(), suite.testState.startTime) + assert.Equal(suite.T(), 1, len(pools)) + assert.Equal(suite.T(), testNamespace, pools[0].Namespace) + assert.Equal(suite.T(), suite.connector, pools[0].Connector) + assert.Equal(suite.T(), poolName, pools[0].Name) + assert.Equal(suite.T(), core.TokenTypeFungible, pools[0].Type) + assert.NotEmpty(suite.T(), pools[0].Locator) + + transfer := &core.TokenTransferInput{ + TokenTransfer: core.TokenTransfer{Amount: *fftypes.NewFFBigInt(1), Key: suite.key}, + Pool: poolName, + } + transferOut := client1.MintTokens(suite.T(), transfer, false) + e2e.WaitForEvent(suite.T(), received1, core.EventTypeTransferConfirmed, transferOut.LocalID) + e2e.ValidateAccountBalances(suite.T(), client1, poolID, "", map[string]int64{ + suite.key: 1, + }) + + transfer = &core.TokenTransferInput{ + TokenTransfer: core.TokenTransfer{Amount: *fftypes.NewFFBigInt(1), Key: suite.key}, + Pool: poolName, + } + transferOut = client1.BurnTokens(suite.T(), transfer, false) + e2e.WaitForEvent(suite.T(), received1, core.EventTypeTransferConfirmed, transferOut.LocalID) + e2e.ValidateAccountBalances(suite.T(), client1, poolID, "", map[string]int64{ + suite.key: 0, + }) +} diff --git a/test/e2e/runners/ethereum_gateway_test.go b/test/e2e/runners/ethereum_gateway_test.go index d0f53cfbb4..91afbd057e 100644 --- a/test/e2e/runners/ethereum_gateway_test.go +++ b/test/e2e/runners/ethereum_gateway_test.go @@ -26,4 +26,5 @@ import ( func TestEthereumGatewayE2ESuite(t *testing.T) { suite.Run(t, new(gateway.TokensTestSuite)) suite.Run(t, new(gateway.EthereumContractTestSuite)) + suite.Run(t, new(gateway.TokensOnlyTestSuite)) } diff --git a/test/e2e/stack.go b/test/e2e/stack.go index 1d9392194a..74f3225112 100644 --- a/test/e2e/stack.go +++ b/test/e2e/stack.go @@ -27,6 +27,7 @@ type Stack struct { BlockchainProvider string `json:"blockchainProvider"` TokenProviders []string `json:"tokenProviders"` Members []*Member `json:"members,omitempty"` + Database string `json:"database"` } type StackState struct { From 5b8da24456e383abaf105011ae2b630c3630d694 Mon Sep 17 00:00:00 2001 From: Alex Shorsher Date: Tue, 2 Aug 2022 14:29:53 -0400 Subject: [PATCH 3/7] commonize e2e code moving code for adding namespaces to config, resetting ff, etc. into a common package Signed-off-by: Alex Shorsher --- test/e2e/common.go | 70 +++++++++++++++++++++++ test/e2e/gateway/common.go | 46 --------------- test/e2e/gateway/tokens.go | 2 +- test/e2e/gateway/tokens_only.go | 12 ++-- test/e2e/multiparty/common.go | 45 --------------- test/e2e/multiparty/contract_migration.go | 18 +++--- test/e2e/multiparty/namespace_alias.go | 22 +++---- test/e2e/multiparty/tokens.go | 4 +- 8 files changed, 99 insertions(+), 120 deletions(-) create mode 100644 test/e2e/common.go diff --git a/test/e2e/common.go b/test/e2e/common.go new file mode 100644 index 0000000000..d975a44dc8 --- /dev/null +++ b/test/e2e/common.go @@ -0,0 +1,70 @@ +// Copyright © 2022 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "crypto/rand" + "fmt" + "io/ioutil" + "os" + "testing" + + "github.com/go-resty/resty/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v2" +) + +func ReadConfig(t *testing.T, configFile string) map[string]interface{} { + yfile, err := ioutil.ReadFile(configFile) + assert.NoError(t, err) + data := make(map[string]interface{}) + err = yaml.Unmarshal(yfile, &data) + assert.NoError(t, err) + return data +} + +func WriteConfig(t *testing.T, configFile string, data map[string]interface{}) { + out, err := yaml.Marshal(data) + assert.NoError(t, err) + f, err := os.Create(configFile) + assert.NoError(t, err) + _, err = f.Write(out) + assert.NoError(t, err) + f.Close() +} + +func AddNamespace(data map[string]interface{}, ns map[string]interface{}) { + namespaces := data["namespaces"].(map[interface{}]interface{}) + predefined := namespaces["predefined"].([]interface{}) + namespaces["predefined"] = append(predefined, ns) +} + +func ResetFireFly(t *testing.T, client *resty.Client) { + resp, err := client.R(). + SetBody(map[string]interface{}{}). + Post("/reset") + require.NoError(t, err) + assert.Equal(t, 204, resp.StatusCode()) +} + +func RandomName(t *testing.T) string { + b := make([]byte, 5) + _, err := rand.Read(b) + assert.NoError(t, err) + return fmt.Sprintf("e2e_%x", b) +} diff --git a/test/e2e/gateway/common.go b/test/e2e/gateway/common.go index f22a09c6df..d59f79a27a 100644 --- a/test/e2e/gateway/common.go +++ b/test/e2e/gateway/common.go @@ -17,22 +17,16 @@ package gateway import ( - "crypto/rand" "encoding/base64" "fmt" - "io/ioutil" "net/http" "os" "testing" "time" - "github.com/go-resty/resty/v2" "github.com/gorilla/websocket" "github.com/hyperledger/firefly/test/e2e" "github.com/hyperledger/firefly/test/e2e/client" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "gopkg.in/yaml.v2" ) const ( @@ -121,43 +115,3 @@ func beforeE2ETest(t *testing.T) *testState { } return ts } - -func randomName(t *testing.T) string { - b := make([]byte, 5) - _, err := rand.Read(b) - assert.NoError(t, err) - return fmt.Sprintf("e2e_%x", b) -} - -func readConfig(t *testing.T, configFile string) map[string]interface{} { - yfile, err := ioutil.ReadFile(configFile) - assert.NoError(t, err) - data := make(map[string]interface{}) - err = yaml.Unmarshal(yfile, &data) - assert.NoError(t, err) - return data -} - -func writeConfig(t *testing.T, configFile string, data map[string]interface{}) { - out, err := yaml.Marshal(data) - assert.NoError(t, err) - f, err := os.Create(configFile) - assert.NoError(t, err) - _, err = f.Write(out) - assert.NoError(t, err) - f.Close() -} - -func addNamespace(data map[string]interface{}, ns map[string]interface{}) { - namespaces := data["namespaces"].(map[interface{}]interface{}) - predefined := namespaces["predefined"].([]interface{}) - namespaces["predefined"] = append(predefined, ns) -} - -func resetFireFly(t *testing.T, client *resty.Client) { - resp, err := client.R(). - SetBody(map[string]interface{}{}). - Post("/reset") - require.NoError(t, err) - assert.Equal(t, 204, resp.StatusCode()) -} diff --git a/test/e2e/gateway/tokens.go b/test/e2e/gateway/tokens.go index 81cb49a222..8e67a2711e 100644 --- a/test/e2e/gateway/tokens.go +++ b/test/e2e/gateway/tokens.go @@ -56,7 +56,7 @@ func (suite *TokensTestSuite) TestE2EFungibleTokensAsync() { received1 := e2e.WsReader(suite.testState.ws1) - poolName := fmt.Sprintf("pool_%s", randomName(suite.T())) + poolName := fmt.Sprintf("pool_%s", e2e.RandomName(suite.T())) suite.T().Logf("Pool name: %s", poolName) pool := &core.TokenPool{ diff --git a/test/e2e/gateway/tokens_only.go b/test/e2e/gateway/tokens_only.go index df1017d4e8..a5ed4f388b 100644 --- a/test/e2e/gateway/tokens_only.go +++ b/test/e2e/gateway/tokens_only.go @@ -72,7 +72,7 @@ func (suite *TokensOnlyTestSuite) AfterTest(suiteName, testName string) { func (suite *TokensOnlyTestSuite) TestTokensOnlyNamespaces() { defer suite.testState.Done() - testNamespace := randomName(suite.T()) + testNamespace := e2e.RandomName(suite.T()) suite.T().Logf("Test namespace: %s", testNamespace) namespaceInfo := map[string]interface{}{ @@ -86,14 +86,14 @@ func (suite *TokensOnlyTestSuite) TestTokensOnlyNamespaces() { } // Add the new namespace - data1 := readConfig(suite.T(), suite.configFile1) - addNamespace(data1, namespaceInfo) - writeConfig(suite.T(), suite.configFile1, data1) + data1 := e2e.ReadConfig(suite.T(), suite.configFile1) + e2e.AddNamespace(data1, namespaceInfo) + e2e.WriteConfig(suite.T(), suite.configFile1, data1) admin1 := client.NewResty(suite.T()) admin1.SetBaseURL(suite.adminHost1 + "/spi/v1") - resetFireFly(suite.T(), admin1) + e2e.ResetFireFly(suite.T(), admin1) e2e.PollForUp(suite.T(), suite.testState.client1) client1 := client.NewFireFly(suite.T(), suite.testState.client1.Hostname, testNamespace) @@ -102,7 +102,7 @@ func (suite *TokensOnlyTestSuite) TestTokensOnlyNamespaces() { received1 := e2e.WsReader(client1.WebSocket(suite.T(), queryString, nil)) // Attempt async token operations on new namespace - poolName := fmt.Sprintf("pool_%s", randomName(suite.T())) + poolName := fmt.Sprintf("pool_%s", e2e.RandomName(suite.T())) suite.T().Logf("Pool name: %s", poolName) pool := &core.TokenPool{ diff --git a/test/e2e/multiparty/common.go b/test/e2e/multiparty/common.go index d1197a71aa..c890cb28c1 100644 --- a/test/e2e/multiparty/common.go +++ b/test/e2e/multiparty/common.go @@ -18,26 +18,21 @@ package multiparty import ( "context" - "crypto/rand" "crypto/sha256" "encoding/base64" "fmt" - "io/ioutil" "net/http" "os" "path/filepath" "testing" "time" - "github.com/go-resty/resty/v2" "github.com/gorilla/websocket" "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/pkg/core" "github.com/hyperledger/firefly/test/e2e" "github.com/hyperledger/firefly/test/e2e/client" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "gopkg.in/yaml.v2" ) const ( @@ -256,43 +251,3 @@ func validateReceivedMessages(ts *testState, client *client.FireFlyClient, topic // Flip data (returned in most recent order) into delivery order return returnData } - -func randomName(t *testing.T) string { - b := make([]byte, 5) - _, err := rand.Read(b) - assert.NoError(t, err) - return fmt.Sprintf("e2e_%x", b) -} - -func readConfig(t *testing.T, configFile string) map[string]interface{} { - yfile, err := ioutil.ReadFile(configFile) - assert.NoError(t, err) - data := make(map[string]interface{}) - err = yaml.Unmarshal(yfile, &data) - assert.NoError(t, err) - return data -} - -func writeConfig(t *testing.T, configFile string, data map[string]interface{}) { - out, err := yaml.Marshal(data) - assert.NoError(t, err) - f, err := os.Create(configFile) - assert.NoError(t, err) - _, err = f.Write(out) - assert.NoError(t, err) - f.Close() -} - -func addNamespace(data map[string]interface{}, ns map[string]interface{}) { - namespaces := data["namespaces"].(map[interface{}]interface{}) - predefined := namespaces["predefined"].([]interface{}) - namespaces["predefined"] = append(predefined, ns) -} - -func resetFireFly(t *testing.T, client *resty.Client) { - resp, err := client.R(). - SetBody(map[string]interface{}{}). - Post("/reset") - require.NoError(t, err) - assert.Equal(t, 204, resp.StatusCode()) -} diff --git a/test/e2e/multiparty/contract_migration.go b/test/e2e/multiparty/contract_migration.go index d9d1ac1140..3205f768d1 100644 --- a/test/e2e/multiparty/contract_migration.go +++ b/test/e2e/multiparty/contract_migration.go @@ -55,7 +55,7 @@ func (suite *ContractMigrationTestSuite) TestContractMigration() { } func runMigrationTest(suite *ContractMigrationTestSuite, address1, address2 string, startOnV1 bool) { - testNamespace := randomName(suite.T()) + testNamespace := e2e.RandomName(suite.T()) suite.T().Logf("Test namespace: %s", testNamespace) org := map[string]interface{}{} @@ -77,17 +77,17 @@ func runMigrationTest(suite *ContractMigrationTestSuite, address1, address2 stri data := &core.DataRefOrValue{Value: fftypes.JSONAnyPtr(`"test"`)} // Add the new namespace to both config files - data1 := readConfig(suite.T(), suite.testState.configFile1) + data1 := e2e.ReadConfig(suite.T(), suite.testState.configFile1) org["name"] = suite.testState.org1.Name org["key"] = suite.testState.org1key.Value - addNamespace(data1, namespaceInfo) - writeConfig(suite.T(), suite.testState.configFile1, data1) + e2e.AddNamespace(data1, namespaceInfo) + e2e.WriteConfig(suite.T(), suite.testState.configFile1, data1) - data2 := readConfig(suite.T(), suite.testState.configFile2) + data2 := e2e.ReadConfig(suite.T(), suite.testState.configFile2) org["name"] = suite.testState.org2.Name org["key"] = suite.testState.org2key.Value - addNamespace(data2, namespaceInfo) - writeConfig(suite.T(), suite.testState.configFile2, data2) + e2e.AddNamespace(data2, namespaceInfo) + e2e.WriteConfig(suite.T(), suite.testState.configFile2, data2) admin1 := client.NewResty(suite.T()) admin2 := client.NewResty(suite.T()) @@ -95,8 +95,8 @@ func runMigrationTest(suite *ContractMigrationTestSuite, address1, address2 stri admin2.SetBaseURL(suite.testState.adminHost2 + "/spi/v1") // Reset both nodes to pick up the new namespace - resetFireFly(suite.T(), admin1) - resetFireFly(suite.T(), admin2) + e2e.ResetFireFly(suite.T(), admin1) + e2e.ResetFireFly(suite.T(), admin2) e2e.PollForUp(suite.T(), suite.testState.client1) e2e.PollForUp(suite.T(), suite.testState.client2) diff --git a/test/e2e/multiparty/namespace_alias.go b/test/e2e/multiparty/namespace_alias.go index 7ba36a7fcc..c203221e27 100644 --- a/test/e2e/multiparty/namespace_alias.go +++ b/test/e2e/multiparty/namespace_alias.go @@ -49,9 +49,9 @@ func (suite *NamespaceAliasSuite) TestNamespaceMapping() { defer suite.testState.Done() address := deployContract(suite.T(), suite.testState.stackName, "firefly/Firefly.json") - localNamespace1 := randomName(suite.T()) - localNamespace2 := randomName(suite.T()) - remoteNamespace := randomName(suite.T()) + localNamespace1 := e2e.RandomName(suite.T()) + localNamespace2 := e2e.RandomName(suite.T()) + remoteNamespace := e2e.RandomName(suite.T()) suite.T().Logf("Test namespace: local1=%s, local2=%s, remote=%s", localNamespace1, localNamespace2, remoteNamespace) org := map[string]interface{}{} @@ -70,19 +70,19 @@ func (suite *NamespaceAliasSuite) TestNamespaceMapping() { data := &core.DataRefOrValue{Value: fftypes.JSONAnyPtr(`"test"`)} // Add the new namespace to both config files - data1 := readConfig(suite.T(), suite.testState.configFile1) + data1 := e2e.ReadConfig(suite.T(), suite.testState.configFile1) namespaceInfo["name"] = localNamespace1 org["name"] = suite.testState.org1.Name org["key"] = suite.testState.org1key.Value - addNamespace(data1, namespaceInfo) - writeConfig(suite.T(), suite.testState.configFile1, data1) + e2e.AddNamespace(data1, namespaceInfo) + e2e.WriteConfig(suite.T(), suite.testState.configFile1, data1) - data2 := readConfig(suite.T(), suite.testState.configFile2) + data2 := e2e.ReadConfig(suite.T(), suite.testState.configFile2) namespaceInfo["name"] = localNamespace2 org["name"] = suite.testState.org2.Name org["key"] = suite.testState.org2key.Value - addNamespace(data2, namespaceInfo) - writeConfig(suite.T(), suite.testState.configFile2, data2) + e2e.AddNamespace(data2, namespaceInfo) + e2e.WriteConfig(suite.T(), suite.testState.configFile2, data2) admin1 := client.NewResty(suite.T()) admin2 := client.NewResty(suite.T()) @@ -90,8 +90,8 @@ func (suite *NamespaceAliasSuite) TestNamespaceMapping() { admin2.SetBaseURL(suite.testState.adminHost2 + "/spi/v1") // Reset both nodes to pick up the new namespace - resetFireFly(suite.T(), admin1) - resetFireFly(suite.T(), admin2) + e2e.ResetFireFly(suite.T(), admin1) + e2e.ResetFireFly(suite.T(), admin2) e2e.PollForUp(suite.T(), suite.testState.client1) e2e.PollForUp(suite.T(), suite.testState.client2) diff --git a/test/e2e/multiparty/tokens.go b/test/e2e/multiparty/tokens.go index af02d12f22..e0d4e9ba43 100644 --- a/test/e2e/multiparty/tokens.go +++ b/test/e2e/multiparty/tokens.go @@ -53,7 +53,7 @@ func (suite *TokensTestSuite) TestE2EFungibleTokensAsync() { received1 := e2e.WsReader(suite.testState.ws1) received2 := e2e.WsReader(suite.testState.ws2) - poolName := fmt.Sprintf("pool_%s", randomName(suite.T())) + poolName := fmt.Sprintf("pool_%s", e2e.RandomName(suite.T())) suite.T().Logf("Pool name: %s", poolName) pool := &core.TokenPool{ @@ -219,7 +219,7 @@ func (suite *TokensTestSuite) TestE2ENonFungibleTokensSync() { received1 := e2e.WsReader(suite.testState.ws1) received2 := e2e.WsReader(suite.testState.ws2) - poolName := fmt.Sprintf("pool_%s", randomName(suite.T())) + poolName := fmt.Sprintf("pool_%s", e2e.RandomName(suite.T())) suite.T().Logf("Pool name: %s", poolName) pool := &core.TokenPool{ From 39a866272ff85cb4b98f3de1a8efe5af66b83274 Mon Sep 17 00:00:00 2001 From: Alex Shorsher Date: Tue, 2 Aug 2022 18:13:09 -0400 Subject: [PATCH 4/7] update docs Signed-off-by: Alex Shorsher --- docs/reference/config.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/config.md b/docs/reference/config.md index 8d2f815374..2916da184a 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -30,7 +30,7 @@ nav_order: 2 |Key|Description|Type|Default Value| |---|-----------|----|-------------| -|keynormalization|Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization|`string`|`` +|keynormalization|Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization (deprecated - namespace.predefined[].assets.manager.keynormalization)|`string`|`` ## batch.cache From c5e24a17db04294257846a34f7c0d7096074d04f Mon Sep 17 00:00:00 2001 From: Alex Shorsher Date: Tue, 2 Aug 2022 20:16:59 -0400 Subject: [PATCH 5/7] update namespace assets key to match global key Signed-off-by: Alex Shorsher --- docs/reference/config.md | 4 ++-- internal/coreconfig/coreconfig.go | 2 +- internal/coremsgs/en_config_descriptions.go | 4 ++-- internal/identity/identitymanager.go | 2 +- test/e2e/gateway/tokens_only.go | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/reference/config.md b/docs/reference/config.md index 2916da184a..a6ecfbbf64 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -30,7 +30,7 @@ nav_order: 2 |Key|Description|Type|Default Value| |---|-----------|----|-------------| -|keynormalization|Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization (deprecated - namespace.predefined[].assets.manager.keynormalization)|`string`|`` +|keynormalization|Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization (deprecated - namespace.predefined[].asset.manager.keynormalization)|`string`|`` ## batch.cache @@ -622,7 +622,7 @@ nav_order: 2 |plugins|The list of plugins for this namespace|`string`|`` |remotename|The namespace name to be sent in plugin calls, if it differs from namespace name|`string`|`` -## namespaces.predefined[].assets.manager +## namespaces.predefined[].asset.manager |Key|Description|Type|Default Value| |---|-----------|----|-------------| diff --git a/internal/coreconfig/coreconfig.go b/internal/coreconfig/coreconfig.go index e600a81fd8..e3b3498fd8 100644 --- a/internal/coreconfig/coreconfig.go +++ b/internal/coreconfig/coreconfig.go @@ -42,7 +42,7 @@ const ( // NamespaceDefaultKey is the default signing key for blockchain transactions within this namespace NamespaceDefaultKey = "defaultkey" // NamespaceAssetKeyNormalization mechanism to normalize keys before using them. Valid options: "blockchain_plugin" - use blockchain plugin (default), "none" - do not attempt normalization - NamespaceAssetKeyNormalization = "assets.manager.keynormalization" + NamespaceAssetKeyNormalization = "asset.manager.keynormalization" // NamespaceMultiparty contains the multiparty configuration for a namespace NamespaceMultiparty = "multiparty" // NamespaceMultipartyEnabled specifies if multi-party mode is enabled for a namespace diff --git a/internal/coremsgs/en_config_descriptions.go b/internal/coremsgs/en_config_descriptions.go index 915edb74ba..b6fd66457b 100644 --- a/internal/coremsgs/en_config_descriptions.go +++ b/internal/coremsgs/en_config_descriptions.go @@ -41,7 +41,7 @@ var ( ConfigAPIDefaultFilterLimit = ffc("config.api.defaultFilterLimit", "The maximum number of rows to return if no limit is specified on an API request", i18n.IntType) ConfigAPIMaxFilterLimit = ffc("config.api.maxFilterLimit", "The largest value of `limit` that an HTTP client can specify in a request", i18n.IntType) ConfigAPIRequestMaxTimeout = ffc("config.api.requestMaxTimeout", "The maximum amount of time that an HTTP client can specify in a `Request-Timeout` header to keep a specific request open", i18n.TimeDurationType) - ConfigAssetManagerKeyNormalization = ffc("config.asset.manager.keynormalization", "Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization (deprecated - namespace.predefined[].assets.manager.keynormalization)", i18n.StringType) + ConfigAssetManagerKeyNormalization = ffc("config.asset.manager.keynormalization", "Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization (deprecated - namespace.predefined[].asset.manager.keynormalization)", i18n.StringType) ConfigBatchManagerMinimumPollDelay = ffc("config.batch.manager.minimumPollDelay", "The minimum time the batch manager waits between polls on the DB - to prevent thrashing", i18n.TimeDurationType) ConfigBatchManagerPollTimeout = ffc("config.batch.manager.pollTimeout", "How long to wait without any notifications of new messages before doing a page query", i18n.TimeDurationType) @@ -257,7 +257,7 @@ var ( ConfigNamespacesPredefinedPlugins = ffc("config.namespaces.predefined[].plugins", "The list of plugins for this namespace", i18n.StringType) ConfigNamespacesPredefinedRemoteName = ffc("config.namespaces.predefined[].remotename", "The namespace name to be sent in plugin calls, if it differs from namespace name", i18n.StringType) ConfigNamespacesPredefinedDefaultKey = ffc("config.namespaces.predefined[].defaultkey", "A default signing key for blockchain transactions within this namespace", i18n.StringType) - ConfigNamespacesPredefinedKeyNormalization = ffc("config.namespaces.predefined[].assets.manager.keynormalization", "Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization", i18n.StringType) + ConfigNamespacesPredefinedKeyNormalization = ffc("config.namespaces.predefined[].asset.manager.keynormalization", "Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization", i18n.StringType) ConfigNamespacesMultipartyEnabled = ffc("config.namespaces.predefined[].multiparty.enabled", "Enables multi-party mode for this namespace (defaults to true if an org name or key is configured, either here or at the root level)", i18n.BooleanType) ConfigNamespacesMultipartyOrgName = ffc("config.namespaces.predefined[].multiparty.org.name", "A short name for the local root organization within this namespace", i18n.StringType) ConfigNamespacesMultipartyOrgDesc = ffc("config.namespaces.predefined[].multiparty.org.description", "A description for the local root organization within this namespace", i18n.StringType) diff --git a/internal/identity/identitymanager.go b/internal/identity/identitymanager.go index 38dd733189..bf6a5e62a2 100644 --- a/internal/identity/identitymanager.go +++ b/internal/identity/identitymanager.go @@ -135,7 +135,7 @@ func (im *identityManager) NormalizeSigningKey(ctx context.Context, inputKey str } // If the caller is not confident that the blockchain plugin/connector should be used to resolve, // for example it might be a different blockchain (Eth vs Fabric etc.), or it has its own - // verification/management of keys, it should set `assets.keyNormalization: "none"` in the config. + // verification/management of keys, it should set `namespace.predefined[].asset.manager.keynormalization: "none"` in the config. if keyNormalizationMode != KeyNormalizationBlockchainPlugin { return inputKey, nil } diff --git a/test/e2e/gateway/tokens_only.go b/test/e2e/gateway/tokens_only.go index a5ed4f388b..bab22f8f78 100644 --- a/test/e2e/gateway/tokens_only.go +++ b/test/e2e/gateway/tokens_only.go @@ -77,7 +77,7 @@ func (suite *TokensOnlyTestSuite) TestTokensOnlyNamespaces() { namespaceInfo := map[string]interface{}{ "name": testNamespace, - "assets": map[string]interface{}{ + "asset": map[string]interface{}{ "manager": map[string]interface{}{ "keynormalization": "none", }, From dbca11b881fbc0834e69549f1ba81cd06d38f0e0 Mon Sep 17 00:00:00 2001 From: Alex Shorsher Date: Tue, 2 Aug 2022 22:20:38 -0400 Subject: [PATCH 6/7] add additional gateway `testState` functionality Signed-off-by: Alex Shorsher --- test/e2e/gateway/common.go | 17 +++++++++++++++-- test/e2e/gateway/tokens_only.go | 30 +++++++----------------------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/test/e2e/gateway/common.go b/test/e2e/gateway/common.go index d59f79a27a..9b707a2887 100644 --- a/test/e2e/gateway/common.go +++ b/test/e2e/gateway/common.go @@ -21,6 +21,7 @@ import ( "fmt" "net/http" "os" + "path/filepath" "testing" "time" @@ -42,6 +43,9 @@ type testState struct { client1 *client.FireFlyClient unregisteredAccounts []interface{} namespace string + stackName string + adminHost1 string + configFile1 string } func (m *testState) T() *testing.T { @@ -57,6 +61,10 @@ func (m *testState) Done() func() { } func beforeE2ETest(t *testing.T) *testState { + stackDir := os.Getenv("STACK_DIR") + if stackDir == "" { + t.Fatal("STACK_DIR must be set") + } stack := e2e.ReadStack(t) stackState := e2e.ReadStackState(t) @@ -72,7 +80,9 @@ func beforeE2ETest(t *testing.T) *testState { member0WithPort = fmt.Sprintf(":%d", stack.Members[0].ExposedFireflyPort) } - baseURL := fmt.Sprintf("%s://%s%s", httpProtocolClient1, stack.Members[0].FireflyHostname, member0WithPort) + base1 := fmt.Sprintf("%s://%s%s", httpProtocolClient1, stack.Members[0].FireflyHostname, member0WithPort) + admin1 := fmt.Sprintf("%s://%s:%d", httpProtocolClient1, stack.Members[0].FireflyHostname, stack.Members[0].ExposedAdminPort) + namespace := os.Getenv("NAMESPACE") if namespace == "" { namespace = "default" @@ -80,10 +90,13 @@ func beforeE2ETest(t *testing.T) *testState { ts := &testState{ t: t, + stackName: stack.Name, startTime: time.Now(), - client1: client.NewFireFly(t, baseURL, namespace), + client1: client.NewFireFly(t, base1, namespace), unregisteredAccounts: stackState.Accounts[2:], namespace: namespace, + adminHost1: admin1, + configFile1: filepath.Join(stackDir, "runtime", "config", "firefly_core_0.yml"), } t.Logf("Blockchain provider: %s", stack.BlockchainProvider) diff --git a/test/e2e/gateway/tokens_only.go b/test/e2e/gateway/tokens_only.go index bab22f8f78..3b49060ad0 100644 --- a/test/e2e/gateway/tokens_only.go +++ b/test/e2e/gateway/tokens_only.go @@ -18,8 +18,6 @@ package gateway import ( "fmt" - "os" - "path/filepath" "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/pkg/core" @@ -31,12 +29,10 @@ import ( type TokensOnlyTestSuite struct { suite.Suite - testState *testState - connector string - db string - key string - adminHost1 string - configFile1 string + testState *testState + connector string + db string + key string } func (suite *TokensOnlyTestSuite) SetupSuite() { @@ -44,18 +40,6 @@ func (suite *TokensOnlyTestSuite) SetupSuite() { stack := e2e.ReadStack(suite.T()) stackState := e2e.ReadStackState(suite.T()) - adminProtocol1 := schemeHTTP - if stack.Members[0].UseHTTPS { - adminProtocol1 = schemeHTTPS - } - suite.adminHost1 = fmt.Sprintf("%s://%s:%d", adminProtocol1, stack.Members[0].FireflyHostname, stack.Members[0].ExposedAdminPort) - - stackDir := os.Getenv("STACK_DIR") - if stackDir == "" { - suite.T().Fatal("STACK_DIR must be set") - } - suite.configFile1 = filepath.Join(stackDir, "runtime", "config", "firefly_core_0.yml") - suite.connector = stack.TokenProviders[0] suite.db = stack.Database account := stackState.Accounts[0].(map[string]interface{}) @@ -86,12 +70,12 @@ func (suite *TokensOnlyTestSuite) TestTokensOnlyNamespaces() { } // Add the new namespace - data1 := e2e.ReadConfig(suite.T(), suite.configFile1) + data1 := e2e.ReadConfig(suite.T(), suite.testState.configFile1) e2e.AddNamespace(data1, namespaceInfo) - e2e.WriteConfig(suite.T(), suite.configFile1, data1) + e2e.WriteConfig(suite.T(), suite.testState.configFile1, data1) admin1 := client.NewResty(suite.T()) - admin1.SetBaseURL(suite.adminHost1 + "/spi/v1") + admin1.SetBaseURL(suite.testState.adminHost1 + "/spi/v1") e2e.ResetFireFly(suite.T(), admin1) e2e.PollForUp(suite.T(), suite.testState.client1) From 7c839e111727446b45240d155aefecddccbc3453 Mon Sep 17 00:00:00 2001 From: Alex Shorsher Date: Wed, 3 Aug 2022 22:02:09 -0400 Subject: [PATCH 7/7] update docs to use correct `namespaces` config - updating all references of `namespace` to now be `namespaces` Signed-off-by: Alex Shorsher --- docs/reference/config.md | 10 +++++----- internal/coremsgs/en_config_descriptions.go | 10 +++++----- internal/identity/identitymanager.go | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/reference/config.md b/docs/reference/config.md index a6ecfbbf64..72c3881279 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -30,7 +30,7 @@ nav_order: 2 |Key|Description|Type|Default Value| |---|-----------|----|-------------| -|keynormalization|Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization (deprecated - namespace.predefined[].asset.manager.keynormalization)|`string`|`` +|keynormalization|Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization (deprecated - use namespaces.predefined[].asset.manager.keynormalization)|`string`|`` ## batch.cache @@ -132,10 +132,10 @@ nav_order: 2 |batchTimeout|How long Ethconnect should wait for new events to arrive and fill a batch, before sending the batch to FireFly core. Only applies when automatically creating a new event stream|[`time.Duration`](https://pkg.go.dev/time#Duration)|`500` |connectionTimeout|The maximum amount of time that a connection is allowed to remain with no data transmitted|[`time.Duration`](https://pkg.go.dev/time#Duration)|`30s` |expectContinueTimeout|See [ExpectContinueTimeout in the Go docs](https://pkg.go.dev/net/http#Transport)|[`time.Duration`](https://pkg.go.dev/time#Duration)|`1s` -|fromBlock|The first event this FireFly instance should listen to from the BatchPin smart contract. Default=0. Only affects initial creation of the event stream (deprecated - use namespace.predefined[].multiparty.contract[].location.firstEvent)|Address `string`|`0` +|fromBlock|The first event this FireFly instance should listen to from the BatchPin smart contract. Default=0. Only affects initial creation of the event stream (deprecated - use namespaces.predefined[].multiparty.contract[].location.firstEvent)|Address `string`|`0` |headers|Adds custom headers to HTTP requests|`map[string]string`|`` |idleTimeout|The max duration to hold a HTTP keepalive connection between calls|[`time.Duration`](https://pkg.go.dev/time#Duration)|`475ms` -|instance|The Ethereum address of the FireFly BatchPin smart contract that has been deployed to the blockchain (deprecated - use namespace.predefined[].multiparty.contract[].location.address)|Address `string`|`` +|instance|The Ethereum address of the FireFly BatchPin smart contract that has been deployed to the blockchain (deprecated - use namespaces.predefined[].multiparty.contract[].location.address)|Address `string`|`` |maxIdleConns|The max number of idle connections to hold pooled|`int`|`100` |prefixLong|The prefix that will be used for Ethconnect specific HTTP headers when FireFly makes requests to Ethconnect|`string`|`firefly` |prefixShort|The prefix that will be used for Ethconnect specific query parameters when FireFly makes requests to Ethconnect|`string`|`fly` @@ -217,8 +217,8 @@ nav_order: 2 |---|-----------|----|-------------| |batchSize|The number of events Fabconnect should batch together for delivery to FireFly core. Only applies when automatically creating a new event stream|`int`|`50` |batchTimeout|The maximum amount of time to wait for a batch to complete|[`time.Duration`](https://pkg.go.dev/time#Duration)|`500` -|chaincode|The name of the Fabric chaincode that FireFly will use for BatchPin transactions (deprecated - use namespace.predefined[].multiparty.contract[].location.chaincode)|`string`|`` -|channel|The Fabric channel that FireFly will use for BatchPin transactions (deprecated - use namespace.predefined[].multiparty.contract[].location.channel)|`string`|`` +|chaincode|The name of the Fabric chaincode that FireFly will use for BatchPin transactions (deprecated - use namespaces.predefined[].multiparty.contract[].location.chaincode)|`string`|`` +|channel|The Fabric channel that FireFly will use for BatchPin transactions (deprecated - use namespaces.predefined[].multiparty.contract[].location.channel)|`string`|`` |connectionTimeout|The maximum amount of time that a connection is allowed to remain with no data transmitted|[`time.Duration`](https://pkg.go.dev/time#Duration)|`30s` |expectContinueTimeout|See [ExpectContinueTimeout in the Go docs](https://pkg.go.dev/net/http#Transport)|[`time.Duration`](https://pkg.go.dev/time#Duration)|`1s` |headers|Adds custom headers to HTTP requests|`map[string]string`|`` diff --git a/internal/coremsgs/en_config_descriptions.go b/internal/coremsgs/en_config_descriptions.go index b6fd66457b..c9c062fbdf 100644 --- a/internal/coremsgs/en_config_descriptions.go +++ b/internal/coremsgs/en_config_descriptions.go @@ -41,7 +41,7 @@ var ( ConfigAPIDefaultFilterLimit = ffc("config.api.defaultFilterLimit", "The maximum number of rows to return if no limit is specified on an API request", i18n.IntType) ConfigAPIMaxFilterLimit = ffc("config.api.maxFilterLimit", "The largest value of `limit` that an HTTP client can specify in a request", i18n.IntType) ConfigAPIRequestMaxTimeout = ffc("config.api.requestMaxTimeout", "The maximum amount of time that an HTTP client can specify in a `Request-Timeout` header to keep a specific request open", i18n.TimeDurationType) - ConfigAssetManagerKeyNormalization = ffc("config.asset.manager.keynormalization", "Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization (deprecated - namespace.predefined[].asset.manager.keynormalization)", i18n.StringType) + ConfigAssetManagerKeyNormalization = ffc("config.asset.manager.keynormalization", "Mechanism to normalize keys before using them. Valid options are `blockchain_plugin` - use blockchain plugin (default) or `none` - do not attempt normalization (deprecated - use namespaces.predefined[].asset.manager.keynormalization)", i18n.StringType) ConfigBatchManagerMinimumPollDelay = ffc("config.batch.manager.minimumPollDelay", "The minimum time the batch manager waits between polls on the DB - to prevent thrashing", i18n.TimeDurationType) ConfigBatchManagerPollTimeout = ffc("config.batch.manager.pollTimeout", "How long to wait without any notifications of new messages before doing a page query", i18n.TimeDurationType) @@ -70,8 +70,8 @@ var ( ConfigBlockchainEthereumEthconnectBatchSize = ffc("config.blockchain.ethereum.ethconnect.batchSize", "The number of events Ethconnect should batch together for delivery to FireFly core. Only applies when automatically creating a new event stream", i18n.IntType) ConfigBlockchainEthereumEthconnectBatchTimeout = ffc("config.blockchain.ethereum.ethconnect.batchTimeout", "How long Ethconnect should wait for new events to arrive and fill a batch, before sending the batch to FireFly core. Only applies when automatically creating a new event stream", i18n.TimeDurationType) - ConfigBlockchainEthereumEthconnectInstance = ffc("config.blockchain.ethereum.ethconnect.instance", "The Ethereum address of the FireFly BatchPin smart contract that has been deployed to the blockchain (deprecated - use namespace.predefined[].multiparty.contract[].location.address)", "Address "+i18n.StringType) - ConfigBlockchainEthereumEthconnectFromBlock = ffc("config.blockchain.ethereum.ethconnect.fromBlock", "The first event this FireFly instance should listen to from the BatchPin smart contract. Default=0. Only affects initial creation of the event stream (deprecated - use namespace.predefined[].multiparty.contract[].location.firstEvent)", "Address "+i18n.StringType) + ConfigBlockchainEthereumEthconnectInstance = ffc("config.blockchain.ethereum.ethconnect.instance", "The Ethereum address of the FireFly BatchPin smart contract that has been deployed to the blockchain (deprecated - use namespaces.predefined[].multiparty.contract[].location.address)", "Address "+i18n.StringType) + ConfigBlockchainEthereumEthconnectFromBlock = ffc("config.blockchain.ethereum.ethconnect.fromBlock", "The first event this FireFly instance should listen to from the BatchPin smart contract. Default=0. Only affects initial creation of the event stream (deprecated - use namespaces.predefined[].multiparty.contract[].location.firstEvent)", "Address "+i18n.StringType) ConfigBlockchainEthereumEthconnectPrefixLong = ffc("config.blockchain.ethereum.ethconnect.prefixLong", "The prefix that will be used for Ethconnect specific HTTP headers when FireFly makes requests to Ethconnect", i18n.StringType) ConfigBlockchainEthereumEthconnectPrefixShort = ffc("config.blockchain.ethereum.ethconnect.prefixShort", "The prefix that will be used for Ethconnect specific query parameters when FireFly makes requests to Ethconnect", i18n.StringType) ConfigBlockchainEthereumEthconnectTopic = ffc("config.blockchain.ethereum.ethconnect.topic", "The websocket listen topic that the node should register on, which is important if there are multiple nodes using a single ethconnect", i18n.StringType) @@ -83,8 +83,8 @@ var ( ConfigBlockchainFabricFabconnectBatchSize = ffc("config.blockchain.fabric.fabconnect.batchSize", "The number of events Fabconnect should batch together for delivery to FireFly core. Only applies when automatically creating a new event stream", i18n.IntType) ConfigBlockchainFabricFabconnectBatchTimeout = ffc("config.blockchain.fabric.fabconnect.batchTimeout", "The maximum amount of time to wait for a batch to complete", i18n.TimeDurationType) - ConfigBlockchainFabricFabconnectChaincode = ffc("config.blockchain.fabric.fabconnect.chaincode", "The name of the Fabric chaincode that FireFly will use for BatchPin transactions (deprecated - use namespace.predefined[].multiparty.contract[].location.chaincode)", i18n.StringType) - ConfigBlockchainFabricFabconnectChannel = ffc("config.blockchain.fabric.fabconnect.channel", "The Fabric channel that FireFly will use for BatchPin transactions (deprecated - use namespace.predefined[].multiparty.contract[].location.channel)", i18n.StringType) + ConfigBlockchainFabricFabconnectChaincode = ffc("config.blockchain.fabric.fabconnect.chaincode", "The name of the Fabric chaincode that FireFly will use for BatchPin transactions (deprecated - use namespaces.predefined[].multiparty.contract[].location.chaincode)", i18n.StringType) + ConfigBlockchainFabricFabconnectChannel = ffc("config.blockchain.fabric.fabconnect.channel", "The Fabric channel that FireFly will use for BatchPin transactions (deprecated - use namespaces.predefined[].multiparty.contract[].location.channel)", i18n.StringType) ConfigBlockchainFabricFabconnectPrefixLong = ffc("config.blockchain.fabric.fabconnect.prefixLong", "The prefix that will be used for Fabconnect specific HTTP headers when FireFly makes requests to Fabconnect", i18n.StringType) ConfigBlockchainFabricFabconnectPrefixShort = ffc("config.blockchain.fabric.fabconnect.prefixShort", "The prefix that will be used for Fabconnect specific query parameters when FireFly makes requests to Fabconnect", i18n.StringType) ConfigBlockchainFabricFabconnectSigner = ffc("config.blockchain.fabric.fabconnect.signer", "The Fabric signing key to use when submitting transactions to Fabconnect", i18n.StringType) diff --git a/internal/identity/identitymanager.go b/internal/identity/identitymanager.go index bf6a5e62a2..5c862b1083 100644 --- a/internal/identity/identitymanager.go +++ b/internal/identity/identitymanager.go @@ -135,7 +135,7 @@ func (im *identityManager) NormalizeSigningKey(ctx context.Context, inputKey str } // If the caller is not confident that the blockchain plugin/connector should be used to resolve, // for example it might be a different blockchain (Eth vs Fabric etc.), or it has its own - // verification/management of keys, it should set `namespace.predefined[].asset.manager.keynormalization: "none"` in the config. + // verification/management of keys, it should set `namespaces.predefined[].asset.manager.keynormalization: "none"` in the config. if keyNormalizationMode != KeyNormalizationBlockchainPlugin { return inputKey, nil }