From 999cc616c2ef6c618dfbe0685452864a387e5264 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Tue, 3 May 2022 17:05:49 -0400 Subject: [PATCH 01/27] Split definition methods out of Broadcast Manager into new Definition Sender Signed-off-by: Andrew Richardson --- Makefile | 1 + internal/apiserver/route_post_new_datatype.go | 2 +- .../apiserver/route_post_new_datatype_test.go | 14 +- internal/broadcast/definition_test.go | 115 -------------- internal/broadcast/manager.go | 5 - internal/broadcast/message_test.go | 31 ++++ internal/contracts/manager.go | 14 +- internal/contracts/manager_test.go | 56 +++---- internal/{broadcast => defsender}/datatype.go | 4 +- .../{broadcast => defsender}/datatype_test.go | 65 +++----- .../definition.go => defsender/sender.go} | 98 +++++++----- internal/defsender/sender_test.go | 149 ++++++++++++++++++ .../{broadcast => defsender}/tokenpool.go | 4 +- .../tokenpool_test.go | 57 ++----- internal/events/event_manager.go | 11 +- internal/events/event_manager_test.go | 9 +- internal/events/token_pool_created.go | 2 +- internal/events/token_pool_created_test.go | 8 +- internal/networkmap/manager.go | 10 +- internal/networkmap/manager_test.go | 6 +- internal/networkmap/register_identity.go | 4 +- internal/networkmap/register_identity_test.go | 32 ++-- internal/networkmap/register_node_test.go | 8 +- internal/networkmap/register_org_test.go | 8 +- internal/networkmap/update_identity.go | 2 +- internal/networkmap/update_identity_test.go | 14 +- internal/orchestrator/orchestrator.go | 68 ++++++-- internal/orchestrator/orchestrator_test.go | 18 ++- mocks/broadcastmocks/manager.go | 115 -------------- mocks/defsendermocks/sender.go | 145 +++++++++++++++++ mocks/orchestratormocks/orchestrator.go | 18 +++ 31 files changed, 615 insertions(+), 478 deletions(-) delete mode 100644 internal/broadcast/definition_test.go rename internal/{broadcast => defsender}/datatype.go (94%) rename internal/{broadcast => defsender}/datatype_test.go (57%) rename internal/{broadcast/definition.go => defsender/sender.go} (53%) create mode 100644 internal/defsender/sender_test.go rename internal/{broadcast => defsender}/tokenpool.go (92%) rename internal/{broadcast => defsender}/tokenpool_test.go (57%) create mode 100644 mocks/defsendermocks/sender.go diff --git a/Makefile b/Makefile index cce56c32e..ba33e7093 100644 --- a/Makefile +++ b/Makefile @@ -63,6 +63,7 @@ $(eval $(call makemock, internal/privatemessaging, Manager, privateme $(eval $(call makemock, internal/shareddownload, Manager, shareddownloadmocks)) $(eval $(call makemock, internal/shareddownload, Callbacks, shareddownloadmocks)) $(eval $(call makemock, internal/definitions, DefinitionHandler, definitionsmocks)) +$(eval $(call makemock, internal/defsender, Sender, defsendermocks)) $(eval $(call makemock, internal/events, EventManager, eventmocks)) $(eval $(call makemock, internal/namespace, Manager, namespacemocks)) $(eval $(call makemock, internal/networkmap, Manager, networkmapmocks)) diff --git a/internal/apiserver/route_post_new_datatype.go b/internal/apiserver/route_post_new_datatype.go index 53e591247..2e0cbd0ee 100644 --- a/internal/apiserver/route_post_new_datatype.go +++ b/internal/apiserver/route_post_new_datatype.go @@ -41,7 +41,7 @@ var postNewDatatype = &ffapi.Route{ CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) - _, err = cr.or.Broadcast().BroadcastDatatype(cr.ctx, r.Input.(*core.Datatype), waitConfirm) + _, err = cr.or.DefinitionSender().BroadcastDatatype(cr.ctx, r.Input.(*core.Datatype), waitConfirm) return r.Input, err }, }, diff --git a/internal/apiserver/route_post_new_datatype_test.go b/internal/apiserver/route_post_new_datatype_test.go index c047b42bc..616121b4f 100644 --- a/internal/apiserver/route_post_new_datatype_test.go +++ b/internal/apiserver/route_post_new_datatype_test.go @@ -22,7 +22,7 @@ import ( "net/http/httptest" "testing" - "github.com/hyperledger/firefly/mocks/broadcastmocks" + "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -30,8 +30,8 @@ import ( func TestPostNewDatatypes(t *testing.T) { o, r := newTestAPIServer() - mbm := &broadcastmocks.Manager{} - o.On("Broadcast").Return(mbm) + mds := &defsendermocks.Sender{} + o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) @@ -39,7 +39,7 @@ func TestPostNewDatatypes(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mbm.On("BroadcastDatatype", mock.Anything, mock.AnythingOfType("*core.Datatype"), false). + mds.On("BroadcastDatatype", mock.Anything, mock.AnythingOfType("*core.Datatype"), false). Return(&core.Message{}, nil) r.ServeHTTP(res, req) @@ -48,8 +48,8 @@ func TestPostNewDatatypes(t *testing.T) { func TestPostNewDatatypesSync(t *testing.T) { o, r := newTestAPIServer() - mbm := &broadcastmocks.Manager{} - o.On("Broadcast").Return(mbm) + mds := &defsendermocks.Sender{} + o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) @@ -57,7 +57,7 @@ func TestPostNewDatatypesSync(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mbm.On("BroadcastDatatype", mock.Anything, mock.AnythingOfType("*core.Datatype"), true). + mds.On("BroadcastDatatype", mock.Anything, mock.AnythingOfType("*core.Datatype"), true). Return(&core.Message{}, nil) r.ServeHTTP(res, req) diff --git a/internal/broadcast/definition_test.go b/internal/broadcast/definition_test.go deleted file mode 100644 index 40f4f2593..000000000 --- a/internal/broadcast/definition_test.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright © 2021 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 broadcast - -import ( - "fmt" - "testing" - - "github.com/hyperledger/firefly/internal/identity" - "github.com/hyperledger/firefly/mocks/identitymanagermocks" - "github.com/hyperledger/firefly/mocks/syncasyncmocks" - "github.com/hyperledger/firefly/pkg/core" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" -) - -func TestBroadcastDefinitionAsNodeConfirm(t *testing.T) { - bm, cancel := newTestBroadcast(t) - defer cancel() - - msa := bm.syncasync.(*syncasyncmocks.Bridge) - mim := bm.identity.(*identitymanagermocks.Manager) - - mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) - msa.On("WaitForMessage", bm.ctx, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("pop")) - - _, err := bm.BroadcastDefinitionAsNode(bm.ctx, &core.Namespace{}, core.SystemTagDefineNamespace, true) - assert.EqualError(t, err, "pop") - - msa.AssertExpectations(t) - mim.AssertExpectations(t) -} - -func TestBroadcastIdentityClaim(t *testing.T) { - bm, cancel := newTestBroadcast(t) - defer cancel() - - msa := bm.syncasync.(*syncasyncmocks.Bridge) - mim := bm.identity.(*identitymanagermocks.Manager) - - mim.On("NormalizeSigningKey", mock.Anything, "0x1234", identity.KeyNormalizationBlockchainPlugin).Return("", nil) - msa.On("WaitForMessage", bm.ctx, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("pop")) - - _, err := bm.BroadcastIdentityClaim(bm.ctx, &core.IdentityClaim{ - Identity: &core.Identity{}, - }, &core.SignerRef{ - Key: "0x1234", - }, core.SystemTagDefineNamespace, true) - assert.EqualError(t, err, "pop") - - msa.AssertExpectations(t) - mim.AssertExpectations(t) -} - -func TestBroadcastIdentityClaimFail(t *testing.T) { - bm, cancel := newTestBroadcast(t) - defer cancel() - - mim := bm.identity.(*identitymanagermocks.Manager) - - mim.On("NormalizeSigningKey", mock.Anything, "0x1234", identity.KeyNormalizationBlockchainPlugin).Return("", fmt.Errorf("pop")) - - _, err := bm.BroadcastIdentityClaim(bm.ctx, &core.IdentityClaim{ - Identity: &core.Identity{}, - }, &core.SignerRef{ - Key: "0x1234", - }, core.SystemTagDefineNamespace, true) - assert.EqualError(t, err, "pop") - - mim.AssertExpectations(t) -} - -func TestBroadcastDatatypeDefinitionAsNodeConfirm(t *testing.T) { - bm, cancel := newTestBroadcast(t) - defer cancel() - - msa := bm.syncasync.(*syncasyncmocks.Bridge) - mim := bm.identity.(*identitymanagermocks.Manager) - - mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) - msa.On("WaitForMessage", bm.ctx, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("pop")) - - _, err := bm.BroadcastDefinitionAsNode(bm.ctx, &core.Datatype{}, core.SystemTagDefineNamespace, true) - assert.EqualError(t, err, "pop") - - msa.AssertExpectations(t) - mim.AssertExpectations(t) -} - -func TestBroadcastDefinitionBadIdentity(t *testing.T) { - bm, cancel := newTestBroadcast(t) - defer cancel() - - mim := bm.identity.(*identitymanagermocks.Manager) - mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - _, err := bm.BroadcastDefinition(bm.ctx, &core.Namespace{}, &core.SignerRef{ - Author: "wrong", - Key: "wrong", - }, core.SystemTagDefineNamespace, false) - assert.Regexp(t, "pop", err) -} diff --git a/internal/broadcast/manager.go b/internal/broadcast/manager.go index e71aaf238..f3a440e70 100644 --- a/internal/broadcast/manager.go +++ b/internal/broadcast/manager.go @@ -46,12 +46,7 @@ type Manager interface { core.Named NewBroadcast(in *core.MessageInOut) sysmessaging.MessageSender - BroadcastDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (msg *core.Message, err error) BroadcastMessage(ctx context.Context, in *core.MessageInOut, waitConfirm bool) (out *core.Message, err error) - BroadcastDefinitionAsNode(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) - BroadcastDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) - BroadcastIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) - BroadcastTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (msg *core.Message, err error) Start() error WaitStop() diff --git a/internal/broadcast/message_test.go b/internal/broadcast/message_test.go index 6ede2a3a5..954005e98 100644 --- a/internal/broadcast/message_test.go +++ b/internal/broadcast/message_test.go @@ -63,6 +63,37 @@ func TestBroadcastMessageOk(t *testing.T) { mdm.AssertExpectations(t) } +func TestBroadcastMessageWriteFail(t *testing.T) { + bm, cancel := newTestBroadcastWithMetrics(t) + defer cancel() + mdm := bm.data.(*datamocks.Manager) + mim := bm.identity.(*identitymanagermocks.Manager) + + ctx := context.Background() + mdm.On("ResolveInlineData", ctx, mock.Anything).Return(nil) + mdm.On("WriteNewMessage", mock.Anything, mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) + mim.On("ResolveInputSigningIdentity", ctx, mock.Anything).Return(nil) + + msg, err := bm.BroadcastMessage(ctx, &core.MessageInOut{ + Message: core.Message{ + Header: core.MessageHeader{ + SignerRef: core.SignerRef{ + Author: "did:firefly:org/abcd", + Key: "0x12345", + }, + }, + }, + InlineData: core.InlineData{ + {Value: fftypes.JSONAnyPtr(`{"hello": "world"}`)}, + }, + }, false) + assert.EqualError(t, err, "pop") + assert.Equal(t, "ns1", msg.Header.Namespace) + + mim.AssertExpectations(t) + mdm.AssertExpectations(t) +} + func TestBroadcastMessageWaitConfirmOk(t *testing.T) { bm, cancel := newTestBroadcast(t) defer cancel() diff --git a/internal/contracts/manager.go b/internal/contracts/manager.go index dd8ba33c6..861727306 100644 --- a/internal/contracts/manager.go +++ b/internal/contracts/manager.go @@ -23,8 +23,8 @@ import ( "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/coremsgs" + "github.com/hyperledger/firefly/internal/defsender" "github.com/hyperledger/firefly/internal/identity" "github.com/hyperledger/firefly/internal/operations" "github.com/hyperledger/firefly/internal/syncasync" @@ -71,7 +71,7 @@ type contractManager struct { namespace string database database.Plugin txHelper txcommon.Helper - broadcast broadcast.Manager + defsender defsender.Sender identity identity.Manager blockchain blockchain.Plugin ffiParamValidator core.FFIParamValidator @@ -79,8 +79,8 @@ type contractManager struct { syncasync syncasync.Bridge } -func NewContractManager(ctx context.Context, ns string, di database.Plugin, bi blockchain.Plugin, bm broadcast.Manager, im identity.Manager, om operations.Manager, txHelper txcommon.Helper, sa syncasync.Bridge) (Manager, error) { - if di == nil || bm == nil || im == nil || bi == nil || om == nil || txHelper == nil || sa == nil { +func NewContractManager(ctx context.Context, ns string, di database.Plugin, bi blockchain.Plugin, ds defsender.Sender, im identity.Manager, om operations.Manager, txHelper txcommon.Helper, sa syncasync.Bridge) (Manager, error) { + if di == nil || ds == nil || im == nil || bi == nil || om == nil || txHelper == nil || sa == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "ContractManager") } v, err := bi.GetFFIParamValidator(ctx) @@ -92,7 +92,7 @@ func NewContractManager(ctx context.Context, ns string, di database.Plugin, bi b namespace: ns, database: di, txHelper: txHelper, - broadcast: bm, + defsender: ds, identity: im, blockchain: bi, ffiParamValidator: v, @@ -139,7 +139,7 @@ func (cm *contractManager) BroadcastFFI(ctx context.Context, ffi *core.FFI, wait } output = ffi - msg, err := cm.broadcast.BroadcastDefinitionAsNode(ctx, ffi, core.SystemTagDefineFFI, waitConfirm) + msg, err := cm.defsender.BroadcastDefinitionAsNode(ctx, ffi, core.SystemTagDefineFFI, waitConfirm) if err != nil { return nil, err } @@ -373,7 +373,7 @@ func (cm *contractManager) BroadcastContractAPI(ctx context.Context, httpServerU return nil, err } - msg, err := cm.broadcast.BroadcastDefinitionAsNode(ctx, api, core.SystemTagDefineContractAPI, waitConfirm) + msg, err := cm.defsender.BroadcastDefinitionAsNode(ctx, api, core.SystemTagDefineContractAPI, waitConfirm) if err != nil { return nil, err } diff --git a/internal/contracts/manager_test.go b/internal/contracts/manager_test.go index 41b62c210..a7324abce 100644 --- a/internal/contracts/manager_test.go +++ b/internal/contracts/manager_test.go @@ -27,9 +27,9 @@ import ( "github.com/hyperledger/firefly/internal/syncasync" "github.com/hyperledger/firefly/internal/txcommon" "github.com/hyperledger/firefly/mocks/blockchainmocks" - "github.com/hyperledger/firefly/mocks/broadcastmocks" "github.com/hyperledger/firefly/mocks/databasemocks" "github.com/hyperledger/firefly/mocks/datamocks" + "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/mocks/operationmocks" "github.com/hyperledger/firefly/mocks/syncasyncmocks" @@ -44,7 +44,7 @@ import ( func newTestContractManager() *contractManager { mdi := &databasemocks.Plugin{} mdm := &datamocks.Manager{} - mbm := &broadcastmocks.Manager{} + mds := &defsendermocks.Sender{} mim := &identitymanagermocks.Manager{} mbi := &blockchainmocks.Plugin{} mom := &operationmocks.Manager{} @@ -61,7 +61,7 @@ func newTestContractManager() *contractManager { a[1].(func(context.Context) error)(a[0].(context.Context)), } } - cm, _ := NewContractManager(context.Background(), "ns1", mdi, mbi, mbm, mim, mom, txHelper, msa) + cm, _ := NewContractManager(context.Background(), "ns1", mdi, mbi, mds, mim, mom, txHelper, msa) cm.(*contractManager).txHelper = &txcommonmocks.Helper{} return cm.(*contractManager) } @@ -79,21 +79,21 @@ func TestName(t *testing.T) { func TestNewContractManagerFFISchemaLoaderFail(t *testing.T) { mdi := &databasemocks.Plugin{} mdm := &datamocks.Manager{} - mbm := &broadcastmocks.Manager{} + mds := &defsendermocks.Sender{} mim := &identitymanagermocks.Manager{} mbi := &blockchainmocks.Plugin{} mom := &operationmocks.Manager{} txHelper := txcommon.NewTransactionHelper("ns1", mdi, mdm) msa := &syncasyncmocks.Bridge{} mbi.On("GetFFIParamValidator", mock.Anything).Return(nil, fmt.Errorf("pop")) - _, err := NewContractManager(context.Background(), "ns1", mdi, mbi, mbm, mim, mom, txHelper, msa) + _, err := NewContractManager(context.Background(), "ns1", mdi, mbi, mds, mim, mom, txHelper, msa) assert.Regexp(t, "pop", err) } func TestNewContractManagerFFISchemaLoader(t *testing.T) { mdi := &databasemocks.Plugin{} mdm := &datamocks.Manager{} - mbm := &broadcastmocks.Manager{} + mds := &defsendermocks.Sender{} mim := &identitymanagermocks.Manager{} mbi := &blockchainmocks.Plugin{} mom := &operationmocks.Manager{} @@ -101,7 +101,7 @@ func TestNewContractManagerFFISchemaLoader(t *testing.T) { msa := &syncasyncmocks.Bridge{} mbi.On("GetFFIParamValidator", mock.Anything).Return(ðereum.FFIParamValidator{}, nil) mom.On("RegisterHandler", mock.Anything, mock.Anything, mock.Anything) - _, err := NewContractManager(context.Background(), "ns1", mdi, mbi, mbm, mim, mom, txHelper, msa) + _, err := NewContractManager(context.Background(), "ns1", mdi, mbi, mds, mim, mom, txHelper, msa) assert.NoError(t, err) } @@ -109,7 +109,7 @@ func TestBroadcastFFI(t *testing.T) { cm := newTestContractManager() mdb := cm.database.(*databasemocks.Plugin) mim := cm.identity.(*identitymanagermocks.Manager) - mbm := cm.broadcast.(*broadcastmocks.Manager) + mds := cm.defsender.(*defsendermocks.Sender) mdb.On("GetFFI", mock.Anything, "ns1", "test", "1.0.0").Return(nil, nil) mim.On("GetOrgKey", mock.Anything).Return("key", nil) @@ -119,7 +119,7 @@ func TestBroadcastFFI(t *testing.T) { ID: fftypes.NewUUID(), }, } - mbm.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) + mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) ffi := &core.FFI{ Name: "test", Version: "1.0.0", @@ -144,7 +144,7 @@ func TestBroadcastFFI(t *testing.T) { func TestBroadcastFFIInvalid(t *testing.T) { cm := newTestContractManager() mdb := cm.database.(*databasemocks.Plugin) - mbm := cm.broadcast.(*broadcastmocks.Manager) + mds := cm.defsender.(*defsendermocks.Sender) mdb.On("GetFFI", mock.Anything, "ns1", "test", "1.0.0").Return(nil, nil) @@ -153,7 +153,7 @@ func TestBroadcastFFIInvalid(t *testing.T) { ID: fftypes.NewUUID(), }, } - mbm.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) + mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) ffi := &core.FFI{ Name: "test", Version: "1.0.0", @@ -177,7 +177,7 @@ func TestBroadcastFFIInvalid(t *testing.T) { func TestBroadcastFFIExists(t *testing.T) { cm := newTestContractManager() mdb := cm.database.(*databasemocks.Plugin) - mbm := cm.broadcast.(*broadcastmocks.Manager) + mds := &defsendermocks.Sender{} mdb.On("GetFFI", mock.Anything, "ns1", "test", "1.0.0").Return(&core.FFI{}, nil) @@ -186,7 +186,7 @@ func TestBroadcastFFIExists(t *testing.T) { ID: fftypes.NewUUID(), }, } - mbm.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) + mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) ffi := &core.FFI{ Name: "test", Version: "1.0.0", @@ -199,13 +199,13 @@ func TestBroadcastFFIExists(t *testing.T) { func TestBroadcastFFIFail(t *testing.T) { cm := newTestContractManager() mdb := cm.database.(*databasemocks.Plugin) - mbm := cm.broadcast.(*broadcastmocks.Manager) + mds := cm.defsender.(*defsendermocks.Sender) mim := cm.identity.(*identitymanagermocks.Manager) mdb.On("GetFFI", mock.Anything, "ns1", "test", "1.0.0").Return(nil, nil) mim.On("GetOrgKey", mock.Anything).Return("key", nil) - mbm.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(nil, fmt.Errorf("pop")) + mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(nil, fmt.Errorf("pop")) ffi := &core.FFI{ Name: "test", Version: "1.0.0", @@ -1926,7 +1926,7 @@ func TestBroadcastContractAPI(t *testing.T) { cm := newTestContractManager() mbi := cm.blockchain.(*blockchainmocks.Plugin) mdb := cm.database.(*databasemocks.Plugin) - mbm := cm.broadcast.(*broadcastmocks.Manager) + mds := cm.defsender.(*defsendermocks.Sender) msg := &core.Message{ Header: core.MessageHeader{ @@ -1946,7 +1946,7 @@ func TestBroadcastContractAPI(t *testing.T) { mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) mdb.On("GetFFIByID", mock.Anything, "ns1", api.Interface.ID).Return(&core.FFI{}, nil) - mbm.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) + mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) api, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) @@ -1957,7 +1957,7 @@ func TestBroadcastContractAPI(t *testing.T) { mbi.AssertExpectations(t) mdb.AssertExpectations(t) - mbm.AssertExpectations(t) + mds.AssertExpectations(t) } func TestBroadcastContractAPIBadLocation(t *testing.T) { @@ -1987,7 +1987,7 @@ func TestBroadcastContractAPIExisting(t *testing.T) { cm := newTestContractManager() mbi := cm.blockchain.(*blockchainmocks.Plugin) mdb := cm.database.(*databasemocks.Plugin) - mbm := cm.broadcast.(*broadcastmocks.Manager) + mds := cm.defsender.(*defsendermocks.Sender) msg := &core.Message{ Header: core.MessageHeader{ @@ -2017,7 +2017,7 @@ func TestBroadcastContractAPIExisting(t *testing.T) { mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(existing, nil) mdb.On("GetFFIByID", mock.Anything, "ns1", api.Interface.ID).Return(&core.FFI{}, nil) - mbm.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) + mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) @@ -2025,7 +2025,7 @@ func TestBroadcastContractAPIExisting(t *testing.T) { mbi.AssertExpectations(t) mdb.AssertExpectations(t) - mbm.AssertExpectations(t) + mds.AssertExpectations(t) } func TestBroadcastContractAPICannotChangeLocation(t *testing.T) { @@ -2068,7 +2068,7 @@ func TestBroadcastContractAPIInterfaceName(t *testing.T) { cm := newTestContractManager() mbi := cm.blockchain.(*blockchainmocks.Plugin) mdb := cm.database.(*databasemocks.Plugin) - mbm := cm.broadcast.(*broadcastmocks.Manager) + mds := cm.defsender.(*defsendermocks.Sender) msg := &core.Message{ Header: core.MessageHeader{ @@ -2090,7 +2090,7 @@ func TestBroadcastContractAPIInterfaceName(t *testing.T) { mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) mdb.On("GetFFI", mock.Anything, "ns1", "my-ffi", "1").Return(&core.FFI{ID: interfaceID}, nil) - mbm.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) + mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) @@ -2099,14 +2099,14 @@ func TestBroadcastContractAPIInterfaceName(t *testing.T) { mbi.AssertExpectations(t) mdb.AssertExpectations(t) - mbm.AssertExpectations(t) + mds.AssertExpectations(t) } func TestBroadcastContractAPIFail(t *testing.T) { cm := newTestContractManager() mbi := cm.blockchain.(*blockchainmocks.Plugin) mdb := cm.database.(*databasemocks.Plugin) - mbm := cm.broadcast.(*broadcastmocks.Manager) + mds := cm.defsender.(*defsendermocks.Sender) api := &core.ContractAPI{ ID: fftypes.NewUUID(), @@ -2121,7 +2121,7 @@ func TestBroadcastContractAPIFail(t *testing.T) { mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) mdb.On("GetFFIByID", mock.Anything, "ns1", api.Interface.ID).Return(&core.FFI{}, nil) - mbm.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(nil, fmt.Errorf("pop")) + mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(nil, fmt.Errorf("pop")) _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) @@ -2129,7 +2129,7 @@ func TestBroadcastContractAPIFail(t *testing.T) { mbi.AssertExpectations(t) mdb.AssertExpectations(t) - mbm.AssertExpectations(t) + mds.AssertExpectations(t) } func TestBroadcastContractAPINoInterface(t *testing.T) { @@ -2324,7 +2324,7 @@ func TestCheckParamSchemaCompileFail(t *testing.T) { func TestAddJSONSchemaExtension(t *testing.T) { cm := &contractManager{ database: &databasemocks.Plugin{}, - broadcast: &broadcastmocks.Manager{}, + defsender: &defsendermocks.Sender{}, identity: &identitymanagermocks.Manager{}, blockchain: &blockchainmocks.Plugin{}, ffiParamValidator: &MockFFIParamValidator{}, diff --git a/internal/broadcast/datatype.go b/internal/defsender/datatype.go similarity index 94% rename from internal/broadcast/datatype.go rename to internal/defsender/datatype.go index 159731bdf..a9cb7af05 100644 --- a/internal/broadcast/datatype.go +++ b/internal/defsender/datatype.go @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package broadcast +package defsender import ( "context" @@ -23,7 +23,7 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (bm *broadcastManager) BroadcastDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (*core.Message, error) { +func (bm *definitionSender) BroadcastDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (*core.Message, error) { // Validate the input data definition data datatype.ID = fftypes.NewUUID() diff --git a/internal/broadcast/datatype_test.go b/internal/defsender/datatype_test.go similarity index 57% rename from internal/broadcast/datatype_test.go rename to internal/defsender/datatype_test.go index 7d98afba6..a57144b01 100644 --- a/internal/broadcast/datatype_test.go +++ b/internal/defsender/datatype_test.go @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package broadcast +package defsender import ( "context" @@ -22,32 +22,32 @@ import ( "testing" "github.com/hyperledger/firefly-common/pkg/fftypes" - "github.com/hyperledger/firefly/mocks/databasemocks" + "github.com/hyperledger/firefly/mocks/broadcastmocks" "github.com/hyperledger/firefly/mocks/datamocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" + "github.com/hyperledger/firefly/mocks/sysmessagingmocks" "github.com/hyperledger/firefly/pkg/core" - "github.com/hyperledger/firefly/pkg/database" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) func TestBroadcastDatatypeBadType(t *testing.T) { - bm, cancel := newTestBroadcast(t) + ds, cancel := newTestDefinitionSender(t) defer cancel() - _, err := bm.BroadcastDatatype(context.Background(), &core.Datatype{ + _, err := ds.BroadcastDatatype(context.Background(), &core.Datatype{ Validator: core.ValidatorType("wrong"), }, false) assert.Regexp(t, "FF00111.*validator", err) } func TestBroadcastDatatypeBadValue(t *testing.T) { - bm, cancel := newTestBroadcast(t) + ds, cancel := newTestDefinitionSender(t) defer cancel() - mdm := bm.data.(*datamocks.Manager) + mdm := ds.data.(*datamocks.Manager) mdm.On("CheckDatatype", mock.Anything, mock.Anything).Return(nil) - mim := bm.identity.(*identitymanagermocks.Manager) + mim := ds.identity.(*identitymanagermocks.Manager) mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) - _, err := bm.BroadcastDatatype(context.Background(), &core.Datatype{ + _, err := ds.BroadcastDatatype(context.Background(), &core.Datatype{ Namespace: "ns1", Name: "ent1", Version: "0.0.1", @@ -56,40 +56,16 @@ func TestBroadcastDatatypeBadValue(t *testing.T) { assert.Regexp(t, "FF10137.*value", err) } -func TestBroadcastUpsertFail(t *testing.T) { - bm, cancel := newTestBroadcast(t) - defer cancel() - mdm := bm.data.(*datamocks.Manager) - mim := bm.identity.(*identitymanagermocks.Manager) - - mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) - mdm.On("WriteNewMessage", mock.Anything, mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - mdm.On("CheckDatatype", mock.Anything, mock.Anything).Return(nil) - - _, err := bm.BroadcastDatatype(context.Background(), &core.Datatype{ - Namespace: "ns1", - Name: "ent1", - Version: "0.0.1", - Value: fftypes.JSONAnyPtr(`{"some": "data"}`), - }, false) - assert.EqualError(t, err, "pop") - - mim.AssertExpectations(t) - mdm.AssertExpectations(t) -} - func TestBroadcastDatatypeInvalid(t *testing.T) { - bm, cancel := newTestBroadcast(t) + ds, cancel := newTestDefinitionSender(t) defer cancel() - mdi := bm.database.(*databasemocks.Plugin) - mdm := bm.data.(*datamocks.Manager) - mim := bm.identity.(*identitymanagermocks.Manager) + mdm := ds.data.(*datamocks.Manager) + mim := ds.identity.(*identitymanagermocks.Manager) mim.On("ResolveInputIdentity", mock.Anything, mock.Anything).Return(nil) - mdi.On("UpsertData", mock.Anything, mock.Anything, database.UpsertOptimizationNew).Return(nil) mdm.On("CheckDatatype", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - _, err := bm.BroadcastDatatype(context.Background(), &core.Datatype{ + _, err := ds.BroadcastDatatype(context.Background(), &core.Datatype{ Namespace: "ns1", Name: "ent1", Version: "0.0.1", @@ -99,16 +75,19 @@ func TestBroadcastDatatypeInvalid(t *testing.T) { } func TestBroadcastOk(t *testing.T) { - bm, cancel := newTestBroadcast(t) + ds, cancel := newTestDefinitionSender(t) defer cancel() - mdm := bm.data.(*datamocks.Manager) - mim := bm.identity.(*identitymanagermocks.Manager) + mdm := ds.data.(*datamocks.Manager) + mim := ds.identity.(*identitymanagermocks.Manager) + mbm := ds.broadcast.(*broadcastmocks.Manager) + mms := &sysmessagingmocks.MessageSender{} mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) mdm.On("CheckDatatype", mock.Anything, mock.Anything).Return(nil) - mdm.On("WriteNewMessage", mock.Anything, mock.Anything, mock.Anything).Return(nil) + mbm.On("NewBroadcast", mock.Anything).Return(mms) + mms.On("Send", context.Background()).Return(nil) - _, err := bm.BroadcastDatatype(context.Background(), &core.Datatype{ + _, err := ds.BroadcastDatatype(context.Background(), &core.Datatype{ Namespace: "ns1", Name: "ent1", Version: "0.0.1", @@ -118,4 +97,6 @@ func TestBroadcastOk(t *testing.T) { mdm.AssertExpectations(t) mim.AssertExpectations(t) + mbm.AssertExpectations(t) + mms.AssertExpectations(t) } diff --git a/internal/broadcast/definition.go b/internal/defsender/sender.go similarity index 53% rename from internal/broadcast/definition.go rename to internal/defsender/sender.go index 361b08784..34822fd29 100644 --- a/internal/broadcast/definition.go +++ b/internal/defsender/sender.go @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package broadcast +package defsender import ( "context" @@ -22,17 +22,53 @@ import ( "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/coremsgs" "github.com/hyperledger/firefly/internal/data" "github.com/hyperledger/firefly/internal/identity" "github.com/hyperledger/firefly/pkg/core" ) -func (bm *broadcastManager) BroadcastDefinitionAsNode(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) { +type Sender interface { + core.Named + + BroadcastDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (msg *core.Message, err error) + BroadcastDefinitionAsNode(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) + BroadcastDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) + BroadcastIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) + BroadcastTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (msg *core.Message, err error) +} + +type definitionSender struct { + ctx context.Context + namespace string + broadcast broadcast.Manager + identity identity.Manager + data data.Manager +} + +func NewDefinitionSender(ctx context.Context, ns string, bm broadcast.Manager, im identity.Manager, dm data.Manager) (Sender, error) { + if bm == nil || im == nil || dm == nil { + return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError) + } + return &definitionSender{ + ctx: ctx, + namespace: ns, + broadcast: bm, + identity: im, + data: dm, + }, nil +} + +func (bm *definitionSender) Name() string { + return "DefinitionSender" +} + +func (bm *definitionSender) BroadcastDefinitionAsNode(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) { return bm.BroadcastDefinition(ctx, def, &core.SignerRef{ /* resolve to node default */ }, tag, waitConfirm) } -func (bm *broadcastManager) BroadcastDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { +func (bm *definitionSender) BroadcastDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { err = bm.identity.ResolveInputSigningIdentity(ctx, signingIdentity) if err != nil { @@ -44,7 +80,7 @@ func (bm *broadcastManager) BroadcastDefinition(ctx context.Context, def core.De // BroadcastIdentityClaim is a special form of BroadcastDefinitionAsNode where the signing identity does not need to have been pre-registered // The blockchain "key" will be normalized, but the "author" will pass through unchecked -func (bm *broadcastManager) BroadcastIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { +func (bm *definitionSender) BroadcastIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { signingIdentity.Key, err = bm.identity.NormalizeSigningKey(ctx, signingIdentity.Key, identity.KeyNormalizationBlockchainPlugin) if err != nil { @@ -54,56 +90,36 @@ func (bm *broadcastManager) BroadcastIdentityClaim(ctx context.Context, def *cor return bm.broadcastDefinitionCommon(ctx, def, signingIdentity, tag, waitConfirm) } -func (bm *broadcastManager) broadcastDefinitionCommon(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { +func (bm *definitionSender) broadcastDefinitionCommon(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { - // Serialize it into a data object, as a piece of data we can write to a message - d := &core.Data{ - Validator: core.ValidatorTypeSystemDefinition, - ID: fftypes.NewUUID(), - Namespace: bm.namespace, - Created: fftypes.Now(), - } b, err := json.Marshal(&def) - if err == nil { - d.Value = fftypes.JSONAnyPtrBytes(b) - err = d.Seal(ctx, nil) - } if err != nil { return nil, i18n.WrapError(ctx, err, coremsgs.MsgSerializationFailed) } - // Create a broadcast message referring to the data - newMsg := &data.NewMessage{ - Message: &core.MessageInOut{ - Message: core.Message{ - Header: core.MessageHeader{ - Namespace: bm.namespace, - Type: core.MessageTypeDefinition, - SignerRef: *signingIdentity, - Topics: core.FFStringArray{def.Topic()}, - Tag: tag, - TxType: core.TransactionTypeBatchPin, - }, - Data: core.DataRefs{ - {ID: d.ID, Hash: d.Hash, ValueSize: d.ValueSize}, - }, + message := &core.MessageInOut{ + Message: core.Message{ + Header: core.MessageHeader{ + Namespace: bm.namespace, + Type: core.MessageTypeDefinition, + SignerRef: *signingIdentity, + Topics: core.FFStringArray{def.Topic()}, + Tag: tag, + TxType: core.TransactionTypeBatchPin, + }, + }, + InlineData: core.InlineData{ + &core.DataRefOrValue{ + Value: fftypes.JSONAnyPtrBytes(b), }, }, - NewData: core.DataArray{d}, - AllData: core.DataArray{d}, } + sender := bm.broadcast.NewBroadcast(message) - // Broadcast the message - sender := broadcastSender{ - mgr: bm, - msg: newMsg, - resolved: true, - } - sender.setDefaults() if waitConfirm { err = sender.SendAndWait(ctx) } else { err = sender.Send(ctx) } - return &newMsg.Message.Message, err + return &message.Message, err } diff --git a/internal/defsender/sender_test.go b/internal/defsender/sender_test.go new file mode 100644 index 000000000..1487635af --- /dev/null +++ b/internal/defsender/sender_test.go @@ -0,0 +1,149 @@ +// Copyright © 2021 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 defsender + +import ( + "context" + "fmt" + "testing" + + "github.com/hyperledger/firefly/internal/identity" + "github.com/hyperledger/firefly/mocks/broadcastmocks" + "github.com/hyperledger/firefly/mocks/datamocks" + "github.com/hyperledger/firefly/mocks/identitymanagermocks" + "github.com/hyperledger/firefly/mocks/sysmessagingmocks" + "github.com/hyperledger/firefly/pkg/core" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func newTestDefinitionSender(t *testing.T) (*definitionSender, func()) { + mbm := &broadcastmocks.Manager{} + mim := &identitymanagermocks.Manager{} + mdm := &datamocks.Manager{} + + ctx, cancel := context.WithCancel(context.Background()) + b, err := NewDefinitionSender(ctx, "ns1", mbm, mim, mdm) + assert.NoError(t, err) + return b.(*definitionSender), cancel +} + +func TestInitFail(t *testing.T) { + _, err := NewDefinitionSender(context.Background(), "", nil, nil, nil) + assert.Regexp(t, "FF10128", err) +} + +func TestName(t *testing.T) { + bm, cancel := newTestDefinitionSender(t) + defer cancel() + assert.Equal(t, "DefinitionSender", bm.Name()) +} + +func TestBroadcastDefinitionAsNodeConfirm(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + + mim := ds.identity.(*identitymanagermocks.Manager) + mbm := ds.broadcast.(*broadcastmocks.Manager) + mms := &sysmessagingmocks.MessageSender{} + + mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) + mbm.On("NewBroadcast", mock.Anything).Return(mms) + mms.On("SendAndWait", mock.Anything).Return(nil) + + _, err := ds.BroadcastDefinitionAsNode(ds.ctx, &core.Namespace{}, core.SystemTagDefineNamespace, true) + assert.NoError(t, err) + + mim.AssertExpectations(t) + mbm.AssertExpectations(t) + mms.AssertExpectations(t) +} + +func TestBroadcastIdentityClaim(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + + mim := ds.identity.(*identitymanagermocks.Manager) + mbm := ds.broadcast.(*broadcastmocks.Manager) + mms := &sysmessagingmocks.MessageSender{} + + mim.On("NormalizeSigningKey", mock.Anything, "0x1234", identity.KeyNormalizationBlockchainPlugin).Return("", nil) + mbm.On("NewBroadcast", mock.Anything).Return(mms) + mms.On("SendAndWait", mock.Anything).Return(nil) + + _, err := ds.BroadcastIdentityClaim(ds.ctx, &core.IdentityClaim{ + Identity: &core.Identity{}, + }, &core.SignerRef{ + Key: "0x1234", + }, core.SystemTagDefineNamespace, true) + assert.NoError(t, err) + + mim.AssertExpectations(t) + mbm.AssertExpectations(t) + mms.AssertExpectations(t) +} + +func TestBroadcastIdentityClaimFail(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + + mim := ds.identity.(*identitymanagermocks.Manager) + + mim.On("NormalizeSigningKey", mock.Anything, "0x1234", identity.KeyNormalizationBlockchainPlugin).Return("", fmt.Errorf("pop")) + + _, err := ds.BroadcastIdentityClaim(ds.ctx, &core.IdentityClaim{ + Identity: &core.Identity{}, + }, &core.SignerRef{ + Key: "0x1234", + }, core.SystemTagDefineNamespace, true) + assert.EqualError(t, err, "pop") + + mim.AssertExpectations(t) +} + +func TestBroadcastDatatypeDefinitionAsNodeConfirm(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + + mim := ds.identity.(*identitymanagermocks.Manager) + mbm := ds.broadcast.(*broadcastmocks.Manager) + mms := &sysmessagingmocks.MessageSender{} + + mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) + mbm.On("NewBroadcast", mock.Anything).Return(mms) + mms.On("SendAndWait", mock.Anything).Return(nil) + + _, err := ds.BroadcastDefinitionAsNode(ds.ctx, &core.Datatype{}, core.SystemTagDefineNamespace, true) + assert.NoError(t, err) + + mim.AssertExpectations(t) + mbm.AssertExpectations(t) + mms.AssertExpectations(t) +} + +func TestBroadcastDefinitionBadIdentity(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + + mim := ds.identity.(*identitymanagermocks.Manager) + mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) + _, err := ds.BroadcastDefinition(ds.ctx, &core.Namespace{}, &core.SignerRef{ + Author: "wrong", + Key: "wrong", + }, core.SystemTagDefineNamespace, false) + assert.Regexp(t, "pop", err) +} diff --git a/internal/broadcast/tokenpool.go b/internal/defsender/tokenpool.go similarity index 92% rename from internal/broadcast/tokenpool.go rename to internal/defsender/tokenpool.go index 7b62e9d90..b44f76707 100644 --- a/internal/broadcast/tokenpool.go +++ b/internal/defsender/tokenpool.go @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package broadcast +package defsender import ( "context" @@ -22,7 +22,7 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (bm *broadcastManager) BroadcastTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (msg *core.Message, err error) { +func (bm *definitionSender) BroadcastTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (msg *core.Message, err error) { if err := pool.Pool.Validate(ctx); err != nil { return nil, err } diff --git a/internal/broadcast/tokenpool_test.go b/internal/defsender/tokenpool_test.go similarity index 57% rename from internal/broadcast/tokenpool_test.go rename to internal/defsender/tokenpool_test.go index aea276d41..ad5e09981 100644 --- a/internal/broadcast/tokenpool_test.go +++ b/internal/defsender/tokenpool_test.go @@ -14,27 +14,26 @@ // See the License for the specific language governing permissions and // limitations under the License. -package broadcast +package defsender import ( "context" - "fmt" "testing" "github.com/hyperledger/firefly-common/pkg/fftypes" - "github.com/hyperledger/firefly/mocks/databasemocks" + "github.com/hyperledger/firefly/mocks/broadcastmocks" "github.com/hyperledger/firefly/mocks/datamocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" + "github.com/hyperledger/firefly/mocks/sysmessagingmocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) func TestBroadcastTokenPoolInvalid(t *testing.T) { - bm, cancel := newTestBroadcast(t) + ds, cancel := newTestDefinitionSender(t) defer cancel() - mdi := bm.database.(*databasemocks.Plugin) - mdm := bm.data.(*datamocks.Manager) + mdm := ds.data.(*datamocks.Manager) pool := &core.TokenPoolAnnouncement{ Pool: &core.TokenPool{ @@ -47,45 +46,20 @@ func TestBroadcastTokenPoolInvalid(t *testing.T) { }, } - _, err := bm.BroadcastTokenPool(context.Background(), pool, false) + _, err := ds.BroadcastTokenPool(context.Background(), pool, false) assert.Regexp(t, "FF00140", err) - mdi.AssertExpectations(t) mdm.AssertExpectations(t) } -func TestBroadcastTokenPoolBroadcastFail(t *testing.T) { - bm, cancel := newTestBroadcast(t) - defer cancel() - mdm := bm.data.(*datamocks.Manager) - mim := bm.identity.(*identitymanagermocks.Manager) - - pool := &core.TokenPoolAnnouncement{ - Pool: &core.TokenPool{ - ID: fftypes.NewUUID(), - Namespace: "ns1", - Name: "mypool", - Type: core.TokenTypeNonFungible, - Locator: "N1", - Symbol: "COIN", - }, - } - - mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) - mdm.On("WriteNewMessage", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - - _, err := bm.BroadcastTokenPool(context.Background(), pool, false) - assert.EqualError(t, err, "pop") - - mdm.AssertExpectations(t) - mim.AssertExpectations(t) -} - func TestBroadcastTokenPoolOk(t *testing.T) { - bm, cancel := newTestBroadcast(t) + ds, cancel := newTestDefinitionSender(t) defer cancel() - mdm := bm.data.(*datamocks.Manager) - mim := bm.identity.(*identitymanagermocks.Manager) + + mdm := ds.data.(*datamocks.Manager) + mim := ds.identity.(*identitymanagermocks.Manager) + mbm := ds.broadcast.(*broadcastmocks.Manager) + mms := &sysmessagingmocks.MessageSender{} pool := &core.TokenPoolAnnouncement{ Pool: &core.TokenPool{ @@ -99,11 +73,14 @@ func TestBroadcastTokenPoolOk(t *testing.T) { } mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) - mdm.On("WriteNewMessage", mock.Anything, mock.Anything).Return(nil) + mbm.On("NewBroadcast", mock.Anything).Return(mms) + mms.On("Send", context.Background()).Return(nil) - _, err := bm.BroadcastTokenPool(context.Background(), pool, false) + _, err := ds.BroadcastTokenPool(context.Background(), pool, false) assert.NoError(t, err) mdm.AssertExpectations(t) mim.AssertExpectations(t) + mbm.AssertExpectations(t) + mms.AssertExpectations(t) } diff --git a/internal/events/event_manager.go b/internal/events/event_manager.go index 56a7c4001..e2fb0cce7 100644 --- a/internal/events/event_manager.go +++ b/internal/events/event_manager.go @@ -34,6 +34,7 @@ import ( "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/internal/data" "github.com/hyperledger/firefly/internal/definitions" + "github.com/hyperledger/firefly/internal/defsender" "github.com/hyperledger/firefly/internal/events/eifactory" "github.com/hyperledger/firefly/internal/events/system" "github.com/hyperledger/firefly/internal/identity" @@ -95,7 +96,8 @@ type eventManager struct { database database.Plugin txHelper txcommon.Helper identity identity.Manager - definitions definitions.DefinitionHandler + defsender defsender.Sender + defhandler definitions.DefinitionHandler data data.Manager subManager *subscriptionManager retry retry.Retry @@ -115,8 +117,8 @@ type eventManager struct { multiparty multiparty.Manager } -func NewEventManager(ctx context.Context, ns string, ni sysmessaging.LocalNodeInfo, si sharedstorage.Plugin, di database.Plugin, bi blockchain.Plugin, im identity.Manager, dh definitions.DefinitionHandler, dm data.Manager, bm broadcast.Manager, pm privatemessaging.Manager, am assets.Manager, sd shareddownload.Manager, mm metrics.Manager, txHelper txcommon.Helper, transports map[string]events.Plugin, mp multiparty.Manager) (EventManager, error) { - if ni == nil || si == nil || di == nil || bi == nil || im == nil || dh == nil || dm == nil || bm == nil || pm == nil || am == nil { +func NewEventManager(ctx context.Context, ns string, ni sysmessaging.LocalNodeInfo, si sharedstorage.Plugin, di database.Plugin, bi blockchain.Plugin, im identity.Manager, dh definitions.DefinitionHandler, dm data.Manager, ds defsender.Sender, bm broadcast.Manager, pm privatemessaging.Manager, am assets.Manager, sd shareddownload.Manager, mm metrics.Manager, txHelper txcommon.Helper, transports map[string]events.Plugin, mp multiparty.Manager) (EventManager, error) { + if ni == nil || si == nil || di == nil || bi == nil || im == nil || dh == nil || dm == nil || ds == nil || bm == nil || pm == nil || am == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "EventManager") } newPinNotifier := newEventNotifier(ctx, "pins") @@ -129,7 +131,8 @@ func NewEventManager(ctx context.Context, ns string, ni sysmessaging.LocalNodeIn database: di, txHelper: txHelper, identity: im, - definitions: dh, + defsender: ds, + defhandler: dh, data: dm, broadcast: bm, messaging: pm, diff --git a/internal/events/event_manager_test.go b/internal/events/event_manager_test.go index c06d68471..d6d7c10f8 100644 --- a/internal/events/event_manager_test.go +++ b/internal/events/event_manager_test.go @@ -32,6 +32,7 @@ import ( "github.com/hyperledger/firefly/mocks/databasemocks" "github.com/hyperledger/firefly/mocks/datamocks" "github.com/hyperledger/firefly/mocks/definitionsmocks" + "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/mocks/eventsmocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/mocks/metricsmocks" @@ -76,6 +77,7 @@ func newTestEventManagerCommon(t *testing.T, metrics, dbconcurrency bool) (*even met := &eventsmocks.Plugin{} mdm := &datamocks.Manager{} msh := &definitionsmocks.DefinitionHandler{} + mds := &defsendermocks.Sender{} mbm := &broadcastmocks.Manager{} mpm := &privatemessagingmocks.Manager{} mam := &assetmocks.Manager{} @@ -96,7 +98,7 @@ func newTestEventManagerCommon(t *testing.T, metrics, dbconcurrency bool) (*even mdi.On("Capabilities").Return(&database.Capabilities{Concurrency: dbconcurrency}).Maybe() mev.On("SetHandler", "ns1", mock.Anything).Return(nil).Maybe() mev.On("ValidateOptions", mock.Anything).Return(nil).Maybe() - emi, err := NewEventManager(ctx, "ns1", mni, mpi, mdi, mbi, mim, msh, mdm, mbm, mpm, mam, mdd, mmi, txHelper, events, mmp) + emi, err := NewEventManager(ctx, "ns1", mni, mpi, mdi, mbi, mim, msh, mdm, mds, mbm, mpm, mam, mdd, mmi, txHelper, events, mmp) em := emi.(*eventManager) em.txHelper = &txcommonmocks.Helper{} mockRunAsGroupPassthrough(mdi) @@ -131,7 +133,7 @@ func TestStartStop(t *testing.T) { } func TestStartStopBadDependencies(t *testing.T) { - _, err := NewEventManager(context.Background(), "", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) + _, err := NewEventManager(context.Background(), "", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) assert.Regexp(t, "FF10128", err) } @@ -145,6 +147,7 @@ func TestStartStopEventListenerFail(t *testing.T) { mpi := &sharedstoragemocks.Plugin{} mdm := &datamocks.Manager{} msh := &definitionsmocks.DefinitionHandler{} + mds := &defsendermocks.Sender{} mbm := &broadcastmocks.Manager{} mpm := &privatemessagingmocks.Manager{} mni := &sysmessagingmocks.LocalNodeInfo{} @@ -158,7 +161,7 @@ func TestStartStopEventListenerFail(t *testing.T) { mdi.On("Capabilities").Return(&database.Capabilities{Concurrency: false}) mbi.On("VerifierType").Return(core.VerifierTypeEthAddress) mev.On("SetHandler", "ns1", mock.Anything).Return(fmt.Errorf("pop")) - _, err := NewEventManager(context.Background(), "ns1", mni, mpi, mdi, mbi, mim, msh, mdm, mbm, mpm, mam, msd, mm, txHelper, events, mmp) + _, err := NewEventManager(context.Background(), "ns1", mni, mpi, mdi, mbi, mim, msh, mdm, mds, mbm, mpm, mam, msd, mm, txHelper, events, mmp) assert.EqualError(t, err, "pop") } diff --git a/internal/events/token_pool_created.go b/internal/events/token_pool_created.go index 3ebd5e7a6..5d07dd3a3 100644 --- a/internal/events/token_pool_created.go +++ b/internal/events/token_pool_created.go @@ -195,7 +195,7 @@ func (em *eventManager) TokenPoolCreated(ti tokens.Plugin, pool *tokens.TokenPoo Pool: announcePool, } log.L(em.ctx).Infof("Announcing token pool, id=%s", announcePool.ID) - _, err = em.broadcast.BroadcastTokenPool(em.ctx, broadcast, false) + _, err = em.defsender.BroadcastTokenPool(em.ctx, broadcast, false) } } diff --git a/internal/events/token_pool_created_test.go b/internal/events/token_pool_created_test.go index d42d57c8a..27dbc1244 100644 --- a/internal/events/token_pool_created_test.go +++ b/internal/events/token_pool_created_test.go @@ -22,9 +22,9 @@ import ( "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/mocks/assetmocks" - "github.com/hyperledger/firefly/mocks/broadcastmocks" "github.com/hyperledger/firefly/mocks/databasemocks" "github.com/hyperledger/firefly/mocks/datamocks" + "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/mocks/tokenmocks" "github.com/hyperledger/firefly/mocks/txcommonmocks" "github.com/hyperledger/firefly/pkg/blockchain" @@ -472,7 +472,7 @@ func TestTokenPoolCreatedAnnounce(t *testing.T) { defer cancel() mdi := em.database.(*databasemocks.Plugin) mti := &tokenmocks.Plugin{} - mbm := em.broadcast.(*broadcastmocks.Manager) + mds := em.defsender.(*defsendermocks.Sender) poolID := fftypes.NewUUID() txID := fftypes.NewUUID() @@ -505,7 +505,7 @@ func TestTokenPoolCreatedAnnounce(t *testing.T) { mdi.On("GetTokenPoolByLocator", em.ctx, "ns1", "erc1155", "123").Return(nil, nil).Times(2) mdi.On("GetOperations", em.ctx, "ns1", mock.Anything).Return(nil, nil, fmt.Errorf("pop")).Once() mdi.On("GetOperations", em.ctx, "ns1", mock.Anything).Return(operations, nil, nil).Once() - mbm.On("BroadcastTokenPool", em.ctx, mock.MatchedBy(func(pool *core.TokenPoolAnnouncement) bool { + mds.On("BroadcastTokenPool", em.ctx, mock.MatchedBy(func(pool *core.TokenPoolAnnouncement) bool { return pool.Pool.Namespace == "ns1" && pool.Pool.Name == "my-pool" && *pool.Pool.ID == *poolID }), false).Return(nil, nil) @@ -514,7 +514,7 @@ func TestTokenPoolCreatedAnnounce(t *testing.T) { mti.AssertExpectations(t) mdi.AssertExpectations(t) - mbm.AssertExpectations(t) + mds.AssertExpectations(t) } func TestTokenPoolCreatedAnnounceWrongNS(t *testing.T) { diff --git a/internal/networkmap/manager.go b/internal/networkmap/manager.go index 0f7881e41..3b4208b14 100644 --- a/internal/networkmap/manager.go +++ b/internal/networkmap/manager.go @@ -20,8 +20,8 @@ import ( "context" "github.com/hyperledger/firefly-common/pkg/i18n" - "github.com/hyperledger/firefly/internal/broadcast" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/defsender" "github.com/hyperledger/firefly/internal/identity" "github.com/hyperledger/firefly/internal/multiparty" "github.com/hyperledger/firefly/internal/syncasync" @@ -59,15 +59,15 @@ type networkMap struct { ctx context.Context namespace string database database.Plugin - broadcast broadcast.Manager + defsender defsender.Sender exchange dataexchange.Plugin identity identity.Manager syncasync syncasync.Bridge multiparty multiparty.Manager } -func NewNetworkMap(ctx context.Context, ns string, di database.Plugin, dx dataexchange.Plugin, bm broadcast.Manager, im identity.Manager, sa syncasync.Bridge, mm multiparty.Manager) (Manager, error) { - if di == nil || bm == nil || dx == nil || im == nil || mm == nil { +func NewNetworkMap(ctx context.Context, ns string, di database.Plugin, dx dataexchange.Plugin, ds defsender.Sender, im identity.Manager, sa syncasync.Bridge, mm multiparty.Manager) (Manager, error) { + if di == nil || ds == nil || dx == nil || im == nil || mm == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "NetworkMap") } @@ -75,7 +75,7 @@ func NewNetworkMap(ctx context.Context, ns string, di database.Plugin, dx dataex ctx: ctx, namespace: ns, database: di, - broadcast: bm, + defsender: ds, exchange: dx, identity: im, syncasync: sa, diff --git a/internal/networkmap/manager_test.go b/internal/networkmap/manager_test.go index 8dad0170b..48c031395 100644 --- a/internal/networkmap/manager_test.go +++ b/internal/networkmap/manager_test.go @@ -21,9 +21,9 @@ import ( "testing" "github.com/hyperledger/firefly/internal/coreconfig" - "github.com/hyperledger/firefly/mocks/broadcastmocks" "github.com/hyperledger/firefly/mocks/databasemocks" "github.com/hyperledger/firefly/mocks/dataexchangemocks" + "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/mocks/multipartymocks" "github.com/hyperledger/firefly/mocks/syncasyncmocks" @@ -34,12 +34,12 @@ func newTestNetworkmap(t *testing.T) (*networkMap, func()) { coreconfig.Reset() ctx, cancel := context.WithCancel(context.Background()) mdi := &databasemocks.Plugin{} - mbm := &broadcastmocks.Manager{} + mds := &defsendermocks.Sender{} mdx := &dataexchangemocks.Plugin{} mim := &identitymanagermocks.Manager{} msa := &syncasyncmocks.Bridge{} mmp := &multipartymocks.Manager{} - nm, err := NewNetworkMap(ctx, "ns1", mdi, mdx, mbm, mim, msa, mmp) + nm, err := NewNetworkMap(ctx, "ns1", mdi, mdx, mds, mim, msa, mmp) assert.NoError(t, err) return nm.(*networkMap), cancel diff --git a/internal/networkmap/register_identity.go b/internal/networkmap/register_identity.go index b7af67975..cc0376a2b 100644 --- a/internal/networkmap/register_identity.go +++ b/internal/networkmap/register_identity.go @@ -109,7 +109,7 @@ func (nm *networkMap) RegisterIdentity(ctx context.Context, dto *core.IdentityCr func (nm *networkMap) sendIdentityRequest(ctx context.Context, identity *core.Identity, claimSigner *core.SignerRef, parentSigner *core.SignerRef) error { // Send the claim - we disable the check on the DID author here, as we are registering the identity so it will not exist - claimMsg, err := nm.broadcast.BroadcastIdentityClaim(ctx, &core.IdentityClaim{ + claimMsg, err := nm.defsender.BroadcastIdentityClaim(ctx, &core.IdentityClaim{ Identity: identity, }, claimSigner, core.SystemTagIdentityClaim, false) if err != nil { @@ -119,7 +119,7 @@ func (nm *networkMap) sendIdentityRequest(ctx context.Context, identity *core.Id // Send the verification if one is required. if parentSigner != nil { - verifyMsg, err := nm.broadcast.BroadcastDefinition(ctx, &core.IdentityVerification{ + verifyMsg, err := nm.defsender.BroadcastDefinition(ctx, &core.IdentityVerification{ Claim: core.MessageRef{ ID: claimMsg.Header.ID, Hash: claimMsg.Hash, diff --git a/internal/networkmap/register_identity_test.go b/internal/networkmap/register_identity_test.go index e9f51569c..ff00bd673 100644 --- a/internal/networkmap/register_identity_test.go +++ b/internal/networkmap/register_identity_test.go @@ -23,7 +23,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/syncasync" - "github.com/hyperledger/firefly/mocks/broadcastmocks" + "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/mocks/syncasyncmocks" "github.com/hyperledger/firefly/pkg/core" @@ -46,16 +46,16 @@ func TestRegisterIdentityOrgWithParentOk(t *testing.T) { mockMsg1 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mockMsg2 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mbm := nm.broadcast.(*broadcastmocks.Manager) + mds := nm.defsender.(*defsendermocks.Sender) - mbm.On("BroadcastIdentityClaim", nm.ctx, + mds.On("BroadcastIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" }), core.SystemTagIdentityClaim, false).Return(mockMsg1, nil) - mbm.On("BroadcastDefinition", nm.ctx, + mds.On("BroadcastDefinition", nm.ctx, mock.AnythingOfType("*core.IdentityVerification"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x23456" @@ -72,7 +72,7 @@ func TestRegisterIdentityOrgWithParentOk(t *testing.T) { assert.Equal(t, *mockMsg2.Header.ID, *org.Messages.Verification) mim.AssertExpectations(t) - mbm.AssertExpectations(t) + mds.AssertExpectations(t) } func TestRegisterIdentityOrgWithParentWaitConfirmOk(t *testing.T) { @@ -100,16 +100,16 @@ func TestRegisterIdentityOrgWithParentWaitConfirmOk(t *testing.T) { mockMsg1 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mockMsg2 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mbm := nm.broadcast.(*broadcastmocks.Manager) + mds := nm.defsender.(*defsendermocks.Sender) - mbm.On("BroadcastIdentityClaim", nm.ctx, + mds.On("BroadcastIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" }), core.SystemTagIdentityClaim, false).Return(mockMsg1, nil) - mbm.On("BroadcastDefinition", nm.ctx, + mds.On("BroadcastDefinition", nm.ctx, mock.AnythingOfType("*core.IdentityVerification"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x23456" @@ -124,7 +124,7 @@ func TestRegisterIdentityOrgWithParentWaitConfirmOk(t *testing.T) { assert.NoError(t, err) mim.AssertExpectations(t) - mbm.AssertExpectations(t) + mds.AssertExpectations(t) msa.AssertExpectations(t) } @@ -148,16 +148,16 @@ func TestRegisterIdentityCustomWithParentFail(t *testing.T) { }, nil) mockMsg := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mbm := nm.broadcast.(*broadcastmocks.Manager) + mds := nm.defsender.(*defsendermocks.Sender) - mbm.On("BroadcastIdentityClaim", nm.ctx, + mds.On("BroadcastIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" }), core.SystemTagIdentityClaim, false).Return(mockMsg, nil) - mbm.On("BroadcastDefinition", nm.ctx, + mds.On("BroadcastDefinition", nm.ctx, mock.AnythingOfType("*core.IdentityVerification"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x23456" @@ -172,7 +172,7 @@ func TestRegisterIdentityCustomWithParentFail(t *testing.T) { assert.Regexp(t, "pop", err) mim.AssertExpectations(t) - mbm.AssertExpectations(t) + mds.AssertExpectations(t) } func TestRegisterIdentityGetParentMsgFail(t *testing.T) { @@ -204,8 +204,8 @@ func TestRegisterIdentityRootBroadcastFail(t *testing.T) { mim := nm.identity.(*identitymanagermocks.Manager) mim.On("VerifyIdentityChain", nm.ctx, mock.AnythingOfType("*core.Identity")).Return(nil, false, nil) - mbm := nm.broadcast.(*broadcastmocks.Manager) - mbm.On("BroadcastIdentityClaim", nm.ctx, + mds := nm.defsender.(*defsendermocks.Sender) + mds.On("BroadcastIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" @@ -220,7 +220,7 @@ func TestRegisterIdentityRootBroadcastFail(t *testing.T) { assert.Regexp(t, "pop", err) mim.AssertExpectations(t) - mbm.AssertExpectations(t) + mds.AssertExpectations(t) } func TestRegisterIdentityMissingKey(t *testing.T) { diff --git a/internal/networkmap/register_node_test.go b/internal/networkmap/register_node_test.go index 4ae4c28a0..666ccc2a5 100644 --- a/internal/networkmap/register_node_test.go +++ b/internal/networkmap/register_node_test.go @@ -23,8 +23,8 @@ import ( "github.com/hyperledger/firefly-common/pkg/config" "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/coreconfig" - "github.com/hyperledger/firefly/mocks/broadcastmocks" "github.com/hyperledger/firefly/mocks/dataexchangemocks" + "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" @@ -55,8 +55,8 @@ func TestRegisterNodeOk(t *testing.T) { }, nil) mockMsg := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mbm := nm.broadcast.(*broadcastmocks.Manager) - mbm.On("BroadcastIdentityClaim", nm.ctx, + mds := nm.defsender.(*defsendermocks.Sender) + mds.On("BroadcastIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), signerRef, core.SystemTagIdentityClaim, false).Return(mockMsg, nil) @@ -67,7 +67,7 @@ func TestRegisterNodeOk(t *testing.T) { mim.AssertExpectations(t) mdx.AssertExpectations(t) - mbm.AssertExpectations(t) + mds.AssertExpectations(t) } func TestRegisterNodePeerInfoFail(t *testing.T) { diff --git a/internal/networkmap/register_org_test.go b/internal/networkmap/register_org_test.go index 8a8ccc801..b932a24e8 100644 --- a/internal/networkmap/register_org_test.go +++ b/internal/networkmap/register_org_test.go @@ -23,7 +23,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/multiparty" - "github.com/hyperledger/firefly/mocks/broadcastmocks" + "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/mocks/multipartymocks" "github.com/hyperledger/firefly/pkg/core" @@ -68,8 +68,8 @@ func TestRegisterNodeOrgOk(t *testing.T) { mmp.On("RootOrg").Return(multiparty.RootOrg{Name: "org0"}) mockMsg := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mbm := nm.broadcast.(*broadcastmocks.Manager) - mbm.On("BroadcastIdentityClaim", nm.ctx, + mds := nm.defsender.(*defsendermocks.Sender) + mds.On("BroadcastIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" @@ -81,7 +81,7 @@ func TestRegisterNodeOrgOk(t *testing.T) { assert.Equal(t, *mockMsg.Header.ID, *org.Messages.Claim) mim.AssertExpectations(t) - mbm.AssertExpectations(t) + mds.AssertExpectations(t) mmp.AssertExpectations(t) } diff --git a/internal/networkmap/update_identity.go b/internal/networkmap/update_identity.go index 6e0d6d741..a0541c5e8 100644 --- a/internal/networkmap/update_identity.go +++ b/internal/networkmap/update_identity.go @@ -56,7 +56,7 @@ func (nm *networkMap) updateIdentityID(ctx context.Context, id *fftypes.UUID, dt } // Send the update - updateMsg, err := nm.broadcast.BroadcastDefinition(ctx, &core.IdentityUpdate{ + updateMsg, err := nm.defsender.BroadcastDefinition(ctx, &core.IdentityUpdate{ Identity: identity.IdentityBase, Updates: dto.IdentityProfile, }, updateSigner, core.SystemTagIdentityUpdate, waitConfirm) diff --git a/internal/networkmap/update_identity_test.go b/internal/networkmap/update_identity_test.go index 593bb1df6..bfa9e02cd 100644 --- a/internal/networkmap/update_identity_test.go +++ b/internal/networkmap/update_identity_test.go @@ -21,7 +21,7 @@ import ( "testing" "github.com/hyperledger/firefly-common/pkg/fftypes" - "github.com/hyperledger/firefly/mocks/broadcastmocks" + "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" @@ -41,9 +41,9 @@ func TestUpdateIdentityProfileOk(t *testing.T) { mim.On("ResolveIdentitySigner", nm.ctx, identity).Return(signerRef, nil) mockMsg1 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mbm := nm.broadcast.(*broadcastmocks.Manager) + mds := nm.defsender.(*defsendermocks.Sender) - mbm.On("BroadcastDefinition", nm.ctx, + mds.On("BroadcastDefinition", nm.ctx, mock.AnythingOfType("*core.IdentityUpdate"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" @@ -60,7 +60,7 @@ func TestUpdateIdentityProfileOk(t *testing.T) { assert.Equal(t, *mockMsg1.Header.ID, *org.Messages.Update) mim.AssertExpectations(t) - mbm.AssertExpectations(t) + mds.AssertExpectations(t) } func TestUpdateIdentityProfileBroadcastFail(t *testing.T) { @@ -75,8 +75,8 @@ func TestUpdateIdentityProfileBroadcastFail(t *testing.T) { signerRef := &core.SignerRef{Key: "0x12345"} mim.On("ResolveIdentitySigner", nm.ctx, identity).Return(signerRef, nil) - mbm := nm.broadcast.(*broadcastmocks.Manager) - mbm.On("BroadcastDefinition", nm.ctx, + mds := nm.defsender.(*defsendermocks.Sender) + mds.On("BroadcastDefinition", nm.ctx, mock.AnythingOfType("*core.IdentityUpdate"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" @@ -92,7 +92,7 @@ func TestUpdateIdentityProfileBroadcastFail(t *testing.T) { assert.Regexp(t, "pop", err) mim.AssertExpectations(t) - mbm.AssertExpectations(t) + mds.AssertExpectations(t) } func TestUpdateIdentityProfileBadProfile(t *testing.T) { diff --git a/internal/orchestrator/orchestrator.go b/internal/orchestrator/orchestrator.go index 5957c1d30..75b709c35 100644 --- a/internal/orchestrator/orchestrator.go +++ b/internal/orchestrator/orchestrator.go @@ -27,6 +27,7 @@ import ( "github.com/hyperledger/firefly/internal/contracts" "github.com/hyperledger/firefly/internal/data" "github.com/hyperledger/firefly/internal/definitions" + "github.com/hyperledger/firefly/internal/defsender" "github.com/hyperledger/firefly/internal/events" "github.com/hyperledger/firefly/internal/identity" "github.com/hyperledger/firefly/internal/metrics" @@ -55,6 +56,7 @@ type Orchestrator interface { Assets() assets.Manager BatchManager() batch.Manager Broadcast() broadcast.Manager + DefinitionSender() defsender.Sender Contracts() contracts.Manager MultiParty() multiparty.Manager Data() data.Manager @@ -172,7 +174,8 @@ type orchestrator struct { batch batch.Manager broadcast broadcast.Manager messaging privatemessaging.Manager - definitions definitions.DefinitionHandler + defhandler definitions.DefinitionHandler + defsender defsender.Sender data data.Manager syncasync syncasync.Bridge assets assets.Manager @@ -318,6 +321,10 @@ func (or *orchestrator) PrivateMessaging() privatemessaging.Manager { return or.messaging } +func (or *orchestrator) DefinitionSender() defsender.Sender { + return or.defsender +} + func (or *orchestrator) Events() events.EventManager { return or.events } @@ -378,14 +385,7 @@ func (or *orchestrator) initPlugins(ctx context.Context) (err error) { return nil } -func (or *orchestrator) initComponents(ctx context.Context) (err error) { - - if or.data == nil { - or.data, err = data.NewDataManager(ctx, or.namespace, or.database(), or.sharedstorage(), or.dataexchange()) - if err != nil { - return err - } - } +func (or *orchestrator) initManagers(ctx context.Context) (err error) { if or.txHelper == nil { or.txHelper = txcommon.NewTransactionHelper(or.namespace, or.database(), or.data) @@ -432,8 +432,18 @@ func (or *orchestrator) initComponents(ctx context.Context) (err error) { } } + if or.defsender == nil { + or.defsender, err = defsender.NewDefinitionSender(ctx, or.namespace, or.broadcast, or.identity, or.data) + if err != nil { + return err + } + } + if or.networkmap == nil { - or.networkmap, err = networkmap.NewNetworkMap(ctx, or.namespace, or.database(), or.dataexchange(), or.broadcast, or.identity, or.syncasync, or.multiparty) + or.networkmap, err = networkmap.NewNetworkMap(ctx, or.namespace, or.database(), or.dataexchange(), or.defsender, or.identity, or.syncasync, or.multiparty) + if err != nil { + return err + } } if or.assets == nil { @@ -444,35 +454,59 @@ func (or *orchestrator) initComponents(ctx context.Context) (err error) { } if or.contracts == nil { - or.contracts, err = contracts.NewContractManager(ctx, or.namespace, or.database(), or.blockchain(), or.broadcast, or.identity, or.operations, or.txHelper, or.syncasync) + or.contracts, err = contracts.NewContractManager(ctx, or.namespace, or.database(), or.blockchain(), or.defsender, or.identity, or.operations, or.txHelper, or.syncasync) if err != nil { return err } } - if or.definitions == nil { - or.definitions, err = definitions.NewDefinitionHandler(ctx, or.namespace, or.database(), or.blockchain(), or.dataexchange(), or.data, or.identity, or.assets, or.contracts) + if or.sharedDownload == nil { + or.sharedDownload, err = shareddownload.NewDownloadManager(ctx, or.namespace, or.database(), or.sharedstorage(), or.dataexchange(), or.operations, &or.bc) if err != nil { return err } } - if or.sharedDownload == nil { - or.sharedDownload, err = shareddownload.NewDownloadManager(ctx, or.namespace, or.database(), or.sharedstorage(), or.dataexchange(), or.operations, &or.bc) + return nil +} + +func (or *orchestrator) initHandlers(ctx context.Context) (err error) { + if or.defhandler == nil { + or.defhandler, err = definitions.NewDefinitionHandler(ctx, or.namespace, or.database(), or.blockchain(), or.dataexchange(), or.data, or.identity, or.assets, or.contracts) if err != nil { return err } } if or.events == nil { - or.events, err = events.NewEventManager(ctx, or.namespace, or, or.sharedstorage(), or.database(), or.blockchain(), or.identity, or.definitions, or.data, or.broadcast, or.messaging, or.assets, or.sharedDownload, or.metrics, or.txHelper, or.plugins.Events, or.multiparty) + or.events, err = events.NewEventManager(ctx, or.namespace, or, or.sharedstorage(), or.database(), or.blockchain(), or.identity, or.defhandler, or.data, or.defsender, or.broadcast, or.messaging, or.assets, or.sharedDownload, or.metrics, or.txHelper, or.plugins.Events, or.multiparty) + if err != nil { + return err + } + } + + return nil +} + +func (or *orchestrator) initComponents(ctx context.Context) (err error) { + if or.data == nil { + or.data, err = data.NewDataManager(ctx, or.namespace, or.database(), or.sharedstorage(), or.dataexchange()) if err != nil { return err } } + if err := or.initManagers(ctx); err != nil { + return err + } + + if err := or.initHandlers(ctx); err != nil { + return err + } + or.syncasync.Init(or.events) - return err + + return nil } func (or *orchestrator) SubmitNetworkAction(ctx context.Context, action *core.NetworkAction) error { diff --git a/internal/orchestrator/orchestrator_test.go b/internal/orchestrator/orchestrator_test.go index 5a255f9ce..c8abc8053 100644 --- a/internal/orchestrator/orchestrator_test.go +++ b/internal/orchestrator/orchestrator_test.go @@ -32,6 +32,7 @@ import ( "github.com/hyperledger/firefly/mocks/dataexchangemocks" "github.com/hyperledger/firefly/mocks/datamocks" "github.com/hyperledger/firefly/mocks/definitionsmocks" + "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/mocks/eventmocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/mocks/identitymocks" @@ -77,6 +78,7 @@ type testOrchestrator struct { mae *spieventsmocks.Manager mdh *definitionsmocks.DefinitionHandler mmp *multipartymocks.Manager + mds *defsendermocks.Sender } func (tor *testOrchestrator) cleanup(t *testing.T) { @@ -135,6 +137,7 @@ func newTestOrchestrator() *testOrchestrator { mae: &spieventsmocks.Manager{}, mdh: &definitionsmocks.DefinitionHandler{}, mmp: &multipartymocks.Manager{}, + mds: &defsendermocks.Sender{}, } tor.orchestrator.multiparty = tor.mmp tor.orchestrator.data = tor.mdm @@ -150,7 +153,8 @@ func newTestOrchestrator() *testOrchestrator { tor.orchestrator.operations = tor.mom tor.orchestrator.sharedDownload = tor.msd tor.orchestrator.txHelper = tor.mth - tor.orchestrator.definitions = tor.mdh + tor.orchestrator.defhandler = tor.mdh + tor.orchestrator.defsender = tor.mds tor.orchestrator.plugins.Blockchain.Plugin = tor.mbi tor.orchestrator.plugins.SharedStorage.Plugin = tor.mps tor.orchestrator.plugins.DataExchange.Plugin = tor.mdx @@ -199,6 +203,7 @@ func TestInitOK(t *testing.T) { assert.Equal(t, or.mba, or.BatchManager()) assert.Equal(t, or.mbm, or.Broadcast()) assert.Equal(t, or.mpm, or.PrivateMessaging()) + assert.Equal(t, or.mds, or.DefinitionSender()) assert.Equal(t, or.mem, or.Events()) assert.Equal(t, or.mam, or.Assets()) assert.Equal(t, or.mdm, or.Data()) @@ -297,6 +302,15 @@ func TestInitBroadcastComponentFail(t *testing.T) { assert.Regexp(t, "FF10128", err) } +func TestInitDefSenderComponentFail(t *testing.T) { + or := newTestOrchestrator() + defer or.cleanup(t) + or.data = nil + or.defsender = nil + err := or.initManagers(context.Background()) + assert.Regexp(t, "FF10128", err) +} + func TestInitDataComponentFail(t *testing.T) { or := newTestOrchestrator() defer or.cleanup(t) @@ -337,7 +351,7 @@ func TestInitDefinitionsComponentFail(t *testing.T) { or := newTestOrchestrator() defer or.cleanup(t) or.plugins.Database.Plugin = nil - or.definitions = nil + or.defhandler = nil err := or.initComponents(context.Background()) assert.Regexp(t, "FF10128", err) } diff --git a/mocks/broadcastmocks/manager.go b/mocks/broadcastmocks/manager.go index 522802d6e..4c778b984 100644 --- a/mocks/broadcastmocks/manager.go +++ b/mocks/broadcastmocks/manager.go @@ -18,98 +18,6 @@ type Manager struct { mock.Mock } -// BroadcastDatatype provides a mock function with given fields: ctx, datatype, waitConfirm -func (_m *Manager) BroadcastDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (*core.Message, error) { - ret := _m.Called(ctx, datatype, waitConfirm) - - var r0 *core.Message - if rf, ok := ret.Get(0).(func(context.Context, *core.Datatype, bool) *core.Message); ok { - r0 = rf(ctx, datatype, waitConfirm) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*core.Message) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *core.Datatype, bool) error); ok { - r1 = rf(ctx, datatype, waitConfirm) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// BroadcastDefinition provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm -func (_m *Manager) BroadcastDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { - ret := _m.Called(ctx, def, signingIdentity, tag, waitConfirm) - - var r0 *core.Message - if rf, ok := ret.Get(0).(func(context.Context, core.Definition, *core.SignerRef, string, bool) *core.Message); ok { - r0 = rf(ctx, def, signingIdentity, tag, waitConfirm) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*core.Message) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, core.Definition, *core.SignerRef, string, bool) error); ok { - r1 = rf(ctx, def, signingIdentity, tag, waitConfirm) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// BroadcastDefinitionAsNode provides a mock function with given fields: ctx, def, tag, waitConfirm -func (_m *Manager) BroadcastDefinitionAsNode(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (*core.Message, error) { - ret := _m.Called(ctx, def, tag, waitConfirm) - - var r0 *core.Message - if rf, ok := ret.Get(0).(func(context.Context, core.Definition, string, bool) *core.Message); ok { - r0 = rf(ctx, def, tag, waitConfirm) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*core.Message) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, core.Definition, string, bool) error); ok { - r1 = rf(ctx, def, tag, waitConfirm) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// BroadcastIdentityClaim provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm -func (_m *Manager) BroadcastIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { - ret := _m.Called(ctx, def, signingIdentity, tag, waitConfirm) - - var r0 *core.Message - if rf, ok := ret.Get(0).(func(context.Context, *core.IdentityClaim, *core.SignerRef, string, bool) *core.Message); ok { - r0 = rf(ctx, def, signingIdentity, tag, waitConfirm) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*core.Message) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *core.IdentityClaim, *core.SignerRef, string, bool) error); ok { - r1 = rf(ctx, def, signingIdentity, tag, waitConfirm) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // BroadcastMessage provides a mock function with given fields: ctx, in, waitConfirm func (_m *Manager) BroadcastMessage(ctx context.Context, in *core.MessageInOut, waitConfirm bool) (*core.Message, error) { ret := _m.Called(ctx, in, waitConfirm) @@ -133,29 +41,6 @@ func (_m *Manager) BroadcastMessage(ctx context.Context, in *core.MessageInOut, return r0, r1 } -// BroadcastTokenPool provides a mock function with given fields: ctx, pool, waitConfirm -func (_m *Manager) BroadcastTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (*core.Message, error) { - ret := _m.Called(ctx, pool, waitConfirm) - - var r0 *core.Message - if rf, ok := ret.Get(0).(func(context.Context, *core.TokenPoolAnnouncement, bool) *core.Message); ok { - r0 = rf(ctx, pool, waitConfirm) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*core.Message) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *core.TokenPoolAnnouncement, bool) error); ok { - r1 = rf(ctx, pool, waitConfirm) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // Name provides a mock function with given fields: func (_m *Manager) Name() string { ret := _m.Called() diff --git a/mocks/defsendermocks/sender.go b/mocks/defsendermocks/sender.go new file mode 100644 index 000000000..7f440c127 --- /dev/null +++ b/mocks/defsendermocks/sender.go @@ -0,0 +1,145 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package defsendermocks + +import ( + context "context" + + core "github.com/hyperledger/firefly/pkg/core" + + mock "github.com/stretchr/testify/mock" +) + +// Sender is an autogenerated mock type for the Sender type +type Sender struct { + mock.Mock +} + +// BroadcastDatatype provides a mock function with given fields: ctx, datatype, waitConfirm +func (_m *Sender) BroadcastDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (*core.Message, error) { + ret := _m.Called(ctx, datatype, waitConfirm) + + var r0 *core.Message + if rf, ok := ret.Get(0).(func(context.Context, *core.Datatype, bool) *core.Message); ok { + r0 = rf(ctx, datatype, waitConfirm) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*core.Message) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *core.Datatype, bool) error); ok { + r1 = rf(ctx, datatype, waitConfirm) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BroadcastDefinition provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm +func (_m *Sender) BroadcastDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { + ret := _m.Called(ctx, def, signingIdentity, tag, waitConfirm) + + var r0 *core.Message + if rf, ok := ret.Get(0).(func(context.Context, core.Definition, *core.SignerRef, string, bool) *core.Message); ok { + r0 = rf(ctx, def, signingIdentity, tag, waitConfirm) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*core.Message) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, core.Definition, *core.SignerRef, string, bool) error); ok { + r1 = rf(ctx, def, signingIdentity, tag, waitConfirm) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BroadcastDefinitionAsNode provides a mock function with given fields: ctx, def, tag, waitConfirm +func (_m *Sender) BroadcastDefinitionAsNode(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (*core.Message, error) { + ret := _m.Called(ctx, def, tag, waitConfirm) + + var r0 *core.Message + if rf, ok := ret.Get(0).(func(context.Context, core.Definition, string, bool) *core.Message); ok { + r0 = rf(ctx, def, tag, waitConfirm) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*core.Message) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, core.Definition, string, bool) error); ok { + r1 = rf(ctx, def, tag, waitConfirm) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BroadcastIdentityClaim provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm +func (_m *Sender) BroadcastIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { + ret := _m.Called(ctx, def, signingIdentity, tag, waitConfirm) + + var r0 *core.Message + if rf, ok := ret.Get(0).(func(context.Context, *core.IdentityClaim, *core.SignerRef, string, bool) *core.Message); ok { + r0 = rf(ctx, def, signingIdentity, tag, waitConfirm) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*core.Message) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *core.IdentityClaim, *core.SignerRef, string, bool) error); ok { + r1 = rf(ctx, def, signingIdentity, tag, waitConfirm) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BroadcastTokenPool provides a mock function with given fields: ctx, pool, waitConfirm +func (_m *Sender) BroadcastTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (*core.Message, error) { + ret := _m.Called(ctx, pool, waitConfirm) + + var r0 *core.Message + if rf, ok := ret.Get(0).(func(context.Context, *core.TokenPoolAnnouncement, bool) *core.Message); ok { + r0 = rf(ctx, pool, waitConfirm) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*core.Message) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *core.TokenPoolAnnouncement, bool) error); ok { + r1 = rf(ctx, pool, waitConfirm) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Name provides a mock function with given fields: +func (_m *Sender) Name() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} diff --git a/mocks/orchestratormocks/orchestrator.go b/mocks/orchestratormocks/orchestrator.go index c31c137a2..36364dbc6 100644 --- a/mocks/orchestratormocks/orchestrator.go +++ b/mocks/orchestratormocks/orchestrator.go @@ -18,6 +18,8 @@ import ( database "github.com/hyperledger/firefly/pkg/database" + defsender "github.com/hyperledger/firefly/internal/defsender" + events "github.com/hyperledger/firefly/internal/events" mock "github.com/stretchr/testify/mock" @@ -162,6 +164,22 @@ func (_m *Orchestrator) Data() data.Manager { return r0 } +// DefinitionSender provides a mock function with given fields: +func (_m *Orchestrator) DefinitionSender() defsender.Sender { + ret := _m.Called() + + var r0 defsender.Sender + if rf, ok := ret.Get(0).(func() defsender.Sender); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(defsender.Sender) + } + } + + return r0 +} + // DeleteSubscription provides a mock function with given fields: ctx, id func (_m *Orchestrator) DeleteSubscription(ctx context.Context, id string) error { ret := _m.Called(ctx, id) From 0312f18d1fd627f9bc0d0a75ebdd430f8aba44e6 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Wed, 11 May 2022 15:46:36 -0400 Subject: [PATCH 02/27] Rename "Broadcast" methods of Definition Sender to "Create" Signed-off-by: Andrew Richardson --- internal/apiserver/route_post_new_datatype.go | 2 +- .../apiserver/route_post_new_datatype_test.go | 4 +- internal/contracts/manager.go | 4 +- internal/contracts/manager_test.go | 16 ++++---- internal/defsender/datatype.go | 4 +- internal/defsender/datatype_test.go | 12 +++--- internal/defsender/sender.go | 20 +++++----- internal/defsender/sender_test.go | 20 +++++----- internal/defsender/tokenpool.go | 4 +- internal/defsender/tokenpool_test.go | 6 +-- internal/events/token_pool_created.go | 2 +- internal/events/token_pool_created_test.go | 2 +- internal/networkmap/register_identity.go | 4 +- internal/networkmap/register_identity_test.go | 14 +++---- internal/networkmap/register_node_test.go | 2 +- internal/networkmap/register_org_test.go | 2 +- internal/networkmap/update_identity.go | 2 +- internal/networkmap/update_identity_test.go | 4 +- mocks/defsendermocks/sender.go | 40 +++++++++---------- 19 files changed, 82 insertions(+), 82 deletions(-) diff --git a/internal/apiserver/route_post_new_datatype.go b/internal/apiserver/route_post_new_datatype.go index 2e0cbd0ee..328c55b44 100644 --- a/internal/apiserver/route_post_new_datatype.go +++ b/internal/apiserver/route_post_new_datatype.go @@ -41,7 +41,7 @@ var postNewDatatype = &ffapi.Route{ CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) - _, err = cr.or.DefinitionSender().BroadcastDatatype(cr.ctx, r.Input.(*core.Datatype), waitConfirm) + _, err = cr.or.DefinitionSender().CreateDatatype(cr.ctx, r.Input.(*core.Datatype), waitConfirm) return r.Input, err }, }, diff --git a/internal/apiserver/route_post_new_datatype_test.go b/internal/apiserver/route_post_new_datatype_test.go index 616121b4f..58f5b21d4 100644 --- a/internal/apiserver/route_post_new_datatype_test.go +++ b/internal/apiserver/route_post_new_datatype_test.go @@ -39,7 +39,7 @@ func TestPostNewDatatypes(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mds.On("BroadcastDatatype", mock.Anything, mock.AnythingOfType("*core.Datatype"), false). + mds.On("CreateDatatype", mock.Anything, mock.AnythingOfType("*core.Datatype"), false). Return(&core.Message{}, nil) r.ServeHTTP(res, req) @@ -57,7 +57,7 @@ func TestPostNewDatatypesSync(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mds.On("BroadcastDatatype", mock.Anything, mock.AnythingOfType("*core.Datatype"), true). + mds.On("CreateDatatype", mock.Anything, mock.AnythingOfType("*core.Datatype"), true). Return(&core.Message{}, nil) r.ServeHTTP(res, req) diff --git a/internal/contracts/manager.go b/internal/contracts/manager.go index 861727306..2c7097d79 100644 --- a/internal/contracts/manager.go +++ b/internal/contracts/manager.go @@ -139,7 +139,7 @@ func (cm *contractManager) BroadcastFFI(ctx context.Context, ffi *core.FFI, wait } output = ffi - msg, err := cm.defsender.BroadcastDefinitionAsNode(ctx, ffi, core.SystemTagDefineFFI, waitConfirm) + msg, err := cm.defsender.CreateDefinition(ctx, ffi, core.SystemTagDefineFFI, waitConfirm) if err != nil { return nil, err } @@ -373,7 +373,7 @@ func (cm *contractManager) BroadcastContractAPI(ctx context.Context, httpServerU return nil, err } - msg, err := cm.defsender.BroadcastDefinitionAsNode(ctx, api, core.SystemTagDefineContractAPI, waitConfirm) + msg, err := cm.defsender.CreateDefinition(ctx, api, core.SystemTagDefineContractAPI, waitConfirm) if err != nil { return nil, err } diff --git a/internal/contracts/manager_test.go b/internal/contracts/manager_test.go index a7324abce..5af03db1e 100644 --- a/internal/contracts/manager_test.go +++ b/internal/contracts/manager_test.go @@ -119,7 +119,7 @@ func TestBroadcastFFI(t *testing.T) { ID: fftypes.NewUUID(), }, } - mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) + mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) ffi := &core.FFI{ Name: "test", Version: "1.0.0", @@ -153,7 +153,7 @@ func TestBroadcastFFIInvalid(t *testing.T) { ID: fftypes.NewUUID(), }, } - mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) + mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) ffi := &core.FFI{ Name: "test", Version: "1.0.0", @@ -186,7 +186,7 @@ func TestBroadcastFFIExists(t *testing.T) { ID: fftypes.NewUUID(), }, } - mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) + mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) ffi := &core.FFI{ Name: "test", Version: "1.0.0", @@ -205,7 +205,7 @@ func TestBroadcastFFIFail(t *testing.T) { mdb.On("GetFFI", mock.Anything, "ns1", "test", "1.0.0").Return(nil, nil) mim.On("GetOrgKey", mock.Anything).Return("key", nil) - mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(nil, fmt.Errorf("pop")) + mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(nil, fmt.Errorf("pop")) ffi := &core.FFI{ Name: "test", Version: "1.0.0", @@ -1946,7 +1946,7 @@ func TestBroadcastContractAPI(t *testing.T) { mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) mdb.On("GetFFIByID", mock.Anything, "ns1", api.Interface.ID).Return(&core.FFI{}, nil) - mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) + mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) api, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) @@ -2017,7 +2017,7 @@ func TestBroadcastContractAPIExisting(t *testing.T) { mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(existing, nil) mdb.On("GetFFIByID", mock.Anything, "ns1", api.Interface.ID).Return(&core.FFI{}, nil) - mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) + mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) @@ -2090,7 +2090,7 @@ func TestBroadcastContractAPIInterfaceName(t *testing.T) { mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) mdb.On("GetFFI", mock.Anything, "ns1", "my-ffi", "1").Return(&core.FFI{ID: interfaceID}, nil) - mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) + mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) @@ -2121,7 +2121,7 @@ func TestBroadcastContractAPIFail(t *testing.T) { mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) mdb.On("GetFFIByID", mock.Anything, "ns1", api.Interface.ID).Return(&core.FFI{}, nil) - mds.On("BroadcastDefinitionAsNode", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(nil, fmt.Errorf("pop")) + mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(nil, fmt.Errorf("pop")) _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) diff --git a/internal/defsender/datatype.go b/internal/defsender/datatype.go index a9cb7af05..a23087303 100644 --- a/internal/defsender/datatype.go +++ b/internal/defsender/datatype.go @@ -23,7 +23,7 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (bm *definitionSender) BroadcastDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (*core.Message, error) { +func (bm *definitionSender) CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (*core.Message, error) { // Validate the input data definition data datatype.ID = fftypes.NewUUID() @@ -41,7 +41,7 @@ func (bm *definitionSender) BroadcastDatatype(ctx context.Context, datatype *cor if err := bm.data.CheckDatatype(ctx, datatype); err != nil { return nil, err } - msg, err := bm.BroadcastDefinitionAsNode(ctx, datatype, core.SystemTagDefineDatatype, waitConfirm) + msg, err := bm.CreateDefinition(ctx, datatype, core.SystemTagDefineDatatype, waitConfirm) if msg != nil { datatype.Message = msg.Header.ID } diff --git a/internal/defsender/datatype_test.go b/internal/defsender/datatype_test.go index a57144b01..373469c7f 100644 --- a/internal/defsender/datatype_test.go +++ b/internal/defsender/datatype_test.go @@ -31,10 +31,10 @@ import ( "github.com/stretchr/testify/mock" ) -func TestBroadcastDatatypeBadType(t *testing.T) { +func TestCreateDatatypeBadType(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() - _, err := ds.BroadcastDatatype(context.Background(), &core.Datatype{ + _, err := ds.CreateDatatype(context.Background(), &core.Datatype{ Validator: core.ValidatorType("wrong"), }, false) assert.Regexp(t, "FF00111.*validator", err) @@ -47,7 +47,7 @@ func TestBroadcastDatatypeBadValue(t *testing.T) { mdm.On("CheckDatatype", mock.Anything, mock.Anything).Return(nil) mim := ds.identity.(*identitymanagermocks.Manager) mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) - _, err := ds.BroadcastDatatype(context.Background(), &core.Datatype{ + _, err := ds.CreateDatatype(context.Background(), &core.Datatype{ Namespace: "ns1", Name: "ent1", Version: "0.0.1", @@ -56,7 +56,7 @@ func TestBroadcastDatatypeBadValue(t *testing.T) { assert.Regexp(t, "FF10137.*value", err) } -func TestBroadcastDatatypeInvalid(t *testing.T) { +func TestCreateDatatypeInvalid(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() mdm := ds.data.(*datamocks.Manager) @@ -65,7 +65,7 @@ func TestBroadcastDatatypeInvalid(t *testing.T) { mim.On("ResolveInputIdentity", mock.Anything, mock.Anything).Return(nil) mdm.On("CheckDatatype", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - _, err := ds.BroadcastDatatype(context.Background(), &core.Datatype{ + _, err := ds.CreateDatatype(context.Background(), &core.Datatype{ Namespace: "ns1", Name: "ent1", Version: "0.0.1", @@ -87,7 +87,7 @@ func TestBroadcastOk(t *testing.T) { mbm.On("NewBroadcast", mock.Anything).Return(mms) mms.On("Send", context.Background()).Return(nil) - _, err := ds.BroadcastDatatype(context.Background(), &core.Datatype{ + _, err := ds.CreateDatatype(context.Background(), &core.Datatype{ Namespace: "ns1", Name: "ent1", Version: "0.0.1", diff --git a/internal/defsender/sender.go b/internal/defsender/sender.go index 34822fd29..eac59ecb1 100644 --- a/internal/defsender/sender.go +++ b/internal/defsender/sender.go @@ -32,11 +32,11 @@ import ( type Sender interface { core.Named - BroadcastDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (msg *core.Message, err error) - BroadcastDefinitionAsNode(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) - BroadcastDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) - BroadcastIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) - BroadcastTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (msg *core.Message, err error) + CreateDefinition(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) + CreateDefinitionWithIdentity(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) + CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (msg *core.Message, err error) + CreateIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) + CreateTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (msg *core.Message, err error) } type definitionSender struct { @@ -64,11 +64,11 @@ func (bm *definitionSender) Name() string { return "DefinitionSender" } -func (bm *definitionSender) BroadcastDefinitionAsNode(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) { - return bm.BroadcastDefinition(ctx, def, &core.SignerRef{ /* resolve to node default */ }, tag, waitConfirm) +func (bm *definitionSender) CreateDefinition(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) { + return bm.CreateDefinitionWithIdentity(ctx, def, &core.SignerRef{ /* resolve to node default */ }, tag, waitConfirm) } -func (bm *definitionSender) BroadcastDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { +func (bm *definitionSender) CreateDefinitionWithIdentity(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { err = bm.identity.ResolveInputSigningIdentity(ctx, signingIdentity) if err != nil { @@ -78,9 +78,9 @@ func (bm *definitionSender) BroadcastDefinition(ctx context.Context, def core.De return bm.broadcastDefinitionCommon(ctx, def, signingIdentity, tag, waitConfirm) } -// BroadcastIdentityClaim is a special form of BroadcastDefinitionAsNode where the signing identity does not need to have been pre-registered +// CreateIdentityClaim is a special form of CreateDefinition where the signing identity does not need to have been pre-registered // The blockchain "key" will be normalized, but the "author" will pass through unchecked -func (bm *definitionSender) BroadcastIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { +func (bm *definitionSender) CreateIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { signingIdentity.Key, err = bm.identity.NormalizeSigningKey(ctx, signingIdentity.Key, identity.KeyNormalizationBlockchainPlugin) if err != nil { diff --git a/internal/defsender/sender_test.go b/internal/defsender/sender_test.go index 1487635af..f42ea0c42 100644 --- a/internal/defsender/sender_test.go +++ b/internal/defsender/sender_test.go @@ -53,7 +53,7 @@ func TestName(t *testing.T) { assert.Equal(t, "DefinitionSender", bm.Name()) } -func TestBroadcastDefinitionAsNodeConfirm(t *testing.T) { +func TestCreateDefinitionConfirm(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() @@ -65,7 +65,7 @@ func TestBroadcastDefinitionAsNodeConfirm(t *testing.T) { mbm.On("NewBroadcast", mock.Anything).Return(mms) mms.On("SendAndWait", mock.Anything).Return(nil) - _, err := ds.BroadcastDefinitionAsNode(ds.ctx, &core.Namespace{}, core.SystemTagDefineNamespace, true) + _, err := ds.CreateDefinition(ds.ctx, &core.Namespace{}, core.SystemTagDefineNamespace, true) assert.NoError(t, err) mim.AssertExpectations(t) @@ -73,7 +73,7 @@ func TestBroadcastDefinitionAsNodeConfirm(t *testing.T) { mms.AssertExpectations(t) } -func TestBroadcastIdentityClaim(t *testing.T) { +func TestCreateIdentityClaim(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() @@ -85,7 +85,7 @@ func TestBroadcastIdentityClaim(t *testing.T) { mbm.On("NewBroadcast", mock.Anything).Return(mms) mms.On("SendAndWait", mock.Anything).Return(nil) - _, err := ds.BroadcastIdentityClaim(ds.ctx, &core.IdentityClaim{ + _, err := ds.CreateIdentityClaim(ds.ctx, &core.IdentityClaim{ Identity: &core.Identity{}, }, &core.SignerRef{ Key: "0x1234", @@ -97,7 +97,7 @@ func TestBroadcastIdentityClaim(t *testing.T) { mms.AssertExpectations(t) } -func TestBroadcastIdentityClaimFail(t *testing.T) { +func TestCreateIdentityClaimFail(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() @@ -105,7 +105,7 @@ func TestBroadcastIdentityClaimFail(t *testing.T) { mim.On("NormalizeSigningKey", mock.Anything, "0x1234", identity.KeyNormalizationBlockchainPlugin).Return("", fmt.Errorf("pop")) - _, err := ds.BroadcastIdentityClaim(ds.ctx, &core.IdentityClaim{ + _, err := ds.CreateIdentityClaim(ds.ctx, &core.IdentityClaim{ Identity: &core.Identity{}, }, &core.SignerRef{ Key: "0x1234", @@ -115,7 +115,7 @@ func TestBroadcastIdentityClaimFail(t *testing.T) { mim.AssertExpectations(t) } -func TestBroadcastDatatypeDefinitionAsNodeConfirm(t *testing.T) { +func TestCreateDatatypeDefinitionAsNodeConfirm(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() @@ -127,7 +127,7 @@ func TestBroadcastDatatypeDefinitionAsNodeConfirm(t *testing.T) { mbm.On("NewBroadcast", mock.Anything).Return(mms) mms.On("SendAndWait", mock.Anything).Return(nil) - _, err := ds.BroadcastDefinitionAsNode(ds.ctx, &core.Datatype{}, core.SystemTagDefineNamespace, true) + _, err := ds.CreateDefinition(ds.ctx, &core.Datatype{}, core.SystemTagDefineNamespace, true) assert.NoError(t, err) mim.AssertExpectations(t) @@ -135,13 +135,13 @@ func TestBroadcastDatatypeDefinitionAsNodeConfirm(t *testing.T) { mms.AssertExpectations(t) } -func TestBroadcastDefinitionBadIdentity(t *testing.T) { +func TestCreateDefinitionBadIdentity(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() mim := ds.identity.(*identitymanagermocks.Manager) mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - _, err := ds.BroadcastDefinition(ds.ctx, &core.Namespace{}, &core.SignerRef{ + _, err := ds.CreateDefinitionWithIdentity(ds.ctx, &core.Namespace{}, &core.SignerRef{ Author: "wrong", Key: "wrong", }, core.SystemTagDefineNamespace, false) diff --git a/internal/defsender/tokenpool.go b/internal/defsender/tokenpool.go index b44f76707..625c1d90e 100644 --- a/internal/defsender/tokenpool.go +++ b/internal/defsender/tokenpool.go @@ -22,12 +22,12 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (bm *definitionSender) BroadcastTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (msg *core.Message, err error) { +func (bm *definitionSender) CreateTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (msg *core.Message, err error) { if err := pool.Pool.Validate(ctx); err != nil { return nil, err } - msg, err = bm.BroadcastDefinitionAsNode(ctx, pool, core.SystemTagDefinePool, waitConfirm) + msg, err = bm.CreateDefinition(ctx, pool, core.SystemTagDefinePool, waitConfirm) if msg != nil { pool.Pool.Message = msg.Header.ID } diff --git a/internal/defsender/tokenpool_test.go b/internal/defsender/tokenpool_test.go index ad5e09981..7cfbba8c0 100644 --- a/internal/defsender/tokenpool_test.go +++ b/internal/defsender/tokenpool_test.go @@ -46,13 +46,13 @@ func TestBroadcastTokenPoolInvalid(t *testing.T) { }, } - _, err := ds.BroadcastTokenPool(context.Background(), pool, false) + _, err := ds.CreateTokenPool(context.Background(), pool, false) assert.Regexp(t, "FF00140", err) mdm.AssertExpectations(t) } -func TestBroadcastTokenPoolOk(t *testing.T) { +func TestCreateTokenPoolOk(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() @@ -76,7 +76,7 @@ func TestBroadcastTokenPoolOk(t *testing.T) { mbm.On("NewBroadcast", mock.Anything).Return(mms) mms.On("Send", context.Background()).Return(nil) - _, err := ds.BroadcastTokenPool(context.Background(), pool, false) + _, err := ds.CreateTokenPool(context.Background(), pool, false) assert.NoError(t, err) mdm.AssertExpectations(t) diff --git a/internal/events/token_pool_created.go b/internal/events/token_pool_created.go index 5d07dd3a3..dfa259d75 100644 --- a/internal/events/token_pool_created.go +++ b/internal/events/token_pool_created.go @@ -195,7 +195,7 @@ func (em *eventManager) TokenPoolCreated(ti tokens.Plugin, pool *tokens.TokenPoo Pool: announcePool, } log.L(em.ctx).Infof("Announcing token pool, id=%s", announcePool.ID) - _, err = em.defsender.BroadcastTokenPool(em.ctx, broadcast, false) + _, err = em.defsender.CreateTokenPool(em.ctx, broadcast, false) } } diff --git a/internal/events/token_pool_created_test.go b/internal/events/token_pool_created_test.go index 27dbc1244..960e36963 100644 --- a/internal/events/token_pool_created_test.go +++ b/internal/events/token_pool_created_test.go @@ -505,7 +505,7 @@ func TestTokenPoolCreatedAnnounce(t *testing.T) { mdi.On("GetTokenPoolByLocator", em.ctx, "ns1", "erc1155", "123").Return(nil, nil).Times(2) mdi.On("GetOperations", em.ctx, "ns1", mock.Anything).Return(nil, nil, fmt.Errorf("pop")).Once() mdi.On("GetOperations", em.ctx, "ns1", mock.Anything).Return(operations, nil, nil).Once() - mds.On("BroadcastTokenPool", em.ctx, mock.MatchedBy(func(pool *core.TokenPoolAnnouncement) bool { + mds.On("CreateTokenPool", em.ctx, mock.MatchedBy(func(pool *core.TokenPoolAnnouncement) bool { return pool.Pool.Namespace == "ns1" && pool.Pool.Name == "my-pool" && *pool.Pool.ID == *poolID }), false).Return(nil, nil) diff --git a/internal/networkmap/register_identity.go b/internal/networkmap/register_identity.go index cc0376a2b..2254a7baf 100644 --- a/internal/networkmap/register_identity.go +++ b/internal/networkmap/register_identity.go @@ -109,7 +109,7 @@ func (nm *networkMap) RegisterIdentity(ctx context.Context, dto *core.IdentityCr func (nm *networkMap) sendIdentityRequest(ctx context.Context, identity *core.Identity, claimSigner *core.SignerRef, parentSigner *core.SignerRef) error { // Send the claim - we disable the check on the DID author here, as we are registering the identity so it will not exist - claimMsg, err := nm.defsender.BroadcastIdentityClaim(ctx, &core.IdentityClaim{ + claimMsg, err := nm.defsender.CreateIdentityClaim(ctx, &core.IdentityClaim{ Identity: identity, }, claimSigner, core.SystemTagIdentityClaim, false) if err != nil { @@ -119,7 +119,7 @@ func (nm *networkMap) sendIdentityRequest(ctx context.Context, identity *core.Id // Send the verification if one is required. if parentSigner != nil { - verifyMsg, err := nm.defsender.BroadcastDefinition(ctx, &core.IdentityVerification{ + verifyMsg, err := nm.defsender.CreateDefinitionWithIdentity(ctx, &core.IdentityVerification{ Claim: core.MessageRef{ ID: claimMsg.Header.ID, Hash: claimMsg.Hash, diff --git a/internal/networkmap/register_identity_test.go b/internal/networkmap/register_identity_test.go index ff00bd673..39009ad8b 100644 --- a/internal/networkmap/register_identity_test.go +++ b/internal/networkmap/register_identity_test.go @@ -48,14 +48,14 @@ func TestRegisterIdentityOrgWithParentOk(t *testing.T) { mockMsg2 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mds := nm.defsender.(*defsendermocks.Sender) - mds.On("BroadcastIdentityClaim", nm.ctx, + mds.On("CreateIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" }), core.SystemTagIdentityClaim, false).Return(mockMsg1, nil) - mds.On("BroadcastDefinition", nm.ctx, + mds.On("CreateDefinitionWithIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityVerification"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x23456" @@ -102,14 +102,14 @@ func TestRegisterIdentityOrgWithParentWaitConfirmOk(t *testing.T) { mockMsg2 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mds := nm.defsender.(*defsendermocks.Sender) - mds.On("BroadcastIdentityClaim", nm.ctx, + mds.On("CreateIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" }), core.SystemTagIdentityClaim, false).Return(mockMsg1, nil) - mds.On("BroadcastDefinition", nm.ctx, + mds.On("CreateDefinitionWithIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityVerification"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x23456" @@ -150,14 +150,14 @@ func TestRegisterIdentityCustomWithParentFail(t *testing.T) { mockMsg := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mds := nm.defsender.(*defsendermocks.Sender) - mds.On("BroadcastIdentityClaim", nm.ctx, + mds.On("CreateIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" }), core.SystemTagIdentityClaim, false).Return(mockMsg, nil) - mds.On("BroadcastDefinition", nm.ctx, + mds.On("CreateDefinitionWithIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityVerification"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x23456" @@ -205,7 +205,7 @@ func TestRegisterIdentityRootBroadcastFail(t *testing.T) { mim.On("VerifyIdentityChain", nm.ctx, mock.AnythingOfType("*core.Identity")).Return(nil, false, nil) mds := nm.defsender.(*defsendermocks.Sender) - mds.On("BroadcastIdentityClaim", nm.ctx, + mds.On("CreateIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" diff --git a/internal/networkmap/register_node_test.go b/internal/networkmap/register_node_test.go index 666ccc2a5..15050460b 100644 --- a/internal/networkmap/register_node_test.go +++ b/internal/networkmap/register_node_test.go @@ -56,7 +56,7 @@ func TestRegisterNodeOk(t *testing.T) { mockMsg := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mds := nm.defsender.(*defsendermocks.Sender) - mds.On("BroadcastIdentityClaim", nm.ctx, + mds.On("CreateIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), signerRef, core.SystemTagIdentityClaim, false).Return(mockMsg, nil) diff --git a/internal/networkmap/register_org_test.go b/internal/networkmap/register_org_test.go index b932a24e8..33c6d364e 100644 --- a/internal/networkmap/register_org_test.go +++ b/internal/networkmap/register_org_test.go @@ -69,7 +69,7 @@ func TestRegisterNodeOrgOk(t *testing.T) { mockMsg := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mds := nm.defsender.(*defsendermocks.Sender) - mds.On("BroadcastIdentityClaim", nm.ctx, + mds.On("CreateIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" diff --git a/internal/networkmap/update_identity.go b/internal/networkmap/update_identity.go index a0541c5e8..fe0d2d28a 100644 --- a/internal/networkmap/update_identity.go +++ b/internal/networkmap/update_identity.go @@ -56,7 +56,7 @@ func (nm *networkMap) updateIdentityID(ctx context.Context, id *fftypes.UUID, dt } // Send the update - updateMsg, err := nm.defsender.BroadcastDefinition(ctx, &core.IdentityUpdate{ + updateMsg, err := nm.defsender.CreateDefinitionWithIdentity(ctx, &core.IdentityUpdate{ Identity: identity.IdentityBase, Updates: dto.IdentityProfile, }, updateSigner, core.SystemTagIdentityUpdate, waitConfirm) diff --git a/internal/networkmap/update_identity_test.go b/internal/networkmap/update_identity_test.go index bfa9e02cd..aac84a9b6 100644 --- a/internal/networkmap/update_identity_test.go +++ b/internal/networkmap/update_identity_test.go @@ -43,7 +43,7 @@ func TestUpdateIdentityProfileOk(t *testing.T) { mockMsg1 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mds := nm.defsender.(*defsendermocks.Sender) - mds.On("BroadcastDefinition", nm.ctx, + mds.On("CreateDefinitionWithIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityUpdate"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" @@ -76,7 +76,7 @@ func TestUpdateIdentityProfileBroadcastFail(t *testing.T) { mim.On("ResolveIdentitySigner", nm.ctx, identity).Return(signerRef, nil) mds := nm.defsender.(*defsendermocks.Sender) - mds.On("BroadcastDefinition", nm.ctx, + mds.On("CreateDefinitionWithIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityUpdate"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" diff --git a/mocks/defsendermocks/sender.go b/mocks/defsendermocks/sender.go index 7f440c127..f908270da 100644 --- a/mocks/defsendermocks/sender.go +++ b/mocks/defsendermocks/sender.go @@ -15,8 +15,8 @@ type Sender struct { mock.Mock } -// BroadcastDatatype provides a mock function with given fields: ctx, datatype, waitConfirm -func (_m *Sender) BroadcastDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (*core.Message, error) { +// CreateDatatype provides a mock function with given fields: ctx, datatype, waitConfirm +func (_m *Sender) CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (*core.Message, error) { ret := _m.Called(ctx, datatype, waitConfirm) var r0 *core.Message @@ -38,13 +38,13 @@ func (_m *Sender) BroadcastDatatype(ctx context.Context, datatype *core.Datatype return r0, r1 } -// BroadcastDefinition provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm -func (_m *Sender) BroadcastDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { - ret := _m.Called(ctx, def, signingIdentity, tag, waitConfirm) +// CreateDefinition provides a mock function with given fields: ctx, def, tag, waitConfirm +func (_m *Sender) CreateDefinition(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (*core.Message, error) { + ret := _m.Called(ctx, def, tag, waitConfirm) var r0 *core.Message - if rf, ok := ret.Get(0).(func(context.Context, core.Definition, *core.SignerRef, string, bool) *core.Message); ok { - r0 = rf(ctx, def, signingIdentity, tag, waitConfirm) + if rf, ok := ret.Get(0).(func(context.Context, core.Definition, string, bool) *core.Message); ok { + r0 = rf(ctx, def, tag, waitConfirm) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*core.Message) @@ -52,8 +52,8 @@ func (_m *Sender) BroadcastDefinition(ctx context.Context, def core.Definition, } var r1 error - if rf, ok := ret.Get(1).(func(context.Context, core.Definition, *core.SignerRef, string, bool) error); ok { - r1 = rf(ctx, def, signingIdentity, tag, waitConfirm) + if rf, ok := ret.Get(1).(func(context.Context, core.Definition, string, bool) error); ok { + r1 = rf(ctx, def, tag, waitConfirm) } else { r1 = ret.Error(1) } @@ -61,13 +61,13 @@ func (_m *Sender) BroadcastDefinition(ctx context.Context, def core.Definition, return r0, r1 } -// BroadcastDefinitionAsNode provides a mock function with given fields: ctx, def, tag, waitConfirm -func (_m *Sender) BroadcastDefinitionAsNode(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (*core.Message, error) { - ret := _m.Called(ctx, def, tag, waitConfirm) +// CreateDefinitionWithIdentity provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm +func (_m *Sender) CreateDefinitionWithIdentity(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { + ret := _m.Called(ctx, def, signingIdentity, tag, waitConfirm) var r0 *core.Message - if rf, ok := ret.Get(0).(func(context.Context, core.Definition, string, bool) *core.Message); ok { - r0 = rf(ctx, def, tag, waitConfirm) + if rf, ok := ret.Get(0).(func(context.Context, core.Definition, *core.SignerRef, string, bool) *core.Message); ok { + r0 = rf(ctx, def, signingIdentity, tag, waitConfirm) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*core.Message) @@ -75,8 +75,8 @@ func (_m *Sender) BroadcastDefinitionAsNode(ctx context.Context, def core.Defini } var r1 error - if rf, ok := ret.Get(1).(func(context.Context, core.Definition, string, bool) error); ok { - r1 = rf(ctx, def, tag, waitConfirm) + if rf, ok := ret.Get(1).(func(context.Context, core.Definition, *core.SignerRef, string, bool) error); ok { + r1 = rf(ctx, def, signingIdentity, tag, waitConfirm) } else { r1 = ret.Error(1) } @@ -84,8 +84,8 @@ func (_m *Sender) BroadcastDefinitionAsNode(ctx context.Context, def core.Defini return r0, r1 } -// BroadcastIdentityClaim provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm -func (_m *Sender) BroadcastIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { +// CreateIdentityClaim provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm +func (_m *Sender) CreateIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { ret := _m.Called(ctx, def, signingIdentity, tag, waitConfirm) var r0 *core.Message @@ -107,8 +107,8 @@ func (_m *Sender) BroadcastIdentityClaim(ctx context.Context, def *core.Identity return r0, r1 } -// BroadcastTokenPool provides a mock function with given fields: ctx, pool, waitConfirm -func (_m *Sender) BroadcastTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (*core.Message, error) { +// CreateTokenPool provides a mock function with given fields: ctx, pool, waitConfirm +func (_m *Sender) CreateTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (*core.Message, error) { ret := _m.Called(ctx, pool, waitConfirm) var r0 *core.Message From 96dde6089e4087a2e0deeb7bfe757f7a2aedcd53 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Thu, 12 May 2022 10:11:22 -0400 Subject: [PATCH 03/27] Move BatchState struct into core Signed-off-by: Andrew Richardson --- internal/definitions/definition_handler.go | 22 +----- .../definition_handler_contracts.go | 4 +- .../definition_handler_contracts_test.go | 22 +++--- .../definition_handler_datatype.go | 2 +- .../definition_handler_datatype_test.go | 20 ++--- .../definition_handler_identity_claim.go | 10 +-- .../definition_handler_identity_claim_test.go | 52 ++++++------ .../definition_handler_identity_update.go | 2 +- ...definition_handler_identity_update_test.go | 16 ++-- ...efinition_handler_identity_verification.go | 4 +- ...tion_handler_identity_verification_test.go | 28 +++---- .../definition_handler_namespace.go | 2 +- .../definition_handler_namespace_test.go | 26 +++--- .../definition_handler_network_node.go | 2 +- .../definition_handler_network_node_test.go | 12 +-- .../definition_handler_network_org.go | 2 +- .../definition_handler_network_org_test.go | 6 +- .../definitions/definition_handler_test.go | 37 +++------ .../definition_handler_tokenpool.go | 2 +- .../definition_handler_tokenpool_test.go | 24 +++--- internal/events/aggregator.go | 12 +-- internal/events/aggregator_batch_state.go | 64 +++------------ .../events/aggregator_batch_state_test.go | 6 +- internal/events/aggregator_test.go | 6 +- mocks/definitionsmocks/definition_handler.go | 6 +- pkg/core/batch_state.go | 79 +++++++++++++++++++ pkg/core/batch_state_test.go | 68 ++++++++++++++++ 27 files changed, 305 insertions(+), 231 deletions(-) create mode 100644 pkg/core/batch_state.go create mode 100644 pkg/core/batch_state_test.go diff --git a/internal/definitions/definition_handler.go b/internal/definitions/definition_handler.go index f5ff854e2..d688a0258 100644 --- a/internal/definitions/definition_handler.go +++ b/internal/definitions/definition_handler.go @@ -36,7 +36,7 @@ import ( ) type DefinitionHandler interface { - HandleDefinitionBroadcast(ctx context.Context, state DefinitionBatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) + HandleDefinitionBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) } type HandlerResult struct { @@ -76,24 +76,6 @@ func (dma DefinitionMessageAction) String() string { } } -// DefinitionBatchState tracks the state between definition handlers that run in-line on the pin processing route in the -// aggregator as part of a batch of pins. They might have complex API calls, and interdependencies, that need to be managed via this state. -// The actions to be taken at the end of a definition batch. -// See further notes on "batchState" in the event aggregator -type DefinitionBatchState interface { - // PreFinalize may perform a blocking action (possibly to an external connector) that should execute outside database RunAsGroup - AddPreFinalize(func(ctx context.Context) error) - - // Finalize may perform final, non-idempotent database operations (such as inserting Events) - AddFinalize(func(ctx context.Context) error) - - // GetPendingConfirm returns a map of messages are that pending confirmation after already being processed in this batch - GetPendingConfirm() map[fftypes.UUID]*core.Message - - // Notify of a DID claim locking in, so a rewind gets queued for it to go back and process any dependent child identities/messages - DIDClaimConfirmed(did string) -} - type definitionHandlers struct { namespace string database database.Plugin @@ -121,7 +103,7 @@ func NewDefinitionHandler(ctx context.Context, ns string, di database.Plugin, bi }, nil } -func (dh *definitionHandlers) HandleDefinitionBroadcast(ctx context.Context, state DefinitionBatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (msgAction HandlerResult, err error) { +func (dh *definitionHandlers) HandleDefinitionBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (msgAction HandlerResult, err error) { l := log.L(ctx) l.Infof("Processing system definition '%s' [%s]", msg.Header.Tag, msg.Header.ID) switch msg.Header.Tag { diff --git a/internal/definitions/definition_handler_contracts.go b/internal/definitions/definition_handler_contracts.go index f6bf550c2..fa9f5b5ce 100644 --- a/internal/definitions/definition_handler_contracts.go +++ b/internal/definitions/definition_handler_contracts.go @@ -75,7 +75,7 @@ func (dh *definitionHandlers) persistContractAPI(ctx context.Context, api *core. return false, nil } -func (dh *definitionHandlers) handleFFIBroadcast(ctx context.Context, state DefinitionBatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { +func (dh *definitionHandlers) handleFFIBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { l := log.L(ctx) var ffi core.FFI if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &ffi); !valid { @@ -98,7 +98,7 @@ func (dh *definitionHandlers) handleFFIBroadcast(ctx context.Context, state Defi return HandlerResult{Action: ActionConfirm}, nil } -func (dh *definitionHandlers) handleContractAPIBroadcast(ctx context.Context, state DefinitionBatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { +func (dh *definitionHandlers) handleContractAPIBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { l := log.L(ctx) var api core.ContractAPI if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &api); !valid { diff --git a/internal/definitions/definition_handler_contracts_test.go b/internal/definitions/definition_handler_contracts_test.go index cba38a783..570261640 100644 --- a/internal/definitions/definition_handler_contracts_test.go +++ b/internal/definitions/definition_handler_contracts_test.go @@ -104,14 +104,14 @@ func TestHandleFFIBroadcastOk(t *testing.T) { mcm := dh.contracts.(*contractmocks.Manager) mcm.On("ValidateFFIAndSetPathnames", mock.Anything, mock.Anything).Return(nil) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineFFI, }, }, core.DataArray{data}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) - err = bs.finalizers[0](context.Background()) + err = bs.RunFinalize(context.Background()) assert.NoError(t, err) mbi.AssertExpectations(t) } @@ -131,7 +131,7 @@ func TestHandleFFIBroadcastReject(t *testing.T) { mcm := dh.contracts.(*contractmocks.Manager) mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) mcm.On("ValidateFFIAndSetPathnames", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - action, err := dh.handleFFIBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.handleFFIBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineFFI, }, @@ -191,7 +191,7 @@ func TestHandleFFIBroadcastValidateFail(t *testing.T) { } mbi := dh.database.(*databasemocks.Plugin) mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineFFI, }, @@ -214,7 +214,7 @@ func TestHandleFFIBroadcastPersistFail(t *testing.T) { mdi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) mcm := dh.contracts.(*contractmocks.Manager) mcm.On("ValidateFFIAndSetPathnames", mock.Anything, mock.Anything).Return(nil) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineFFI, }, @@ -237,14 +237,14 @@ func TestHandleContractAPIBroadcastOk(t *testing.T) { mbi.On("UpsertContractAPI", mock.Anything, mock.Anything, mock.Anything).Return(nil) mbi.On("GetContractAPIByName", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineContractAPI, }, }, core.DataArray{data}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) - err = bs.finalizers[0](context.Background()) + err = bs.RunFinalize(context.Background()) assert.NoError(t, err) mbi.AssertExpectations(t) } @@ -255,7 +255,7 @@ func TestHandleContractAPIBadPayload(t *testing.T) { Value: fftypes.JSONAnyPtr("bad"), } - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineContractAPI, }, @@ -277,7 +277,7 @@ func TestHandleContractAPIIDMismatch(t *testing.T) { mbi.On("GetContractAPIByName", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) mbi.On("UpsertContractAPI", mock.Anything, mock.Anything, mock.Anything).Return(database.IDMismatch) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineContractAPI, }, @@ -329,7 +329,7 @@ func TestHandleContractAPIBroadcastValidateFail(t *testing.T) { } mbi := dh.database.(*databasemocks.Plugin) mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineContractAPI, }, @@ -351,7 +351,7 @@ func TestHandleContractAPIBroadcastPersistFail(t *testing.T) { mbi.On("GetContractAPIByName", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) mbi.On("UpsertContractAPI", mock.Anything, mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineContractAPI, }, diff --git a/internal/definitions/definition_handler_datatype.go b/internal/definitions/definition_handler_datatype.go index 0f6c79a00..1730d6894 100644 --- a/internal/definitions/definition_handler_datatype.go +++ b/internal/definitions/definition_handler_datatype.go @@ -25,7 +25,7 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (dh *definitionHandlers) handleDatatypeBroadcast(ctx context.Context, state DefinitionBatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { +func (dh *definitionHandlers) handleDatatypeBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { var dt core.Datatype valid := dh.getSystemBroadcastPayload(ctx, msg, data, &dt) if !valid { diff --git a/internal/definitions/definition_handler_datatype_test.go b/internal/definitions/definition_handler_datatype_test.go index a901bde15..d289a82ab 100644 --- a/internal/definitions/definition_handler_datatype_test.go +++ b/internal/definitions/definition_handler_datatype_test.go @@ -54,14 +54,14 @@ func TestHandleDefinitionBroadcastDatatypeOk(t *testing.T) { mbi.On("GetDatatypeByName", mock.Anything, "ns1", "name1", "ver1").Return(nil, nil) mbi.On("UpsertDatatype", mock.Anything, mock.Anything, false).Return(nil) mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineDatatype, }, }, core.DataArray{data}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) - err = bs.finalizers[0](context.Background()) + err = bs.RunFinalize(context.Background()) assert.NoError(t, err) mdm.AssertExpectations(t) @@ -92,14 +92,14 @@ func TestHandleDefinitionBroadcastDatatypeEventFail(t *testing.T) { mbi.On("GetDatatypeByName", mock.Anything, "ns1", "name1", "ver1").Return(nil, nil) mbi.On("UpsertDatatype", mock.Anything, mock.Anything, false).Return(nil) mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineDatatype, }, }, core.DataArray{data}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) - err = bs.finalizers[0](context.Background()) + err = bs.RunFinalize(context.Background()) assert.EqualError(t, err, "pop") mdm.AssertExpectations(t) @@ -123,7 +123,7 @@ func TestHandleDefinitionBroadcastDatatypeMissingID(t *testing.T) { Value: fftypes.JSONAnyPtrBytes(b), } - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineDatatype, }, @@ -153,7 +153,7 @@ func TestHandleDefinitionBroadcastBadSchema(t *testing.T) { mdm := dh.data.(*datamocks.Manager) mdm.On("CheckDatatype", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineDatatype, }, @@ -178,7 +178,7 @@ func TestHandleDefinitionBroadcastMissingData(t *testing.T) { } dt.Hash = dt.Value.Hash() - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineDatatype, }, @@ -210,7 +210,7 @@ func TestHandleDefinitionBroadcastDatatypeLookupFail(t *testing.T) { mdm.On("CheckDatatype", mock.Anything, mock.Anything).Return(nil) mbi := dh.database.(*databasemocks.Plugin) mbi.On("GetDatatypeByName", mock.Anything, "ns1", "name1", "ver1").Return(nil, fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Namespace: "ns1", Tag: core.SystemTagDefineDatatype, @@ -247,7 +247,7 @@ func TestHandleDefinitionBroadcastUpsertFail(t *testing.T) { mbi := dh.database.(*databasemocks.Plugin) mbi.On("GetDatatypeByName", mock.Anything, "ns1", "name1", "ver1").Return(nil, nil) mbi.On("UpsertDatatype", mock.Anything, mock.Anything, false).Return(fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineDatatype, }, @@ -282,7 +282,7 @@ func TestHandleDefinitionBroadcastDatatypeDuplicate(t *testing.T) { mdm.On("CheckDatatype", mock.Anything, mock.Anything).Return(nil) mbi := dh.database.(*databasemocks.Plugin) mbi.On("GetDatatypeByName", mock.Anything, "ns1", "name1", "ver1").Return(dt, nil) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineDatatype, }, diff --git a/internal/definitions/definition_handler_identity_claim.go b/internal/definitions/definition_handler_identity_claim.go index a541144b6..95c89fd02 100644 --- a/internal/definitions/definition_handler_identity_claim.go +++ b/internal/definitions/definition_handler_identity_claim.go @@ -28,7 +28,7 @@ import ( "github.com/hyperledger/firefly/pkg/database" ) -func (dh *definitionHandlers) handleIdentityClaimBroadcast(ctx context.Context, state DefinitionBatchState, msg *core.Message, data core.DataArray, verificationID *fftypes.UUID) (HandlerResult, error) { +func (dh *definitionHandlers) handleIdentityClaimBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, verificationID *fftypes.UUID) (HandlerResult, error) { var claim core.IdentityClaim if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &claim); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "identity claim", msg.Header.ID) @@ -77,7 +77,7 @@ func (dh *definitionHandlers) getClaimVerifier(msg *core.Message, identity *core return verifier } -func (dh *definitionHandlers) confirmVerificationForClaim(ctx context.Context, state DefinitionBatchState, msg *core.Message, identity, parent *core.Identity) (*fftypes.UUID, error) { +func (dh *definitionHandlers) confirmVerificationForClaim(ctx context.Context, state *core.BatchState, msg *core.Message, identity, parent *core.Identity) (*fftypes.UUID, error) { // Query for messages on the topic for this DID, signed by the right identity idTopic := identity.Topic() fb := database.MessageQueryFactory.NewFilter(ctx) @@ -93,7 +93,7 @@ func (dh *definitionHandlers) confirmVerificationForClaim(ctx context.Context, s return nil, err } // We also need to check pending messages in the current pin batch - for _, pending := range state.GetPendingConfirm() { + for _, pending := range state.PendingConfirms { if pending.Header.Topics.String() == idTopic && pending.Header.Author == parent.DID && pending.Header.Type == core.MessageTypeDefinition && @@ -126,7 +126,7 @@ func (dh *definitionHandlers) confirmVerificationForClaim(ctx context.Context, s return nil, nil } -func (dh *definitionHandlers) handleIdentityClaim(ctx context.Context, state DefinitionBatchState, msg *core.Message, identityClaim *core.IdentityClaim, verificationID *fftypes.UUID) (HandlerResult, error) { +func (dh *definitionHandlers) handleIdentityClaim(ctx context.Context, state *core.BatchState, msg *core.Message, identityClaim *core.IdentityClaim, verificationID *fftypes.UUID) (HandlerResult, error) { l := log.L(ctx) identity := identityClaim.Identity @@ -211,7 +211,7 @@ func (dh *definitionHandlers) handleIdentityClaim(ctx context.Context, state Def }) } - state.DIDClaimConfirmed(identity.DID) + state.AddConfirmedDIDClaim(identity.DID) state.AddFinalize(func(ctx context.Context) error { event := core.NewEvent(core.EventTypeIdentityConfirmed, identity.Namespace, identity.ID, nil, core.SystemTopicDefinitions) return dh.database.InsertEvent(ctx, event) diff --git a/internal/definitions/definition_handler_identity_claim_test.go b/internal/definitions/definition_handler_identity_claim_test.go index 586c41a2c..8e7627dd3 100644 --- a/internal/definitions/definition_handler_identity_claim_test.go +++ b/internal/definitions/definition_handler_identity_claim_test.go @@ -173,14 +173,14 @@ func TestHandleDefinitionIdentityClaimCustomWithExistingParentVerificationOk(t * mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{verifyData}, false, nil).Once() mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{verifyData}, true, nil) - bs.pendingConfirms[*verifyMsg.Header.ID] = verifyMsg + bs.AddPendingConfirm(verifyMsg.Header.ID, verifyMsg) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) - assert.Equal(t, bs.confirmedDIDClaims, []string{custom1.DID}) + assert.Equal(t, bs.ConfirmedDIDClaims, []string{custom1.DID}) - err = bs.finalizers[0](ctx) + err = bs.RunFinalize(ctx) assert.NoError(t, err) mdi.AssertExpectations(t) @@ -220,13 +220,13 @@ func TestHandleDefinitionIdentityClaimIdempotentReplay(t *testing.T) { mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{verifyData}, false, nil).Once() mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{verifyData}, true, nil) - bs.pendingConfirms[*verifyMsg.Header.ID] = verifyMsg + bs.AddPendingConfirm(verifyMsg.Header.ID, verifyMsg) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) - err = bs.finalizers[0](ctx) + err = bs.RunFinalize(ctx) assert.NoError(t, err) mim.AssertExpectations(t) @@ -254,9 +254,9 @@ func TestHandleDefinitionIdentityClaimFailInsertIdentity(t *testing.T) { mdm := dh.data.(*datamocks.Manager) mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{verifyData}, true, nil) - bs.pendingConfirms[*verifyMsg.Header.ID] = verifyMsg + bs.AddPendingConfirm(verifyMsg.Header.ID, verifyMsg) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -284,9 +284,9 @@ func TestHandleDefinitionIdentityClaimVerificationDataFail(t *testing.T) { mdm := dh.data.(*datamocks.Manager) mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(nil, false, fmt.Errorf("pop")) - bs.pendingConfirms[*verifyMsg.Header.ID] = verifyMsg + bs.AddPendingConfirm(verifyMsg.Header.ID, verifyMsg) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -314,9 +314,9 @@ func TestHandleDefinitionIdentityClaimVerificationMissingData(t *testing.T) { mdm := dh.data.(*datamocks.Manager) mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{}, true, nil) - bs.pendingConfirms[*verifyMsg.Header.ID] = verifyMsg + bs.AddPendingConfirm(verifyMsg.Header.ID, verifyMsg) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) @@ -345,9 +345,9 @@ func TestHandleDefinitionIdentityClaimFailInsertVerifier(t *testing.T) { mdm := dh.data.(*datamocks.Manager) mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{verifyData}, true, nil) - bs.pendingConfirms[*verifyMsg.Header.ID] = verifyMsg + bs.AddPendingConfirm(verifyMsg.Header.ID, verifyMsg) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -372,7 +372,7 @@ func TestHandleDefinitionIdentityClaimCustomMissingParentVerificationOk(t *testi mdi.On("GetVerifierByValue", ctx, core.VerifierTypeEthAddress, "ns1", "0x12345").Return(nil, nil) mdi.On("GetMessages", ctx, "ns1", mock.Anything).Return([]*core.Message{}, nil, nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) // Just wait for the verification to come in later assert.NoError(t, err) @@ -396,7 +396,7 @@ func TestHandleDefinitionIdentityClaimCustomParentVerificationFail(t *testing.T) mdi.On("GetVerifierByValue", ctx, core.VerifierTypeEthAddress, "ns1", "0x12345").Return(nil, nil) mdi.On("GetMessages", ctx, "ns1", mock.Anything).Return(nil, nil, fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -421,7 +421,7 @@ func TestHandleDefinitionIdentityClaimVerifierClash(t *testing.T) { Hash: fftypes.NewRandB32(), }, nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -444,7 +444,7 @@ func TestHandleDefinitionIdentityClaimVerifierError(t *testing.T) { mdi.On("GetIdentityByID", ctx, "ns1", custom1.ID).Return(nil, nil) mdi.On("GetVerifierByValue", ctx, core.VerifierTypeEthAddress, "ns1", "0x12345").Return(nil, fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -469,7 +469,7 @@ func TestHandleDefinitionIdentityClaimIdentityClash(t *testing.T) { }, }, nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -491,7 +491,7 @@ func TestHandleDefinitionIdentityClaimIdentityError(t *testing.T) { mdi.On("GetIdentityByName", ctx, custom1.Type, custom1.Namespace, custom1.Name).Return(nil, nil) mdi.On("GetIdentityByID", ctx, "ns1", custom1.ID).Return(nil, fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -510,7 +510,7 @@ func TestHandleDefinitionIdentityMissingAuthor(t *testing.T) { mim := dh.identity.(*identitymanagermocks.Manager) mim.On("VerifyIdentityChain", ctx, custom1).Return(org1, false, nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -528,7 +528,7 @@ func TestHandleDefinitionIdentityClaimBadSignature(t *testing.T) { mim := dh.identity.(*identitymanagermocks.Manager) mim.On("VerifyIdentityChain", ctx, custom1).Return(org1, false, nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -546,7 +546,7 @@ func TestHandleDefinitionIdentityVerifyChainFail(t *testing.T) { mim := dh.identity.(*identitymanagermocks.Manager) mim.On("VerifyIdentityChain", ctx, custom1).Return(nil, true, fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -564,7 +564,7 @@ func TestHandleDefinitionIdentityVerifyChainInvalid(t *testing.T) { mim := dh.identity.(*identitymanagermocks.Manager) mim.On("VerifyIdentityChain", ctx, custom1).Return(nil, false, fmt.Errorf("wrong")) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionWait}, action) assert.NoError(t, err) @@ -579,7 +579,7 @@ func TestHandleDefinitionIdentityClaimBadData(t *testing.T) { _, org1, claimMsg, _, _, _ := testCustomClaimAndVerification(t) claimMsg.Header.Author = org1.DID // should be the child for the claim - action, err := dh.HandleDefinitionBroadcast(ctx, bs, claimMsg, core.DataArray{}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) diff --git a/internal/definitions/definition_handler_identity_update.go b/internal/definitions/definition_handler_identity_update.go index 627ff98b7..5846292fa 100644 --- a/internal/definitions/definition_handler_identity_update.go +++ b/internal/definitions/definition_handler_identity_update.go @@ -25,7 +25,7 @@ import ( "github.com/hyperledger/firefly/pkg/database" ) -func (dh *definitionHandlers) handleIdentityUpdateBroadcast(ctx context.Context, state DefinitionBatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { +func (dh *definitionHandlers) handleIdentityUpdateBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { var update core.IdentityUpdate if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &update); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "identity update", msg.Header.ID) diff --git a/internal/definitions/definition_handler_identity_update_test.go b/internal/definitions/definition_handler_identity_update_test.go index cc1208cbf..4772497aa 100644 --- a/internal/definitions/definition_handler_identity_update_test.go +++ b/internal/definitions/definition_handler_identity_update_test.go @@ -87,11 +87,11 @@ func TestHandleDefinitionIdentityUpdateOk(t *testing.T) { return event.Type == core.EventTypeIdentityUpdated })).Return(nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, updateMsg, core.DataArray{updateData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, updateMsg, core.DataArray{updateData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) - err = bs.finalizers[0](ctx) + err = bs.RunFinalize(ctx) assert.NoError(t, err) mim.AssertExpectations(t) @@ -110,7 +110,7 @@ func TestHandleDefinitionIdentityUpdateUpsertFail(t *testing.T) { mdi := dh.database.(*databasemocks.Plugin) mdi.On("UpsertIdentity", ctx, mock.Anything, database.UpsertOptimizationExisting).Return(fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, updateMsg, core.DataArray{updateData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, updateMsg, core.DataArray{updateData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -129,7 +129,7 @@ func TestHandleDefinitionIdentityInvalidIdentity(t *testing.T) { mim := dh.identity.(*identitymanagermocks.Manager) mim.On("CachedIdentityLookupByID", ctx, org1.ID).Return(org1, nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, updateMsg, core.DataArray{updateData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, updateMsg, core.DataArray{updateData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -146,7 +146,7 @@ func TestHandleDefinitionIdentityNotFound(t *testing.T) { mim := dh.identity.(*identitymanagermocks.Manager) mim.On("CachedIdentityLookupByID", ctx, org1.ID).Return(nil, nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, updateMsg, core.DataArray{updateData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, updateMsg, core.DataArray{updateData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -163,7 +163,7 @@ func TestHandleDefinitionIdentityLookupFail(t *testing.T) { mim := dh.identity.(*identitymanagermocks.Manager) mim.On("CachedIdentityLookupByID", ctx, org1.ID).Return(nil, fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, updateMsg, core.DataArray{updateData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, updateMsg, core.DataArray{updateData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -200,7 +200,7 @@ func TestHandleDefinitionIdentityValidateFail(t *testing.T) { }, } - action, err := dh.HandleDefinitionBroadcast(ctx, bs, updateMsg, core.DataArray{updateData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, updateMsg, core.DataArray{updateData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -225,7 +225,7 @@ func TestHandleDefinitionIdentityMissingData(t *testing.T) { }, } - action, err := dh.HandleDefinitionBroadcast(ctx, bs, updateMsg, core.DataArray{}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, updateMsg, core.DataArray{}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) diff --git a/internal/definitions/definition_handler_identity_verification.go b/internal/definitions/definition_handler_identity_verification.go index aaf5918ea..88bab6846 100644 --- a/internal/definitions/definition_handler_identity_verification.go +++ b/internal/definitions/definition_handler_identity_verification.go @@ -24,7 +24,7 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (dh *definitionHandlers) handleIdentityVerificationBroadcast(ctx context.Context, state DefinitionBatchState, verifyMsg *core.Message, data core.DataArray) (HandlerResult, error) { +func (dh *definitionHandlers) handleIdentityVerificationBroadcast(ctx context.Context, state *core.BatchState, verifyMsg *core.Message, data core.DataArray) (HandlerResult, error) { var verification core.IdentityVerification valid := dh.getSystemBroadcastPayload(ctx, verifyMsg, data, &verification) if !valid { @@ -56,7 +56,7 @@ func (dh *definitionHandlers) handleIdentityVerificationBroadcast(ctx context.Co return HandlerResult{Action: ActionRetry}, err } if claimMsg == nil || claimMsg.State != core.MessageStateConfirmed { - claimMsg = state.GetPendingConfirm()[*verification.Claim.ID] + claimMsg = state.PendingConfirms[*verification.Claim.ID] } if claimMsg != nil { diff --git a/internal/definitions/definition_handler_identity_verification_test.go b/internal/definitions/definition_handler_identity_verification_test.go index 4793bd3ea..71aaa2403 100644 --- a/internal/definitions/definition_handler_identity_verification_test.go +++ b/internal/definitions/definition_handler_identity_verification_test.go @@ -65,14 +65,14 @@ func TestHandleDefinitionIdentityVerificationWithExistingClaimOk(t *testing.T) { mdm := dh.data.(*datamocks.Manager) mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{claimData}, true, nil) - bs.pendingConfirms[*claimMsg.Header.ID] = claimMsg + bs.AddPendingConfirm(claimMsg.Header.ID, claimMsg) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) - assert.Equal(t, bs.confirmedDIDClaims, []string{custom1.DID}) + assert.Equal(t, bs.ConfirmedDIDClaims, []string{custom1.DID}) - err = bs.finalizers[0](ctx) + err = bs.RunFinalize(ctx) assert.NoError(t, err) mim.AssertExpectations(t) @@ -96,7 +96,7 @@ func TestHandleDefinitionIdentityVerificationIncompleteClaimData(t *testing.T) { mdm := dh.data.(*datamocks.Manager) mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{}, false, nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) @@ -122,7 +122,7 @@ func TestHandleDefinitionIdentityVerificationClaimDataFail(t *testing.T) { mdm := dh.data.(*datamocks.Manager) mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(nil, false, fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -146,7 +146,7 @@ func TestHandleDefinitionIdentityVerificationClaimHashMismatchl(t *testing.T) { mdi := dh.database.(*databasemocks.Plugin) mdi.On("GetMessageByID", ctx, "ns1", claimMsg.Header.ID).Return(claimMsg, nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -167,7 +167,7 @@ func TestHandleDefinitionIdentityVerificationBeforeClaim(t *testing.T) { mdi := dh.database.(*databasemocks.Plugin) mdi.On("GetMessageByID", ctx, "ns1", claimMsg.Header.ID).Return(nil, nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) @@ -188,7 +188,7 @@ func TestHandleDefinitionIdentityVerificationClaimLookupFail(t *testing.T) { mdi := dh.database.(*databasemocks.Plugin) mdi.On("GetMessageByID", ctx, "ns1", claimMsg.Header.ID).Return(nil, fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -207,7 +207,7 @@ func TestHandleDefinitionIdentityVerificationWrongSigner(t *testing.T) { mim := dh.identity.(*identitymanagermocks.Manager) mim.On("CachedIdentityLookupByID", ctx, org1.ID).Return(org1, nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -224,7 +224,7 @@ func TestHandleDefinitionIdentityVerificationCheckParentNotFound(t *testing.T) { mim := dh.identity.(*identitymanagermocks.Manager) mim.On("CachedIdentityLookupByID", ctx, org1.ID).Return(nil, nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -241,7 +241,7 @@ func TestHandleDefinitionIdentityVerificationCheckParentFail(t *testing.T) { mim := dh.identity.(*identitymanagermocks.Manager) mim.On("CachedIdentityLookupByID", ctx, org1.ID).Return(nil, fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -263,7 +263,7 @@ func TestHandleDefinitionIdentityVerificationInvalidPayload(t *testing.T) { Value: fftypes.JSONAnyPtrBytes(b), } - action, err := dh.HandleDefinitionBroadcast(ctx, bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, &core.Message{ Header: core.MessageHeader{ ID: fftypes.NewUUID(), Type: core.MessageTypeBroadcast, @@ -280,7 +280,7 @@ func TestHandleDefinitionIdentityVerificationInvalidData(t *testing.T) { dh, bs := newTestDefinitionHandler(t) ctx := context.Background() - action, err := dh.HandleDefinitionBroadcast(ctx, bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, &core.Message{ Header: core.MessageHeader{ ID: fftypes.NewUUID(), Type: core.MessageTypeBroadcast, diff --git a/internal/definitions/definition_handler_namespace.go b/internal/definitions/definition_handler_namespace.go index 39b951713..9725906a8 100644 --- a/internal/definitions/definition_handler_namespace.go +++ b/internal/definitions/definition_handler_namespace.go @@ -25,7 +25,7 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (dh *definitionHandlers) handleNamespaceBroadcast(ctx context.Context, state DefinitionBatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { +func (dh *definitionHandlers) handleNamespaceBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { var ns core.Namespace if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &ns); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "namespace", msg.Header.ID) diff --git a/internal/definitions/definition_handler_namespace_test.go b/internal/definitions/definition_handler_namespace_test.go index 4f3c3abeb..b62a91a32 100644 --- a/internal/definitions/definition_handler_namespace_test.go +++ b/internal/definitions/definition_handler_namespace_test.go @@ -46,14 +46,14 @@ func TestHandleDefinitionBroadcastNSOk(t *testing.T) { mdi.On("GetNamespace", mock.Anything, "ns1").Return(nil, nil) mdi.On("UpsertNamespace", mock.Anything, mock.Anything, false).Return(nil) mdi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineNamespace, }, }, core.DataArray{data}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) - err = bs.finalizers[0](context.Background()) + err = bs.RunFinalize(context.Background()) assert.NoError(t, err) mdi.AssertExpectations(t) @@ -76,14 +76,14 @@ func TestHandleDefinitionBroadcastNSEventFail(t *testing.T) { mdi.On("GetNamespace", mock.Anything, "ns1").Return(nil, nil) mdi.On("UpsertNamespace", mock.Anything, mock.Anything, false).Return(nil) mdi.On("InsertEvent", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineNamespace, }, }, core.DataArray{data}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) - err = bs.finalizers[0](context.Background()) + err = bs.RunFinalize(context.Background()) assert.EqualError(t, err, "pop") mdi.AssertExpectations(t) @@ -105,7 +105,7 @@ func TestHandleDefinitionBroadcastNSUpsertFail(t *testing.T) { mdi := dh.database.(*databasemocks.Plugin) mdi.On("GetNamespace", mock.Anything, "ns1").Return(nil, nil) mdi.On("UpsertNamespace", mock.Anything, mock.Anything, false).Return(fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineNamespace, }, @@ -120,7 +120,7 @@ func TestHandleDefinitionBroadcastNSUpsertFail(t *testing.T) { func TestHandleDefinitionBroadcastNSMissingData(t *testing.T) { dh, bs := newTestDefinitionHandler(t) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineNamespace, }, @@ -140,7 +140,7 @@ func TestHandleDefinitionBroadcastNSBadID(t *testing.T) { Value: fftypes.JSONAnyPtrBytes(b), } - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineNamespace, }, @@ -157,7 +157,7 @@ func TestHandleDefinitionBroadcastNSBadData(t *testing.T) { Value: fftypes.JSONAnyPtr(`!{json`), } - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineNamespace, }, @@ -182,7 +182,7 @@ func TestHandleDefinitionBroadcastDuplicate(t *testing.T) { mdi := dh.database.(*databasemocks.Plugin) mdi.On("GetNamespace", mock.Anything, "ns1").Return(ns, nil) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineNamespace, }, @@ -213,14 +213,14 @@ func TestHandleDefinitionBroadcastDuplicateOverrideLocal(t *testing.T) { mdi.On("DeleteNamespace", mock.Anything, mock.Anything).Return(nil) mdi.On("UpsertNamespace", mock.Anything, mock.Anything, false).Return(nil) mdi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineNamespace, }, }, core.DataArray{data}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) - err = bs.finalizers[0](context.Background()) + err = bs.RunFinalize(context.Background()) assert.NoError(t, err) mdi.AssertExpectations(t) @@ -243,7 +243,7 @@ func TestHandleDefinitionBroadcastDuplicateOverrideLocalFail(t *testing.T) { mdi := dh.database.(*databasemocks.Plugin) mdi.On("GetNamespace", mock.Anything, "ns1").Return(ns, nil) mdi.On("DeleteNamespace", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineNamespace, }, @@ -270,7 +270,7 @@ func TestHandleDefinitionBroadcastDupCheckFail(t *testing.T) { mdi := dh.database.(*databasemocks.Plugin) mdi.On("GetNamespace", mock.Anything, "ns1").Return(nil, fmt.Errorf("pop")) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineNamespace, }, diff --git a/internal/definitions/definition_handler_network_node.go b/internal/definitions/definition_handler_network_node.go index b739251a8..fe33b8c33 100644 --- a/internal/definitions/definition_handler_network_node.go +++ b/internal/definitions/definition_handler_network_node.go @@ -24,7 +24,7 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (dh *definitionHandlers) handleDeprecatedNodeBroadcast(ctx context.Context, state DefinitionBatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { +func (dh *definitionHandlers) handleDeprecatedNodeBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { var nodeOld core.DeprecatedNode if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &nodeOld); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "node", msg.Header.ID) diff --git a/internal/definitions/definition_handler_network_node_test.go b/internal/definitions/definition_handler_network_node_test.go index bb9005361..95567a944 100644 --- a/internal/definitions/definition_handler_network_node_test.go +++ b/internal/definitions/definition_handler_network_node_test.go @@ -130,13 +130,13 @@ func TestHandleDeprecatedNodeDefinitionOK(t *testing.T) { mdx := dh.exchange.(*dataexchangemocks.Plugin) mdx.On("AddPeer", ctx, node.DX.Endpoint).Return(nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, msg, core.DataArray{data}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, msg, core.DataArray{data}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) - err = bs.preFinalizers[0](ctx) + err = bs.RunPreFinalize(ctx) assert.NoError(t, err) - err = bs.finalizers[0](ctx) + err = bs.RunFinalize(ctx) assert.NoError(t, err) mim.AssertExpectations(t) @@ -149,7 +149,7 @@ func TestHandleDeprecatedNodeDefinitionBadData(t *testing.T) { dh, bs := newTestDefinitionHandler(t) ctx := context.Background() - action, err := dh.handleDeprecatedNodeBroadcast(ctx, bs, &core.Message{}, core.DataArray{}) + action, err := dh.handleDeprecatedNodeBroadcast(ctx, &bs.BatchState, &core.Message{}, core.DataArray{}) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -168,7 +168,7 @@ func TestHandleDeprecatedNodeDefinitionFailOrgLookup(t *testing.T) { Value: node.Owner, }).Return(nil, fmt.Errorf("pop")) - action, err := dh.handleDeprecatedNodeBroadcast(ctx, bs, msg, core.DataArray{data}) + action, err := dh.handleDeprecatedNodeBroadcast(ctx, &bs.BatchState, msg, core.DataArray{data}) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -189,7 +189,7 @@ func TestHandleDeprecatedNodeDefinitionOrgNotFound(t *testing.T) { Value: node.Owner, }).Return(nil, nil) - action, err := dh.handleDeprecatedNodeBroadcast(ctx, bs, msg, core.DataArray{data}) + action, err := dh.handleDeprecatedNodeBroadcast(ctx, &bs.BatchState, msg, core.DataArray{data}) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) diff --git a/internal/definitions/definition_handler_network_org.go b/internal/definitions/definition_handler_network_org.go index a3328a49a..87c7df3a2 100644 --- a/internal/definitions/definition_handler_network_org.go +++ b/internal/definitions/definition_handler_network_org.go @@ -24,7 +24,7 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (dh *definitionHandlers) handleDeprecatedOrganizationBroadcast(ctx context.Context, state DefinitionBatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { +func (dh *definitionHandlers) handleDeprecatedOrganizationBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { var orgOld core.DeprecatedOrganization valid := dh.getSystemBroadcastPayload(ctx, msg, data, &orgOld) diff --git a/internal/definitions/definition_handler_network_org_test.go b/internal/definitions/definition_handler_network_org_test.go index 869fd6e0b..8fe989de1 100644 --- a/internal/definitions/definition_handler_network_org_test.go +++ b/internal/definitions/definition_handler_network_org_test.go @@ -110,11 +110,11 @@ func TestHandleDeprecatedOrgDefinitionOK(t *testing.T) { return event.Type == core.EventTypeIdentityConfirmed })).Return(nil) - action, err := dh.HandleDefinitionBroadcast(ctx, bs, msg, core.DataArray{data}, fftypes.NewUUID()) + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, msg, core.DataArray{data}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) - err = bs.finalizers[0](ctx) + err = bs.RunFinalize(ctx) assert.NoError(t, err) mim.AssertExpectations(t) @@ -125,7 +125,7 @@ func TestHandleDeprecatedOrgDefinitionBadData(t *testing.T) { dh, bs := newTestDefinitionHandler(t) ctx := context.Background() - action, err := dh.handleDeprecatedOrganizationBroadcast(ctx, bs, &core.Message{}, core.DataArray{}) + action, err := dh.handleDeprecatedOrganizationBroadcast(ctx, &bs.BatchState, &core.Message{}, core.DataArray{}) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) diff --git a/internal/definitions/definition_handler_test.go b/internal/definitions/definition_handler_test.go index 8ef28629c..c159e70b3 100644 --- a/internal/definitions/definition_handler_test.go +++ b/internal/definitions/definition_handler_test.go @@ -47,39 +47,24 @@ func newTestDefinitionHandler(t *testing.T) (*definitionHandlers, *testDefinitio } type testDefinitionBatchState struct { - t *testing.T - preFinalizers []func(ctx context.Context) error - finalizers []func(ctx context.Context) error - pendingConfirms map[fftypes.UUID]*core.Message - confirmedDIDClaims []string + core.BatchState + t *testing.T } func newTestDefinitionBatchState(t *testing.T) *testDefinitionBatchState { return &testDefinitionBatchState{ - t: t, - pendingConfirms: make(map[fftypes.UUID]*core.Message), + BatchState: core.BatchState{ + PendingConfirms: make(map[fftypes.UUID]*core.Message), + PreFinalize: make([]func(ctx context.Context) error, 0), + Finalize: make([]func(ctx context.Context) error, 0), + }, + t: t, } } -func (bs *testDefinitionBatchState) AddPreFinalize(pf func(ctx context.Context) error) { - bs.preFinalizers = append(bs.preFinalizers, pf) -} - -func (bs *testDefinitionBatchState) AddFinalize(pf func(ctx context.Context) error) { - bs.finalizers = append(bs.finalizers, pf) -} - -func (bs *testDefinitionBatchState) GetPendingConfirm() map[fftypes.UUID]*core.Message { - return bs.pendingConfirms -} - -func (bs *testDefinitionBatchState) DIDClaimConfirmed(did string) { - bs.confirmedDIDClaims = append(bs.confirmedDIDClaims, did) -} - func (bs *testDefinitionBatchState) assertNoFinalizers() { - assert.Empty(bs.t, bs.preFinalizers) - assert.Empty(bs.t, bs.finalizers) + assert.Empty(bs.t, bs.PreFinalize) + assert.Empty(bs.t, bs.Finalize) } func TestInitFail(t *testing.T) { @@ -89,7 +74,7 @@ func TestInitFail(t *testing.T) { func TestHandleDefinitionBroadcastUnknown(t *testing.T) { dh, bs := newTestDefinitionHandler(t) - action, err := dh.HandleDefinitionBroadcast(context.Background(), bs, &core.Message{ + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: "unknown", }, diff --git a/internal/definitions/definition_handler_tokenpool.go b/internal/definitions/definition_handler_tokenpool.go index a8e12f36d..bd05291b0 100644 --- a/internal/definitions/definition_handler_tokenpool.go +++ b/internal/definitions/definition_handler_tokenpool.go @@ -26,7 +26,7 @@ import ( "github.com/hyperledger/firefly/pkg/database" ) -func (dh *definitionHandlers) handleTokenPoolBroadcast(ctx context.Context, state DefinitionBatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { +func (dh *definitionHandlers) handleTokenPoolBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { var announce core.TokenPoolAnnouncement if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &announce); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "token pool", msg.Header.ID) diff --git a/internal/definitions/definition_handler_tokenpool_test.go b/internal/definitions/definition_handler_tokenpool_test.go index d96361aa1..a5d99fe8f 100644 --- a/internal/definitions/definition_handler_tokenpool_test.go +++ b/internal/definitions/definition_handler_tokenpool_test.go @@ -82,11 +82,11 @@ func TestHandleDefinitionBroadcastTokenPoolActivateOK(t *testing.T) { })).Return(nil) mam.On("ActivateTokenPool", context.Background(), mock.AnythingOfType("*core.TokenPool")).Return(nil) - action, err := sh.HandleDefinitionBroadcast(context.Background(), bs, msg, data, fftypes.NewUUID()) + action, err := sh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, msg, data, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionWait, CustomCorrelator: pool.ID}, action) assert.NoError(t, err) - err = bs.preFinalizers[0](context.Background()) + err = bs.RunPreFinalize(context.Background()) assert.NoError(t, err) mdi.AssertExpectations(t) @@ -103,7 +103,7 @@ func TestHandleDefinitionBroadcastTokenPoolGetPoolFail(t *testing.T) { mdi := sh.database.(*databasemocks.Plugin) mdi.On("GetTokenPoolByID", context.Background(), "ns1", pool.ID).Return(nil, fmt.Errorf("pop")) - action, err := sh.HandleDefinitionBroadcast(context.Background(), bs, msg, data, fftypes.NewUUID()) + action, err := sh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, msg, data, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.EqualError(t, err, "pop") @@ -127,11 +127,11 @@ func TestHandleDefinitionBroadcastTokenPoolExisting(t *testing.T) { })).Return(nil) mam.On("ActivateTokenPool", context.Background(), mock.AnythingOfType("*core.TokenPool")).Return(nil) - action, err := sh.HandleDefinitionBroadcast(context.Background(), bs, msg, data, fftypes.NewUUID()) + action, err := sh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, msg, data, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionWait, CustomCorrelator: pool.ID}, action) assert.NoError(t, err) - err = bs.preFinalizers[0](context.Background()) + err = bs.RunPreFinalize(context.Background()) assert.NoError(t, err) } @@ -150,7 +150,7 @@ func TestHandleDefinitionBroadcastTokenPoolExistingConfirmed(t *testing.T) { mdi := sh.database.(*databasemocks.Plugin) mdi.On("GetTokenPoolByID", context.Background(), "ns1", pool.ID).Return(existing, nil) - action, err := sh.HandleDefinitionBroadcast(context.Background(), bs, msg, data, fftypes.NewUUID()) + action, err := sh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, msg, data, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm, CustomCorrelator: pool.ID}, action) assert.NoError(t, err) @@ -171,7 +171,7 @@ func TestHandleDefinitionBroadcastTokenPoolIDMismatch(t *testing.T) { return *p.ID == *pool.ID && p.Message == msg.Header.ID })).Return(database.IDMismatch) - action, err := sh.HandleDefinitionBroadcast(context.Background(), bs, msg, data, fftypes.NewUUID()) + action, err := sh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, msg, data, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject, CustomCorrelator: pool.ID}, action) assert.Error(t, err) @@ -193,7 +193,7 @@ func TestHandleDefinitionBroadcastTokenPoolFailUpsert(t *testing.T) { return *p.ID == *pool.ID && p.Message == msg.Header.ID })).Return(fmt.Errorf("pop")) - action, err := sh.HandleDefinitionBroadcast(context.Background(), bs, msg, data, fftypes.NewUUID()) + action, err := sh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, msg, data, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.EqualError(t, err, "pop") @@ -217,11 +217,11 @@ func TestHandleDefinitionBroadcastTokenPoolActivateFail(t *testing.T) { })).Return(nil) mam.On("ActivateTokenPool", context.Background(), mock.AnythingOfType("*core.TokenPool")).Return(fmt.Errorf("pop")) - action, err := sh.HandleDefinitionBroadcast(context.Background(), bs, msg, data, fftypes.NewUUID()) + action, err := sh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, msg, data, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionWait, CustomCorrelator: pool.ID}, action) assert.NoError(t, err) - err = bs.preFinalizers[0](context.Background()) + err = bs.RunPreFinalize(context.Background()) assert.EqualError(t, err, "pop") mdi.AssertExpectations(t) @@ -236,7 +236,7 @@ func TestHandleDefinitionBroadcastTokenPoolValidateFail(t *testing.T) { msg, data, err := buildPoolDefinitionMessage(announce) assert.NoError(t, err) - action, err := sh.HandleDefinitionBroadcast(context.Background(), bs, msg, data, fftypes.NewUUID()) + action, err := sh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, msg, data, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) bs.assertNoFinalizers() @@ -252,7 +252,7 @@ func TestHandleDefinitionBroadcastTokenPoolBadMessage(t *testing.T) { }, } - action, err := sh.HandleDefinitionBroadcast(context.Background(), bs, msg, nil, fftypes.NewUUID()) + action, err := sh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, msg, nil, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) bs.assertNoFinalizers() diff --git a/internal/events/aggregator.go b/internal/events/aggregator.go index de3a771c9..345261e13 100644 --- a/internal/events/aggregator.go +++ b/internal/events/aggregator.go @@ -453,19 +453,19 @@ func (ag *aggregator) processMessage(ctx context.Context, manifest *core.BatchMa l.Errorf("Message '%s' in batch '%s' has invalid pin at index %d: '%s'", msg.Header.ID, manifest.ID, i, pinStr) return nil } - nextPin, err := state.CheckMaskedContextReady(ctx, msg, msg.Header.Topics[i], pin.Sequence, &msgContext, nonceStr) + nextPin, err := state.checkMaskedContextReady(ctx, msg, msg.Header.Topics[i], pin.Sequence, &msgContext, nonceStr) if err != nil || nextPin == nil { return err } nextPins = append(nextPins, nextPin) } } else { - for i, topic := range msg.Header.Topics { + for _, topic := range msg.Header.Topics { h := sha256.New() h.Write([]byte(topic)) msgContext := fftypes.HashResult(h) unmaskedContexts = append(unmaskedContexts, msgContext) - ready, err := state.CheckUnmaskedContextReady(ctx, msgContext, msg, msg.Header.Topics[i], pin.Sequence) + ready, err := state.checkUnmaskedContextReady(ctx, msgContext, msg, pin.Sequence) if err != nil || !ready { return err } @@ -490,7 +490,7 @@ func (ag *aggregator) processMessage(ctx context.Context, manifest *core.BatchMa for _, np := range nextPins { np.IncrementNextPin(ctx) } - state.MarkMessageDispatched(ctx, manifest.ID, msg, msgBaseIndex, newState) + state.markMessageDispatched(manifest.ID, msg, msgBaseIndex, newState) } else { for _, unmaskedContext := range unmaskedContexts { state.SetContextBlockedBy(ctx, *unmaskedContext, pin.Sequence) @@ -534,7 +534,7 @@ func (ag *aggregator) attemptMessageDispatch(ctx context.Context, msg *core.Mess case msg.Header.Type == core.MessageTypeDefinition: // We handle definition events in-line on the aggregator, as it would be confusing for apps to be // dispatched subsequent events before we have processed the definition events they depend on. - handlerResult, err := ag.definitions.HandleDefinitionBroadcast(ctx, state, msg, data, tx) + handlerResult, err := ag.definitions.HandleDefinitionBroadcast(ctx, &state.BatchState, msg, data, tx) log.L(ctx).Infof("Result of definition broadcast '%s' [%s]: %s", msg.Header.Tag, msg.Header.ID, handlerResult.Action) if handlerResult.Action == definitions.ActionRetry { return "", false, err @@ -561,7 +561,7 @@ func (ag *aggregator) attemptMessageDispatch(ctx context.Context, msg *core.Mess newState = core.MessageStateConfirmed eventType := core.EventTypeMessageConfirmed if valid { - state.pendingConfirms[*msg.Header.ID] = msg + state.AddPendingConfirm(msg.Header.ID, msg) } else { newState = core.MessageStateRejected eventType = core.EventTypeMessageRejected diff --git a/internal/events/aggregator_batch_state.go b/internal/events/aggregator_batch_state.go index 3dc54708a..5448c49f5 100644 --- a/internal/events/aggregator_batch_state.go +++ b/internal/events/aggregator_batch_state.go @@ -40,10 +40,9 @@ func newBatchState(ag *aggregator) *batchState { maskedContexts: make(map[fftypes.Bytes32]*nextPinGroupState), unmaskedContexts: make(map[fftypes.Bytes32]*contextState), dispatchedMessages: make([]*dispatchedMessage, 0), - pendingConfirms: make(map[fftypes.UUID]*core.Message), - - PreFinalize: make([]func(ctx context.Context) error, 0), - Finalize: make([]func(ctx context.Context) error, 0), + BatchState: core.BatchState{ + PendingConfirms: make(map[fftypes.UUID]*core.Message), + }, } } @@ -96,6 +95,8 @@ type dispatchedMessage struct { // Runs in a database operation group/tranaction, which will be the same as phase (1) if there // are no pre-finalize handlers registered. type batchState struct { + core.BatchState + namespace string database database.Plugin messaging privatemessaging.Manager @@ -103,67 +104,26 @@ type batchState struct { maskedContexts map[fftypes.Bytes32]*nextPinGroupState unmaskedContexts map[fftypes.Bytes32]*contextState dispatchedMessages []*dispatchedMessage - pendingConfirms map[fftypes.UUID]*core.Message - confirmedDIDClaims []string - - // PreFinalize callbacks may perform blocking actions (possibly to an external connector) - // - Will execute after all batch messages have been processed - // - Will execute outside database RunAsGroup - // - If any PreFinalize callback errors out, batch will be aborted and retried - PreFinalize []func(ctx context.Context) error - - // Finalize callbacks may perform final, non-idempotent database operations (such as inserting Events) - // - Will execute after all batch messages have been processed and any PreFinalize callbacks have succeeded - // - Will execute inside database RunAsGroup - // - If any Finalize callback errors out, batch will be aborted and retried (small chance of duplicate execution here) - Finalize []func(ctx context.Context) error -} - -func (bs *batchState) AddPreFinalize(action func(ctx context.Context) error) { - if action != nil { - bs.PreFinalize = append(bs.PreFinalize, action) - } -} - -func (bs *batchState) AddFinalize(action func(ctx context.Context) error) { - if action != nil { - bs.Finalize = append(bs.Finalize, action) - } -} - -func (bs *batchState) GetPendingConfirm() map[fftypes.UUID]*core.Message { - return bs.pendingConfirms } func (bs *batchState) RunPreFinalize(ctx context.Context) error { - for _, action := range bs.PreFinalize { - if err := action(ctx); err != nil { - return err - } - } - return nil + return bs.BatchState.RunPreFinalize(ctx) } func (bs *batchState) RunFinalize(ctx context.Context) error { - for _, action := range bs.Finalize { - if err := action(ctx); err != nil { - return err - } + if err := bs.BatchState.RunFinalize(ctx); err != nil { + return err } return bs.flushPins(ctx) } -func (bs *batchState) DIDClaimConfirmed(did string) { - bs.confirmedDIDClaims = append(bs.confirmedDIDClaims, did) -} - func (bs *batchState) queueRewinds(ag *aggregator) { - for _, did := range bs.confirmedDIDClaims { + for _, did := range bs.ConfirmedDIDClaims { ag.queueDIDRewind(did) } } -func (bs *batchState) CheckUnmaskedContextReady(ctx context.Context, contextUnmasked *fftypes.Bytes32, msg *core.Message, topic string, firstMsgPinSequence int64) (bool, error) { +func (bs *batchState) checkUnmaskedContextReady(ctx context.Context, contextUnmasked *fftypes.Bytes32, msg *core.Message, firstMsgPinSequence int64) (bool, error) { ucs, found := bs.unmaskedContexts[*contextUnmasked] if !found { @@ -195,7 +155,7 @@ func (bs *batchState) CheckUnmaskedContextReady(ctx context.Context, contextUnma } -func (bs *batchState) CheckMaskedContextReady(ctx context.Context, msg *core.Message, topic string, firstMsgPinSequence int64, pin *fftypes.Bytes32, nonceStr string) (*nextPinState, error) { +func (bs *batchState) checkMaskedContextReady(ctx context.Context, msg *core.Message, topic string, firstMsgPinSequence int64, pin *fftypes.Bytes32, nonceStr string) (*nextPinState, error) { l := log.L(ctx) // For masked pins, we can only process if: @@ -240,7 +200,7 @@ func (bs *batchState) CheckMaskedContextReady(ctx context.Context, msg *core.Mes }, err } -func (bs *batchState) MarkMessageDispatched(ctx context.Context, batchID *fftypes.UUID, msg *core.Message, msgBaseIndex int64, newState core.MessageState) { +func (bs *batchState) markMessageDispatched(batchID *fftypes.UUID, msg *core.Message, msgBaseIndex int64, newState core.MessageState) { bs.dispatchedMessages = append(bs.dispatchedMessages, &dispatchedMessage{ batchID: batchID, msgID: msg.Header.ID, diff --git a/internal/events/aggregator_batch_state_test.go b/internal/events/aggregator_batch_state_test.go index e0f267626..7735e55ed 100644 --- a/internal/events/aggregator_batch_state_test.go +++ b/internal/events/aggregator_batch_state_test.go @@ -36,7 +36,7 @@ func TestFlushPinsFailUpdatePins(t *testing.T) { mdi := ag.database.(*databasemocks.Plugin) mdi.On("UpdatePins", ag.ctx, mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - bs.MarkMessageDispatched(ag.ctx, fftypes.NewUUID(), &core.Message{ + bs.markMessageDispatched(fftypes.NewUUID(), &core.Message{ Header: core.MessageHeader{ ID: fftypes.NewUUID(), Topics: core.FFStringArray{"topic1"}, @@ -60,7 +60,7 @@ func TestFlushPinsFailUpdateMessages(t *testing.T) { mdm := ag.data.(*datamocks.Manager) mdm.On("UpdateMessageStateIfCached", ag.ctx, msgID, core.MessageStateConfirmed, mock.Anything).Return() - bs.MarkMessageDispatched(ag.ctx, fftypes.NewUUID(), &core.Message{ + bs.markMessageDispatched(fftypes.NewUUID(), &core.Message{ Header: core.MessageHeader{ ID: msgID, Topics: core.FFStringArray{"topic1"}, @@ -80,7 +80,7 @@ func TestSetContextBlockedByNoState(t *testing.T) { unmaskedContext := fftypes.NewRandB32() bs.SetContextBlockedBy(ag.ctx, *unmaskedContext, 10) - ready, err := bs.CheckUnmaskedContextReady(ag.ctx, unmaskedContext, &core.Message{}, "topic1", 1) + ready, err := bs.checkUnmaskedContextReady(ag.ctx, unmaskedContext, &core.Message{}, 1) assert.NoError(t, err) assert.False(t, ready) } diff --git a/internal/events/aggregator_test.go b/internal/events/aggregator_test.go index 5cc20c1a9..cdf59bba9 100644 --- a/internal/events/aggregator_test.go +++ b/internal/events/aggregator_test.go @@ -261,7 +261,7 @@ func TestAggregationMaskedZeroNonceMatch(t *testing.T) { err = bs.RunFinalize(ag.ctx) assert.NoError(t, err) - assert.NotNil(t, bs.GetPendingConfirm()[*msgID]) + assert.NotNil(t, bs.PendingConfirms[*msgID]) // Confirm the offset assert.Equal(t, int64(10001), <-ag.eventPoller.offsetCommitted) @@ -1130,7 +1130,7 @@ func TestCheckMaskedContextReadyMismatchedAuthor(t *testing.T) { }, nil, nil) bs := newBatchState(ag) - _, err := bs.CheckMaskedContextReady(ag.ctx, &core.Message{ + _, err := bs.checkMaskedContextReady(ag.ctx, &core.Message{ Header: core.MessageHeader{ ID: fftypes.NewUUID(), Group: fftypes.NewRandB32(), @@ -2131,7 +2131,7 @@ func TestProcessWithBatchRewindsSuccess(t *testing.T) { } err := ag.processWithBatchState(func(ctx context.Context, actions *batchState) error { - actions.DIDClaimConfirmed("did:firefly:org/test") + actions.AddConfirmedDIDClaim("did:firefly:org/test") return nil }) assert.NoError(t, err) diff --git a/mocks/definitionsmocks/definition_handler.go b/mocks/definitionsmocks/definition_handler.go index 0128b62b1..6e5a74d99 100644 --- a/mocks/definitionsmocks/definition_handler.go +++ b/mocks/definitionsmocks/definition_handler.go @@ -19,18 +19,18 @@ type DefinitionHandler struct { } // HandleDefinitionBroadcast provides a mock function with given fields: ctx, state, msg, data, tx -func (_m *DefinitionHandler) HandleDefinitionBroadcast(ctx context.Context, state definitions.DefinitionBatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (definitions.HandlerResult, error) { +func (_m *DefinitionHandler) HandleDefinitionBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (definitions.HandlerResult, error) { ret := _m.Called(ctx, state, msg, data, tx) var r0 definitions.HandlerResult - if rf, ok := ret.Get(0).(func(context.Context, definitions.DefinitionBatchState, *core.Message, core.DataArray, *fftypes.UUID) definitions.HandlerResult); ok { + if rf, ok := ret.Get(0).(func(context.Context, *core.BatchState, *core.Message, core.DataArray, *fftypes.UUID) definitions.HandlerResult); ok { r0 = rf(ctx, state, msg, data, tx) } else { r0 = ret.Get(0).(definitions.HandlerResult) } var r1 error - if rf, ok := ret.Get(1).(func(context.Context, definitions.DefinitionBatchState, *core.Message, core.DataArray, *fftypes.UUID) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *core.BatchState, *core.Message, core.DataArray, *fftypes.UUID) error); ok { r1 = rf(ctx, state, msg, data, tx) } else { r1 = ret.Error(1) diff --git a/pkg/core/batch_state.go b/pkg/core/batch_state.go new file mode 100644 index 000000000..c4c3b931e --- /dev/null +++ b/pkg/core/batch_state.go @@ -0,0 +1,79 @@ +// 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 core + +import ( + "context" + + "github.com/hyperledger/firefly-common/pkg/fftypes" +) + +// BatchState tracks the state between definition handlers that run in-line on the pin processing route in the aggregator +// as part of a batch of pins. They might have complex API calls and interdependencies that need to be managed via this state. +type BatchState struct { + // PreFinalize callbacks may perform blocking actions (possibly to an external connector) + // - Will execute after all batch messages have been processed + // - Will execute outside database RunAsGroup + // - If any PreFinalize callback errors out, batch will be aborted and retried + PreFinalize []func(ctx context.Context) error + + // Finalize callbacks may perform final, non-idempotent database operations (such as inserting Events) + // - Will execute after all batch messages have been processed and any PreFinalize callbacks have succeeded + // - Will execute inside database RunAsGroup + // - If any Finalize callback errors out, batch will be aborted and retried (small chance of duplicate execution here) + Finalize []func(ctx context.Context) error + + // PendingConfirms are messages that are pending confirmation after already being processed in this batch + PendingConfirms map[fftypes.UUID]*Message + + // ConfirmedDIDClaims are DID claims locked in within this batch + ConfirmedDIDClaims []string +} + +func (bs *BatchState) AddPreFinalize(action func(ctx context.Context) error) { + bs.PreFinalize = append(bs.PreFinalize, action) +} + +func (bs *BatchState) AddFinalize(action func(ctx context.Context) error) { + bs.Finalize = append(bs.Finalize, action) +} + +func (bs *BatchState) AddPendingConfirm(id *fftypes.UUID, message *Message) { + bs.PendingConfirms[*id] = message +} + +func (bs *BatchState) AddConfirmedDIDClaim(did string) { + bs.ConfirmedDIDClaims = append(bs.ConfirmedDIDClaims, did) +} + +func (bs *BatchState) RunPreFinalize(ctx context.Context) error { + for _, action := range bs.PreFinalize { + if err := action(ctx); err != nil { + return err + } + } + return nil +} + +func (bs *BatchState) RunFinalize(ctx context.Context) error { + for _, action := range bs.Finalize { + if err := action(ctx); err != nil { + return err + } + } + return nil +} diff --git a/pkg/core/batch_state_test.go b/pkg/core/batch_state_test.go new file mode 100644 index 000000000..cf8c68c59 --- /dev/null +++ b/pkg/core/batch_state_test.go @@ -0,0 +1,68 @@ +// 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 core + +import ( + "context" + "fmt" + "testing" + + "github.com/hyperledger/firefly-common/pkg/fftypes" + "github.com/stretchr/testify/assert" +) + +func TestBatchStateFinalizers(t *testing.T) { + bs := BatchState{} + + run1 := false + bs.AddPreFinalize(func(ctx context.Context) error { run1 = true; return nil }) + run2 := false + bs.AddFinalize(func(ctx context.Context) error { run2 = true; return nil }) + + bs.RunPreFinalize(context.Background()) + bs.RunFinalize(context.Background()) + assert.True(t, run1) + assert.True(t, run2) +} + +func TestBatchStateFinalizerErrors(t *testing.T) { + bs := BatchState{} + + bs.AddPreFinalize(func(ctx context.Context) error { return fmt.Errorf("pop") }) + bs.AddFinalize(func(ctx context.Context) error { return fmt.Errorf("pop") }) + + err := bs.RunPreFinalize(context.Background()) + assert.EqualError(t, err, "pop") + err = bs.RunFinalize(context.Background()) + assert.EqualError(t, err, "pop") +} + +func TestBatchStateIdentities(t *testing.T) { + bs := BatchState{ + PendingConfirms: make(map[fftypes.UUID]*Message), + } + + id := fftypes.NewUUID() + msg := &Message{} + bs.AddPendingConfirm(id, msg) + + did := "did:firefly:id1" + bs.AddConfirmedDIDClaim(did) + + assert.Equal(t, msg, bs.PendingConfirms[*id]) + assert.Equal(t, bs.ConfirmedDIDClaims[0], did) +} From 8c3a4044610b164f66b1b9900cad8773bf1f2405 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Thu, 23 Jun 2022 11:23:02 -0400 Subject: [PATCH 04/27] Conditionally initialize multiparty messaging managers If multiparty mode is disabled for a given namespace, do not initialize the multipary manager or any of the messaging managers. Adjust other components and routes to deal with these managers potentially being nil. Signed-off-by: Andrew Richardson --- internal/apiserver/route_get_group_by_id.go | 8 +- internal/apiserver/route_get_groups.go | 7 +- .../route_get_status_batchmanager.go | 8 +- .../route_post_new_message_broadcast.go | 7 +- .../route_post_new_message_private.go | 8 +- internal/assets/manager.go | 6 +- internal/assets/token_transfer.go | 6 + internal/coremsgs/en_error_messages.go | 1 + internal/data/blobstore.go | 16 +- internal/data/data_manager.go | 14 +- internal/data/data_manager_test.go | 6 +- internal/definitions/definition_handler.go | 4 +- .../definition_handler_identity_claim.go | 4 + internal/defsender/sender.go | 8 +- internal/events/batch_pin_complete.go | 4 + internal/events/dx_callbacks.go | 4 + internal/events/event_dispatcher.go | 4 +- internal/events/event_manager.go | 14 +- internal/events/event_manager_test.go | 9 +- internal/events/network_action.go | 5 + internal/events/network_action_test.go | 14 ++ internal/events/reply_sender.go | 13 +- internal/events/ss_callbacks.go | 5 + internal/events/ss_callbacks_test.go | 10 +- internal/events/subscription_manager.go | 4 +- internal/identity/identitymanager.go | 4 +- internal/networkmap/manager.go | 6 +- internal/networkmap/register_node.go | 6 + internal/orchestrator/bound_callbacks.go | 10 +- internal/orchestrator/bound_callbacks_test.go | 4 +- internal/orchestrator/message.go | 6 +- internal/orchestrator/orchestrator.go | 151 ++++++++++-------- internal/orchestrator/orchestrator_test.go | 14 +- internal/shareddownload/download_manager.go | 2 +- 34 files changed, 251 insertions(+), 141 deletions(-) diff --git a/internal/apiserver/route_get_group_by_id.go b/internal/apiserver/route_get_group_by_id.go index 4ceaeb526..198fe330f 100644 --- a/internal/apiserver/route_get_group_by_id.go +++ b/internal/apiserver/route_get_group_by_id.go @@ -20,6 +20,7 @@ import ( "net/http" "github.com/hyperledger/firefly-common/pkg/ffapi" + "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/pkg/core" ) @@ -38,8 +39,11 @@ var getGroupByHash = &ffapi.Route{ JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { - output, err = cr.or.PrivateMessaging().GetGroupByID(cr.ctx, r.PP["hash"]) - return output, err + pm := cr.or.PrivateMessaging() + if pm == nil { + return nil, i18n.NewError(cr.ctx, coremsgs.MsgActionOnlyValidMultiparty) + } + return pm.GetGroupByID(cr.ctx, r.PP["hash"]) }, }, } diff --git a/internal/apiserver/route_get_groups.go b/internal/apiserver/route_get_groups.go index 1972d3e70..cf75d4ee6 100644 --- a/internal/apiserver/route_get_groups.go +++ b/internal/apiserver/route_get_groups.go @@ -20,6 +20,7 @@ import ( "net/http" "github.com/hyperledger/firefly-common/pkg/ffapi" + "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/pkg/core" "github.com/hyperledger/firefly/pkg/database" @@ -38,7 +39,11 @@ var getGroups = &ffapi.Route{ Extensions: &coreExtensions{ FilterFactory: database.GroupQueryFactory, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { - return filterResult(cr.or.PrivateMessaging().GetGroups(cr.ctx, cr.filter)) + pm := cr.or.PrivateMessaging() + if pm == nil { + return nil, i18n.NewError(cr.ctx, coremsgs.MsgActionOnlyValidMultiparty) + } + return filterResult(pm.GetGroups(cr.ctx, cr.filter)) }, }, } diff --git a/internal/apiserver/route_get_status_batchmanager.go b/internal/apiserver/route_get_status_batchmanager.go index 50979fed2..ff7688a6c 100644 --- a/internal/apiserver/route_get_status_batchmanager.go +++ b/internal/apiserver/route_get_status_batchmanager.go @@ -20,6 +20,7 @@ import ( "net/http" "github.com/hyperledger/firefly-common/pkg/ffapi" + "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/batch" "github.com/hyperledger/firefly/internal/coremsgs" ) @@ -36,8 +37,11 @@ var getStatusBatchManager = &ffapi.Route{ JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { - output = cr.or.BatchManager().Status() - return output, nil + bm := cr.or.BatchManager() + if bm == nil { + return nil, i18n.NewError(cr.ctx, coremsgs.MsgActionOnlyValidMultiparty) + } + return bm.Status(), nil }, }, } diff --git a/internal/apiserver/route_post_new_message_broadcast.go b/internal/apiserver/route_post_new_message_broadcast.go index bf587cd0e..b287e5152 100644 --- a/internal/apiserver/route_post_new_message_broadcast.go +++ b/internal/apiserver/route_post_new_message_broadcast.go @@ -21,6 +21,7 @@ import ( "strings" "github.com/hyperledger/firefly-common/pkg/ffapi" + "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/pkg/core" ) @@ -41,7 +42,11 @@ var postNewMessageBroadcast = &ffapi.Route{ CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) - output, err = cr.or.Broadcast().BroadcastMessage(cr.ctx, r.Input.(*core.MessageInOut), waitConfirm) + bm := cr.or.Broadcast() + if bm == nil { + return nil, i18n.NewError(cr.ctx, coremsgs.MsgActionOnlyValidMultiparty) + } + output, err = bm.BroadcastMessage(cr.ctx, r.Input.(*core.MessageInOut), waitConfirm) return output, err }, }, diff --git a/internal/apiserver/route_post_new_message_private.go b/internal/apiserver/route_post_new_message_private.go index 181c03988..8a493376f 100644 --- a/internal/apiserver/route_post_new_message_private.go +++ b/internal/apiserver/route_post_new_message_private.go @@ -21,6 +21,7 @@ import ( "strings" "github.com/hyperledger/firefly-common/pkg/ffapi" + "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/pkg/core" ) @@ -41,8 +42,11 @@ var postNewMessagePrivate = &ffapi.Route{ CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) - output, err = cr.or.PrivateMessaging().SendMessage(cr.ctx, r.Input.(*core.MessageInOut), waitConfirm) - return output, err + pm := cr.or.PrivateMessaging() + if pm == nil { + return nil, i18n.NewError(cr.ctx, coremsgs.MsgActionOnlyValidMultiparty) + } + return pm.SendMessage(cr.ctx, r.Input.(*core.MessageInOut), waitConfirm) }, }, } diff --git a/internal/assets/manager.go b/internal/assets/manager.go index 6c028c1f8..2d9228439 100644 --- a/internal/assets/manager.go +++ b/internal/assets/manager.go @@ -76,8 +76,8 @@ type assetManager struct { txHelper txcommon.Helper identity identity.Manager syncasync syncasync.Bridge - broadcast broadcast.Manager - messaging privatemessaging.Manager + broadcast broadcast.Manager // optional + messaging privatemessaging.Manager // optional tokens map[string]tokens.Plugin metrics metrics.Manager operations operations.Manager @@ -85,7 +85,7 @@ type assetManager struct { } 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) { - if di == nil || im == nil || sa == nil || bm == nil || pm == nil || ti == nil || mm == nil || om == nil { + if di == nil || im == nil || sa == nil || ti == nil || mm == nil || om == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "AssetManager") } am := &assetManager{ diff --git a/internal/assets/token_transfer.go b/internal/assets/token_transfer.go index 52ad2e12e..c2ce91952 100644 --- a/internal/assets/token_transfer.go +++ b/internal/assets/token_transfer.go @@ -270,8 +270,14 @@ func (s *transferSender) buildTransferMessage(ctx context.Context, in *core.Mess } switch in.Header.Type { case core.MessageTypeTransferBroadcast: + if s.mgr.broadcast == nil { + return nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + } return s.mgr.broadcast.NewBroadcast(in), nil case core.MessageTypeTransferPrivate: + if s.mgr.messaging == nil { + return nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + } return s.mgr.messaging.NewMessage(in), nil default: return nil, i18n.NewError(ctx, coremsgs.MsgInvalidMessageType, allowedTypes) diff --git a/internal/coremsgs/en_error_messages.go b/internal/coremsgs/en_error_messages.go index 64dfd5840..33c8ef61e 100644 --- a/internal/coremsgs/en_error_messages.go +++ b/internal/coremsgs/en_error_messages.go @@ -252,4 +252,5 @@ var ( MsgDefRejectedHashMismatch = ffe("FF10410", "Rejected %s '%s' - hash mismatch: %s != %s") MsgInvalidNamespaceUUID = ffe("FF10411", "Expected 'namespace:' prefix on ID '%s'", 400) MsgSubscriptionIDInvalid = ffe("FF10412", "Invalid subscription ID: %s") + MsgActionOnlyValidMultiparty = ffe("FF10413", "This action is only valid in a multiparty namespace", 400) ) diff --git a/internal/data/blobstore.go b/internal/data/blobstore.go index f541de457..0fd6387be 100644 --- a/internal/data/blobstore.go +++ b/internal/data/blobstore.go @@ -31,14 +31,12 @@ import ( "github.com/hyperledger/firefly/pkg/core" "github.com/hyperledger/firefly/pkg/database" "github.com/hyperledger/firefly/pkg/dataexchange" - "github.com/hyperledger/firefly/pkg/sharedstorage" ) type blobStore struct { - dm *dataManager - sharedstorage sharedstorage.Plugin - database database.Plugin - exchange dataexchange.Plugin + dm *dataManager + database database.Plugin + exchange dataexchange.Plugin // optional } func (bs *blobStore) uploadVerifyBlob(ctx context.Context, id *fftypes.UUID, reader io.Reader) (hash *fftypes.Bytes32, written int64, payloadRef string, err error) { @@ -81,6 +79,10 @@ func (bs *blobStore) uploadVerifyBlob(ctx context.Context, id *fftypes.UUID, rea func (bs *blobStore) UploadBlob(ctx context.Context, inData *core.DataRefOrValue, mpart *ffapi.Multipart, autoMeta bool) (*core.Data, error) { + if bs.exchange == nil { + return nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + } + data := &core.Data{ ID: fftypes.NewUUID(), Namespace: bs.dm.namespace, @@ -144,6 +146,10 @@ func (bs *blobStore) UploadBlob(ctx context.Context, inData *core.DataRefOrValue func (bs *blobStore) DownloadBlob(ctx context.Context, dataID string) (*core.Blob, io.ReadCloser, error) { + if bs.exchange == nil { + return nil, nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + } + id, err := fftypes.ParseUUID(ctx, dataID) if err != nil { return nil, nil, err diff --git a/internal/data/data_manager.go b/internal/data/data_manager.go index f432a8557..398c3260b 100644 --- a/internal/data/data_manager.go +++ b/internal/data/data_manager.go @@ -32,7 +32,6 @@ import ( "github.com/hyperledger/firefly/pkg/core" "github.com/hyperledger/firefly/pkg/database" "github.com/hyperledger/firefly/pkg/dataexchange" - "github.com/hyperledger/firefly/pkg/sharedstorage" "github.com/karlseguin/ccache" ) @@ -59,7 +58,6 @@ type dataManager struct { blobStore namespace string database database.Plugin - exchange dataexchange.Plugin validatorCache *ccache.Cache validatorCacheTTL time.Duration messageCache *ccache.Cache @@ -95,22 +93,20 @@ const ( CRORequireBatchID ) -func NewDataManager(ctx context.Context, ns string, di database.Plugin, pi sharedstorage.Plugin, dx dataexchange.Plugin) (Manager, error) { - if di == nil || pi == nil || dx == nil { +func NewDataManager(ctx context.Context, ns string, di database.Plugin, dx dataexchange.Plugin) (Manager, error) { + if di == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "DataManager") } dm := &dataManager{ namespace: ns, database: di, - exchange: dx, validatorCacheTTL: config.GetDuration(coreconfig.ValidatorCacheTTL), messageCacheTTL: config.GetDuration(coreconfig.MessageCacheTTL), } dm.blobStore = blobStore{ - dm: dm, - database: di, - sharedstorage: pi, - exchange: dx, + dm: dm, + database: di, + exchange: dx, } dm.validatorCache = ccache.New( // We use a LRU cache with a size-aware max diff --git a/internal/data/data_manager_test.go b/internal/data/data_manager_test.go index 78a6ca2c3..7870cd85a 100644 --- a/internal/data/data_manager_test.go +++ b/internal/data/data_manager_test.go @@ -26,7 +26,6 @@ import ( "github.com/hyperledger/firefly/internal/coreconfig" "github.com/hyperledger/firefly/mocks/databasemocks" "github.com/hyperledger/firefly/mocks/dataexchangemocks" - "github.com/hyperledger/firefly/mocks/sharedstoragemocks" "github.com/hyperledger/firefly/pkg/core" "github.com/hyperledger/firefly/pkg/database" "github.com/stretchr/testify/assert" @@ -42,8 +41,7 @@ func newTestDataManager(t *testing.T) (*dataManager, context.Context, func()) { Concurrency: true, }) mdx := &dataexchangemocks.Plugin{} - mps := &sharedstoragemocks.Plugin{} - dm, err := NewDataManager(ctx, "ns1", mdi, mps, mdx) + dm, err := NewDataManager(ctx, "ns1", mdi, mdx) assert.NoError(t, err) return dm.(*dataManager), ctx, func() { cancel() @@ -213,7 +211,7 @@ func TestWriteNewMessageE2E(t *testing.T) { } func TestInitBadDeps(t *testing.T) { - _, err := NewDataManager(context.Background(), "", nil, nil, nil) + _, err := NewDataManager(context.Background(), "", nil, nil) assert.Regexp(t, "FF10128", err) } diff --git a/internal/definitions/definition_handler.go b/internal/definitions/definition_handler.go index d688a0258..020642d92 100644 --- a/internal/definitions/definition_handler.go +++ b/internal/definitions/definition_handler.go @@ -80,7 +80,7 @@ type definitionHandlers struct { namespace string database database.Plugin blockchain blockchain.Plugin - exchange dataexchange.Plugin + exchange dataexchange.Plugin // optional data data.Manager identity identity.Manager assets assets.Manager @@ -88,7 +88,7 @@ type definitionHandlers struct { } func NewDefinitionHandler(ctx context.Context, ns string, di database.Plugin, bi blockchain.Plugin, dx dataexchange.Plugin, dm data.Manager, im identity.Manager, am assets.Manager, cm contracts.Manager) (DefinitionHandler, error) { - if di == nil || bi == nil || dx == nil || dm == nil || im == nil || am == nil || cm == nil { + if di == nil || bi == nil || dm == nil || im == nil || am == nil || cm == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "DefinitionHandler") } return &definitionHandlers{ diff --git a/internal/definitions/definition_handler_identity_claim.go b/internal/definitions/definition_handler_identity_claim.go index 95c89fd02..cbd797291 100644 --- a/internal/definitions/definition_handler_identity_claim.go +++ b/internal/definitions/definition_handler_identity_claim.go @@ -129,6 +129,10 @@ func (dh *definitionHandlers) confirmVerificationForClaim(ctx context.Context, s func (dh *definitionHandlers) handleIdentityClaim(ctx context.Context, state *core.BatchState, msg *core.Message, identityClaim *core.IdentityClaim, verificationID *fftypes.UUID) (HandlerResult, error) { l := log.L(ctx) + if identityClaim.Identity.Type == core.IdentityTypeNode && dh.exchange == nil { + return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + } + identity := identityClaim.Identity parent, retryable, err := dh.identity.VerifyIdentityChain(ctx, identity) if err != nil && retryable { diff --git a/internal/defsender/sender.go b/internal/defsender/sender.go index eac59ecb1..e52dcbe96 100644 --- a/internal/defsender/sender.go +++ b/internal/defsender/sender.go @@ -42,13 +42,13 @@ type Sender interface { type definitionSender struct { ctx context.Context namespace string - broadcast broadcast.Manager + broadcast broadcast.Manager // optional identity identity.Manager data data.Manager } func NewDefinitionSender(ctx context.Context, ns string, bm broadcast.Manager, im identity.Manager, dm data.Manager) (Sender, error) { - if bm == nil || im == nil || dm == nil { + if im == nil || dm == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError) } return &definitionSender{ @@ -92,6 +92,10 @@ func (bm *definitionSender) CreateIdentityClaim(ctx context.Context, def *core.I func (bm *definitionSender) broadcastDefinitionCommon(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { + if bm.broadcast == nil { + return nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + } + b, err := json.Marshal(&def) if err != nil { return nil, i18n.WrapError(ctx, err, coremsgs.MsgSerializationFailed) diff --git a/internal/events/batch_pin_complete.go b/internal/events/batch_pin_complete.go index d08d5dbf9..9f6a5e0e2 100644 --- a/internal/events/batch_pin_complete.go +++ b/internal/events/batch_pin_complete.go @@ -32,6 +32,10 @@ import ( // We must block here long enough to get the payload from the sharedstorage, persist the messages in the correct // sequence, and also persist all the data. func (em *eventManager) BatchPinComplete(batchPin *blockchain.BatchPin, signingKey *core.VerifierRef) error { + if em.multiparty == nil { + log.L(em.ctx).Errorf("Ignoring batch pin from non-multiparty network!") + return nil + } if batchPin.TransactionID == nil { log.L(em.ctx).Errorf("Invalid BatchPin transaction - ID is nil") return nil // move on diff --git a/internal/events/dx_callbacks.go b/internal/events/dx_callbacks.go index 4c8ad8549..d9821f1bf 100644 --- a/internal/events/dx_callbacks.go +++ b/internal/events/dx_callbacks.go @@ -77,6 +77,10 @@ func (em *eventManager) checkReceivedOffchainIdentity(ctx context.Context, peerI } func (em *eventManager) privateBatchReceived(peerID string, batch *core.Batch, wrapperGroup *core.Group) (manifest string, err error) { + if em.multiparty == nil { + log.L(em.ctx).Errorf("Ignoring private batch from non-multiparty network!") + return "", nil + } // Retry for persistence errors (not validation errors) err = em.retry.Do(em.ctx, "private batch received", func(attempt int) (bool, error) { diff --git a/internal/events/event_dispatcher.go b/internal/events/event_dispatcher.go index 2462146c6..6b8e4bcfd 100644 --- a/internal/events/event_dispatcher.go +++ b/internal/events/event_dispatcher.go @@ -56,8 +56,8 @@ type eventDispatcher struct { data data.Manager database database.Plugin transport events.Plugin - broadcast broadcast.Manager - messaging privatemessaging.Manager + broadcast broadcast.Manager // optional + messaging privatemessaging.Manager // optional elected bool eventPoller *eventPoller inflight map[fftypes.UUID]*core.Event diff --git a/internal/events/event_manager.go b/internal/events/event_manager.go index e2fb0cce7..f3e586c87 100644 --- a/internal/events/event_manager.go +++ b/internal/events/event_manager.go @@ -92,7 +92,6 @@ type eventManager struct { ctx context.Context namespace string ni sysmessaging.LocalNodeInfo - sharedstorage sharedstorage.Plugin database database.Plugin txHelper txcommon.Helper identity identity.Manager @@ -102,10 +101,10 @@ type eventManager struct { subManager *subscriptionManager retry retry.Retry aggregator *aggregator - broadcast broadcast.Manager - messaging privatemessaging.Manager + broadcast broadcast.Manager // optional + messaging privatemessaging.Manager // optional assets assets.Manager - sharedDownload shareddownload.Manager + sharedDownload shareddownload.Manager // optional blobReceiver *blobReceiver newEventNotifier *eventNotifier newPinNotifier *eventNotifier @@ -114,11 +113,11 @@ type eventManager struct { metrics metrics.Manager chainListenerCache *ccache.Cache chainListenerCacheTTL time.Duration - multiparty multiparty.Manager + multiparty multiparty.Manager // optional } -func NewEventManager(ctx context.Context, ns string, ni sysmessaging.LocalNodeInfo, si sharedstorage.Plugin, di database.Plugin, bi blockchain.Plugin, im identity.Manager, dh definitions.DefinitionHandler, dm data.Manager, ds defsender.Sender, bm broadcast.Manager, pm privatemessaging.Manager, am assets.Manager, sd shareddownload.Manager, mm metrics.Manager, txHelper txcommon.Helper, transports map[string]events.Plugin, mp multiparty.Manager) (EventManager, error) { - if ni == nil || si == nil || di == nil || bi == nil || im == nil || dh == nil || dm == nil || ds == nil || bm == nil || pm == nil || am == nil { +func NewEventManager(ctx context.Context, ns string, ni sysmessaging.LocalNodeInfo, di database.Plugin, bi blockchain.Plugin, im identity.Manager, dh definitions.DefinitionHandler, dm data.Manager, ds defsender.Sender, bm broadcast.Manager, pm privatemessaging.Manager, am assets.Manager, sd shareddownload.Manager, mm metrics.Manager, txHelper txcommon.Helper, transports map[string]events.Plugin, mp multiparty.Manager) (EventManager, error) { + if ni == nil || di == nil || bi == nil || im == nil || dh == nil || dm == nil || ds == nil || am == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "EventManager") } newPinNotifier := newEventNotifier(ctx, "pins") @@ -127,7 +126,6 @@ func NewEventManager(ctx context.Context, ns string, ni sysmessaging.LocalNodeIn ctx: log.WithLogField(ctx, "role", "event-manager"), namespace: ns, ni: ni, - sharedstorage: si, database: di, txHelper: txHelper, identity: im, diff --git a/internal/events/event_manager_test.go b/internal/events/event_manager_test.go index d6d7c10f8..43d180fad 100644 --- a/internal/events/event_manager_test.go +++ b/internal/events/event_manager_test.go @@ -39,7 +39,6 @@ import ( "github.com/hyperledger/firefly/mocks/multipartymocks" "github.com/hyperledger/firefly/mocks/privatemessagingmocks" "github.com/hyperledger/firefly/mocks/shareddownloadmocks" - "github.com/hyperledger/firefly/mocks/sharedstoragemocks" "github.com/hyperledger/firefly/mocks/sysmessagingmocks" "github.com/hyperledger/firefly/mocks/txcommonmocks" "github.com/hyperledger/firefly/pkg/core" @@ -73,7 +72,6 @@ func newTestEventManagerCommon(t *testing.T, metrics, dbconcurrency bool) (*even mdi := &databasemocks.Plugin{} mbi := &blockchainmocks.Plugin{} mim := &identitymanagermocks.Manager{} - mpi := &sharedstoragemocks.Plugin{} met := &eventsmocks.Plugin{} mdm := &datamocks.Manager{} msh := &definitionsmocks.DefinitionHandler{} @@ -98,7 +96,7 @@ func newTestEventManagerCommon(t *testing.T, metrics, dbconcurrency bool) (*even mdi.On("Capabilities").Return(&database.Capabilities{Concurrency: dbconcurrency}).Maybe() mev.On("SetHandler", "ns1", mock.Anything).Return(nil).Maybe() mev.On("ValidateOptions", mock.Anything).Return(nil).Maybe() - emi, err := NewEventManager(ctx, "ns1", mni, mpi, mdi, mbi, mim, msh, mdm, mds, mbm, mpm, mam, mdd, mmi, txHelper, events, mmp) + emi, err := NewEventManager(ctx, "ns1", mni, mdi, mbi, mim, msh, mdm, mds, mbm, mpm, mam, mdd, mmi, txHelper, events, mmp) em := emi.(*eventManager) em.txHelper = &txcommonmocks.Helper{} mockRunAsGroupPassthrough(mdi) @@ -133,7 +131,7 @@ func TestStartStop(t *testing.T) { } func TestStartStopBadDependencies(t *testing.T) { - _, err := NewEventManager(context.Background(), "", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) + _, err := NewEventManager(context.Background(), "", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) assert.Regexp(t, "FF10128", err) } @@ -144,7 +142,6 @@ func TestStartStopEventListenerFail(t *testing.T) { mdi := &databasemocks.Plugin{} mbi := &blockchainmocks.Plugin{} mim := &identitymanagermocks.Manager{} - mpi := &sharedstoragemocks.Plugin{} mdm := &datamocks.Manager{} msh := &definitionsmocks.DefinitionHandler{} mds := &defsendermocks.Sender{} @@ -161,7 +158,7 @@ func TestStartStopEventListenerFail(t *testing.T) { mdi.On("Capabilities").Return(&database.Capabilities{Concurrency: false}) mbi.On("VerifierType").Return(core.VerifierTypeEthAddress) mev.On("SetHandler", "ns1", mock.Anything).Return(fmt.Errorf("pop")) - _, err := NewEventManager(context.Background(), "ns1", mni, mpi, mdi, mbi, mim, msh, mdm, mds, mbm, mpm, mam, msd, mm, txHelper, events, mmp) + _, err := NewEventManager(context.Background(), "ns1", mni, mdi, mbi, mim, msh, mdm, mds, mbm, mpm, mam, msd, mm, txHelper, events, mmp) assert.EqualError(t, err, "pop") } diff --git a/internal/events/network_action.go b/internal/events/network_action.go index 8337a48c8..35f826f5b 100644 --- a/internal/events/network_action.go +++ b/internal/events/network_action.go @@ -43,6 +43,11 @@ func (em *eventManager) actionTerminate(mm multiparty.Manager, event *blockchain } func (em *eventManager) BlockchainNetworkAction(action string, event *blockchain.Event, signingKey *core.VerifierRef) error { + if em.multiparty == nil { + log.L(em.ctx).Errorf("Ignoring network action from non-multiparty network!") + return nil + } + return em.retry.Do(em.ctx, "handle network action", func(attempt int) (retry bool, err error) { // Verify that the action came from a registered root org resolvedAuthor, err := em.identity.FindIdentityForVerifier(em.ctx, []core.IdentityType{core.IdentityTypeOrg}, signingKey) diff --git a/internal/events/network_action_test.go b/internal/events/network_action_test.go index b9b3fbab4..671eba446 100644 --- a/internal/events/network_action_test.go +++ b/internal/events/network_action_test.go @@ -107,6 +107,20 @@ func TestNetworkActionNonRootIdentity(t *testing.T) { mii.AssertExpectations(t) } +func TestNetworkActionNonMultiparty(t *testing.T) { + em, cancel := newTestEventManager(t) + defer cancel() + em.multiparty = nil + + verifier := &core.VerifierRef{ + Type: core.VerifierTypeEthAddress, + Value: "0x1234", + } + + err := em.BlockchainNetworkAction("terminate", &blockchain.Event{}, verifier) + assert.NoError(t, err) +} + func TestNetworkActionUnknown(t *testing.T) { em, cancel := newTestEventManager(t) defer cancel() diff --git a/internal/events/reply_sender.go b/internal/events/reply_sender.go index 557914e9c..72c65cfbf 100644 --- a/internal/events/reply_sender.go +++ b/internal/events/reply_sender.go @@ -18,6 +18,7 @@ package events import ( "context" + "fmt" "github.com/hyperledger/firefly-common/pkg/log" "github.com/hyperledger/firefly/pkg/core" @@ -26,9 +27,17 @@ import ( func (ed *eventDispatcher) sendReply(ctx context.Context, event *core.Event, reply *core.MessageInOut) { var err error if reply.Header.Group != nil { - err = ed.messaging.NewMessage(reply).Send(ctx) + if ed.messaging == nil { + err = fmt.Errorf("private messaging manager not initialized") + } else { + err = ed.messaging.NewMessage(reply).Send(ctx) + } } else { - err = ed.broadcast.NewBroadcast(reply).Send(ctx) + if ed.broadcast == nil { + err = fmt.Errorf("broadcast manager not initialized") + } else { + err = ed.broadcast.NewBroadcast(reply).Send(ctx) + } } if err != nil { log.L(ctx).Errorf("Failed to send reply: %s", err) diff --git a/internal/events/ss_callbacks.go b/internal/events/ss_callbacks.go index 906fdddf4..f31e3fe96 100644 --- a/internal/events/ss_callbacks.go +++ b/internal/events/ss_callbacks.go @@ -30,6 +30,11 @@ func (em *eventManager) SharedStorageBatchDownloaded(ss sharedstorage.Plugin, pa l := log.L(em.ctx) + if em.multiparty == nil { + l.Errorf("Ignoring private batch from non-multiparty network!") + return nil, nil + } + // De-serialize the batch var batch *core.Batch err := json.Unmarshal(data, &batch) diff --git a/internal/events/ss_callbacks_test.go b/internal/events/ss_callbacks_test.go index 86bef1388..4ada91bb9 100644 --- a/internal/events/ss_callbacks_test.go +++ b/internal/events/ss_callbacks_test.go @@ -41,7 +41,7 @@ func TestSharedStorageBatchDownloadedOk(t *testing.T) { b, _ := json.Marshal(&batch) mdi := em.database.(*databasemocks.Plugin) - mss := em.sharedstorage.(*sharedstoragemocks.Plugin) + mss := &sharedstoragemocks.Plugin{} mdi.On("UpsertBatch", em.ctx, mock.Anything).Return(nil, nil) mdi.On("InsertDataArray", em.ctx, mock.Anything).Return(nil, nil) mdi.On("InsertMessages", em.ctx, mock.Anything, mock.AnythingOfType("database.PostCompletionHook")).Return(nil, nil).Run(func(args mock.Arguments) { @@ -74,7 +74,7 @@ func TestSharedStorageBatchDownloadedPersistFail(t *testing.T) { b, _ := json.Marshal(&batch) mdi := em.database.(*databasemocks.Plugin) - mss := em.sharedstorage.(*sharedstoragemocks.Plugin) + mss := &sharedstoragemocks.Plugin{} mdi.On("UpsertBatch", em.ctx, mock.Anything).Return(fmt.Errorf("pop")) mss.On("Name").Return("utdx").Maybe() @@ -95,7 +95,7 @@ func TestSharedStorageBatchDownloadedNSMismatch(t *testing.T) { batch := sampleBatch(t, core.BatchTypeBroadcast, core.TransactionTypeBatchPin, core.DataArray{data}) b, _ := json.Marshal(&batch) - mss := em.sharedstorage.(*sharedstoragemocks.Plugin) + mss := &sharedstoragemocks.Plugin{} mss.On("Name").Return("utdx").Maybe() em.namespace = "ns2" @@ -111,7 +111,7 @@ func TestSharedStorageBatchDownloadedBadData(t *testing.T) { em, cancel := newTestEventManager(t) defer cancel() - mss := em.sharedstorage.(*sharedstoragemocks.Plugin) + mss := &sharedstoragemocks.Plugin{} mss.On("Name").Return("utdx").Maybe() _, err := em.SharedStorageBatchDownloaded(mss, "payload1", []byte("!json")) @@ -127,7 +127,7 @@ func TestSharedStorageBlobDownloadedOk(t *testing.T) { defer cancel() mdi := em.database.(*databasemocks.Plugin) - mss := em.sharedstorage.(*sharedstoragemocks.Plugin) + mss := &sharedstoragemocks.Plugin{} mss.On("Name").Return("utsd") mdi.On("GetBlobs", em.ctx, mock.Anything).Return([]*core.Blob{}, nil, nil) mdi.On("InsertBlobs", em.ctx, mock.Anything).Return(nil, nil) diff --git a/internal/events/subscription_manager.go b/internal/events/subscription_manager.go index 50da22db0..b0cdf8898 100644 --- a/internal/events/subscription_manager.go +++ b/internal/events/subscription_manager.go @@ -106,8 +106,8 @@ func newSubscriptionManager(ctx context.Context, ns string, di database.Plugin, maxSubs: uint64(config.GetUint(coreconfig.SubscriptionMax)), cancelCtx: cancelCtx, eventNotifier: en, - broadcast: bm, - messaging: pm, + broadcast: bm, // optional + messaging: pm, // optional txHelper: txHelper, retry: retry.Retry{ InitialDelay: config.GetDuration(coreconfig.SubscriptionsRetryInitialDelay), diff --git a/internal/identity/identitymanager.go b/internal/identity/identitymanager.go index b4111dc18..41c0b6359 100644 --- a/internal/identity/identitymanager.go +++ b/internal/identity/identitymanager.go @@ -57,7 +57,7 @@ type Manager interface { type identityManager struct { database database.Plugin blockchain blockchain.Plugin - multiparty multiparty.Manager + multiparty multiparty.Manager // optional namespace string defaultKey string multipartyRootVerifier *core.VerifierRef @@ -385,7 +385,7 @@ func (im *identityManager) cachedIdentityLookupByVerifierRef(ctx context.Context if err != nil { return nil, err } else if verifier == nil { - if namespace != core.LegacySystemNamespace && im.multiparty.GetNetworkVersion() == 1 { + if namespace != core.LegacySystemNamespace && im.multiparty != nil && im.multiparty.GetNetworkVersion() == 1 { // For V1 networks, fall back to LegacySystemNamespace for looking up identities // This assumes that the system namespace shares a database with this manager's namespace! return im.cachedIdentityLookupByVerifierRef(ctx, core.LegacySystemNamespace, verifierRef) diff --git a/internal/networkmap/manager.go b/internal/networkmap/manager.go index 3b4208b14..091b748ef 100644 --- a/internal/networkmap/manager.go +++ b/internal/networkmap/manager.go @@ -60,14 +60,14 @@ type networkMap struct { namespace string database database.Plugin defsender defsender.Sender - exchange dataexchange.Plugin + exchange dataexchange.Plugin // optional identity identity.Manager syncasync syncasync.Bridge - multiparty multiparty.Manager + multiparty multiparty.Manager // optional } func NewNetworkMap(ctx context.Context, ns string, di database.Plugin, dx dataexchange.Plugin, ds defsender.Sender, im identity.Manager, sa syncasync.Bridge, mm multiparty.Manager) (Manager, error) { - if di == nil || ds == nil || dx == nil || im == nil || mm == nil { + if di == nil || ds == nil || im == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "NetworkMap") } diff --git a/internal/networkmap/register_node.go b/internal/networkmap/register_node.go index c5a56ead4..8ca18898d 100644 --- a/internal/networkmap/register_node.go +++ b/internal/networkmap/register_node.go @@ -21,12 +21,18 @@ import ( "fmt" "github.com/hyperledger/firefly-common/pkg/config" + "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/coreconfig" + "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/pkg/core" ) func (nm *networkMap) RegisterNode(ctx context.Context, waitConfirm bool) (identity *core.Identity, err error) { + if nm.exchange == nil { + return nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + } + nodeOwningOrg, err := nm.identity.GetMultipartyRootOrg(ctx) if err != nil { return nil, err diff --git a/internal/orchestrator/bound_callbacks.go b/internal/orchestrator/bound_callbacks.go index 9acaa1701..fdc968946 100644 --- a/internal/orchestrator/bound_callbacks.go +++ b/internal/orchestrator/bound_callbacks.go @@ -19,7 +19,6 @@ package orchestrator import ( "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/events" - "github.com/hyperledger/firefly/internal/multiparty" "github.com/hyperledger/firefly/internal/operations" "github.com/hyperledger/firefly/pkg/blockchain" "github.com/hyperledger/firefly/pkg/core" @@ -29,11 +28,10 @@ import ( ) type boundCallbacks struct { - dx dataexchange.Plugin - ss sharedstorage.Plugin - ei events.EventManager - om operations.Manager - multiparty multiparty.Manager + dx dataexchange.Plugin + ss sharedstorage.Plugin + ei events.EventManager + om operations.Manager } func (bc *boundCallbacks) BlockchainOpUpdate(plugin blockchain.Plugin, nsOpID string, txState blockchain.TransactionStatus, blockchainTXID, errorMessage string, opOutput fftypes.JSONObject) { diff --git a/internal/orchestrator/bound_callbacks_test.go b/internal/orchestrator/bound_callbacks_test.go index 187027a67..0ddf0a1ed 100644 --- a/internal/orchestrator/bound_callbacks_test.go +++ b/internal/orchestrator/bound_callbacks_test.go @@ -25,7 +25,6 @@ import ( "github.com/hyperledger/firefly/mocks/blockchainmocks" "github.com/hyperledger/firefly/mocks/dataexchangemocks" "github.com/hyperledger/firefly/mocks/eventmocks" - "github.com/hyperledger/firefly/mocks/multipartymocks" "github.com/hyperledger/firefly/mocks/operationmocks" "github.com/hyperledger/firefly/mocks/sharedstoragemocks" "github.com/hyperledger/firefly/mocks/tokenmocks" @@ -40,12 +39,11 @@ import ( func TestBoundCallbacks(t *testing.T) { mei := &eventmocks.EventManager{} mbi := &blockchainmocks.Plugin{} - mmp := &multipartymocks.Manager{} mdx := &dataexchangemocks.Plugin{} mti := &tokenmocks.Plugin{} mss := &sharedstoragemocks.Plugin{} mom := &operationmocks.Manager{} - bc := boundCallbacks{dx: mdx, ei: mei, ss: mss, om: mom, multiparty: mmp} + bc := boundCallbacks{dx: mdx, ei: mei, ss: mss, om: mom} info := fftypes.JSONObject{"hello": "world"} batch := &blockchain.BatchPin{TransactionID: fftypes.NewUUID()} diff --git a/internal/orchestrator/message.go b/internal/orchestrator/message.go index cf5369e74..6bdde0f0e 100644 --- a/internal/orchestrator/message.go +++ b/internal/orchestrator/message.go @@ -25,8 +25,12 @@ import ( ) func (or *orchestrator) RequestReply(ctx context.Context, msg *core.MessageInOut) (reply *core.MessageInOut, err error) { + pm := or.PrivateMessaging() + if pm == nil { + return nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + } if msg.Header.Group == nil && (msg.Group == nil || len(msg.Group.Members) == 0) { return nil, i18n.NewError(ctx, coremsgs.MsgRequestMustBePrivate) } - return or.PrivateMessaging().RequestReply(ctx, msg) + return pm.RequestReply(ctx, msg) } diff --git a/internal/orchestrator/orchestrator.go b/internal/orchestrator/orchestrator.go index 75b709c35..4e8bfa8d7 100644 --- a/internal/orchestrator/orchestrator.go +++ b/internal/orchestrator/orchestrator.go @@ -20,11 +20,13 @@ import ( "context" "github.com/hyperledger/firefly-common/pkg/fftypes" + "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly-common/pkg/log" "github.com/hyperledger/firefly/internal/assets" "github.com/hyperledger/firefly/internal/batch" "github.com/hyperledger/firefly/internal/broadcast" "github.com/hyperledger/firefly/internal/contracts" + "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/internal/data" "github.com/hyperledger/firefly/internal/definitions" "github.com/hyperledger/firefly/internal/defsender" @@ -53,17 +55,18 @@ type Orchestrator interface { Init(ctx context.Context, cancelCtx context.CancelFunc) error Start() error WaitStop() // The close itself is performed by canceling the context + + MultiParty() multiparty.Manager // only for multiparty + BatchManager() batch.Manager // only for multiparty + Broadcast() broadcast.Manager // only for multiparty + PrivateMessaging() privatemessaging.Manager // only for multiparty Assets() assets.Manager - BatchManager() batch.Manager - Broadcast() broadcast.Manager DefinitionSender() defsender.Sender Contracts() contracts.Manager - MultiParty() multiparty.Manager Data() data.Manager Events() events.EventManager NetworkMap() networkmap.Manager Operations() operations.Manager - PrivateMessaging() privatemessaging.Manager // Status GetStatus(ctx context.Context) (*core.NodeStatus, error) @@ -207,7 +210,6 @@ func (or *orchestrator) Init(ctx context.Context, cancelCtx context.CancelFunc) err = or.initComponents(or.ctx) } // Bind together the blockchain interface callbacks, with the events manager - or.bc.multiparty = or.multiparty or.bc.ei = or.events or.bc.dx = or.plugins.DataExchange.Plugin or.bc.ss = or.plugins.SharedStorage.Plugin @@ -240,41 +242,43 @@ func (or *orchestrator) tokens() map[string]tokens.Plugin { } func (or *orchestrator) Start() (err error) { - var ns *core.Namespace - ns, err = or.database().GetNamespace(or.ctx, or.namespace) - if err == nil { - if ns == nil { - ns = &core.Namespace{ - Name: or.namespace, - Created: fftypes.Now(), + if or.config.Multiparty.Enabled { + var ns *core.Namespace + ns, err = or.database().GetNamespace(or.ctx, or.namespace) + if err == nil { + if ns == nil { + ns = &core.Namespace{ + Name: or.namespace, + Created: fftypes.Now(), + } } + err = or.multiparty.ConfigureContract(or.ctx, &ns.Contracts) + } + if err == nil { + err = or.database().UpsertNamespace(or.ctx, ns, true) + } + if err == nil { + err = or.batch.Start() + } + if err == nil { + err = or.broadcast.Start() + } + if err == nil { + err = or.messaging.Start() + } + if err == nil { + err = or.sharedDownload.Start() } - err = or.multiparty.ConfigureContract(or.ctx, &ns.Contracts) } if err == nil { err = or.blockchain().Start() } - if err == nil { - err = or.database().UpsertNamespace(or.ctx, ns, true) - } - if err == nil { - err = or.batch.Start() - } if err == nil { err = or.events.Start() } - if err == nil { - err = or.broadcast.Start() - } - if err == nil { - err = or.messaging.Start() - } if err == nil { err = or.operations.Start() } - if err == nil { - err = or.sharedDownload.Start() - } if err == nil { for _, el := range or.tokens() { if err = el.Start(); err != nil { @@ -359,22 +363,30 @@ func (or *orchestrator) MultiParty() multiparty.Manager { func (or *orchestrator) initPlugins(ctx context.Context) (err error) { or.plugins.Database.Plugin.SetHandler(or.namespace, or) - or.plugins.Blockchain.Plugin.SetHandler(&or.bc) - or.plugins.SharedStorage.Plugin.SetHandler(or.namespace, &or.bc) - fb := database.IdentityQueryFactory.NewFilter(ctx) - nodes, _, err := or.database().GetIdentities(ctx, or.namespace, fb.And( - fb.Eq("type", core.IdentityTypeNode), - )) - if err != nil { - return err + if or.plugins.Blockchain.Plugin != nil { + or.plugins.Blockchain.Plugin.SetHandler(&or.bc) } - nodeInfo := make([]fftypes.JSONObject, len(nodes)) - for i, node := range nodes { - nodeInfo[i] = node.Profile + + if or.plugins.SharedStorage.Plugin != nil { + or.plugins.SharedStorage.Plugin.SetHandler(or.namespace, &or.bc) + } + + if or.plugins.DataExchange.Plugin != nil { + fb := database.IdentityQueryFactory.NewFilter(ctx) + nodes, _, err := or.database().GetIdentities(ctx, or.namespace, fb.And( + fb.Eq("type", core.IdentityTypeNode), + )) + if err != nil { + return err + } + nodeInfo := make([]fftypes.JSONObject, len(nodes)) + for i, node := range nodes { + nodeInfo[i] = node.Profile + } + or.plugins.DataExchange.Plugin.SetNodes(nodeInfo) + or.plugins.DataExchange.Plugin.SetHandler(or.namespace, &or.bc) } - or.plugins.DataExchange.Plugin.SetNodes(nodeInfo) - or.plugins.DataExchange.Plugin.SetHandler(or.namespace, &or.bc) for _, token := range or.plugins.Tokens { if err := token.Plugin.SetHandler(or.namespace, &or.bc); err != nil { @@ -397,10 +409,12 @@ func (or *orchestrator) initManagers(ctx context.Context) (err error) { } } - if or.multiparty == nil { - or.multiparty, err = multiparty.NewMultipartyManager(or.ctx, or.namespace, or.config.Multiparty, or.database(), or.blockchain(), or.operations, or.metrics, or.txHelper) - if err != nil { - return err + if or.config.Multiparty.Enabled { + if or.multiparty == nil { + or.multiparty, err = multiparty.NewMultipartyManager(or.ctx, or.namespace, or.config.Multiparty, or.database(), or.blockchain(), or.operations, or.metrics, or.txHelper) + if err != nil { + return err + } } } @@ -413,22 +427,31 @@ func (or *orchestrator) initManagers(ctx context.Context) (err error) { or.syncasync = syncasync.NewSyncAsyncBridge(ctx, or.namespace, or.database(), or.data) - if or.batch == nil { - or.batch, err = batch.NewBatchManager(ctx, or.namespace, or, or.database(), or.data, or.txHelper) - if err != nil { - return err + if or.config.Multiparty.Enabled { + if or.batch == nil { + or.batch, err = batch.NewBatchManager(ctx, or.namespace, or, or.database(), or.data, or.txHelper) + if err != nil { + return err + } } - } - if or.messaging == nil { - if or.messaging, err = privatemessaging.NewPrivateMessaging(ctx, or.namespace, or.database(), or.dataexchange(), or.blockchain(), or.identity, or.batch, or.data, or.syncasync, or.multiparty, or.metrics, or.operations); err != nil { - return err + if or.messaging == nil { + if or.messaging, err = privatemessaging.NewPrivateMessaging(ctx, or.namespace, or.database(), or.dataexchange(), or.blockchain(), or.identity, or.batch, or.data, or.syncasync, or.multiparty, or.metrics, or.operations); err != nil { + return err + } } - } - if or.broadcast == nil { - if or.broadcast, err = broadcast.NewBroadcastManager(ctx, or.namespace, or.database(), or.blockchain(), or.dataexchange(), or.sharedstorage(), or.identity, or.data, or.batch, or.syncasync, or.multiparty, or.metrics, or.operations); err != nil { - return err + if or.broadcast == nil { + if or.broadcast, err = broadcast.NewBroadcastManager(ctx, or.namespace, or.database(), or.blockchain(), or.dataexchange(), or.sharedstorage(), or.identity, or.data, or.batch, or.syncasync, or.multiparty, or.metrics, or.operations); err != nil { + return err + } + } + + if or.sharedDownload == nil { + or.sharedDownload, err = shareddownload.NewDownloadManager(ctx, or.namespace, or.database(), or.sharedstorage(), or.dataexchange(), or.operations, &or.bc) + if err != nil { + return err + } } } @@ -460,13 +483,6 @@ func (or *orchestrator) initManagers(ctx context.Context) (err error) { } } - if or.sharedDownload == nil { - or.sharedDownload, err = shareddownload.NewDownloadManager(ctx, or.namespace, or.database(), or.sharedstorage(), or.dataexchange(), or.operations, &or.bc) - if err != nil { - return err - } - } - return nil } @@ -479,7 +495,7 @@ func (or *orchestrator) initHandlers(ctx context.Context) (err error) { } if or.events == nil { - or.events, err = events.NewEventManager(ctx, or.namespace, or, or.sharedstorage(), or.database(), or.blockchain(), or.identity, or.defhandler, or.data, or.defsender, or.broadcast, or.messaging, or.assets, or.sharedDownload, or.metrics, or.txHelper, or.plugins.Events, or.multiparty) + or.events, err = events.NewEventManager(ctx, or.namespace, or, or.database(), or.blockchain(), or.identity, or.defhandler, or.data, or.defsender, or.broadcast, or.messaging, or.assets, or.sharedDownload, or.metrics, or.txHelper, or.plugins.Events, or.multiparty) if err != nil { return err } @@ -490,7 +506,7 @@ func (or *orchestrator) initHandlers(ctx context.Context) (err error) { func (or *orchestrator) initComponents(ctx context.Context) (err error) { if or.data == nil { - or.data, err = data.NewDataManager(ctx, or.namespace, or.database(), or.sharedstorage(), or.dataexchange()) + or.data, err = data.NewDataManager(ctx, or.namespace, or.database(), or.dataexchange()) if err != nil { return err } @@ -510,6 +526,9 @@ func (or *orchestrator) initComponents(ctx context.Context) (err error) { } func (or *orchestrator) SubmitNetworkAction(ctx context.Context, action *core.NetworkAction) error { + if or.multiparty == nil { + return i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + } key, err := or.identity.NormalizeSigningKey(ctx, "", identity.KeyNormalizationBlockchainPlugin) if err != nil { return err diff --git a/internal/orchestrator/orchestrator_test.go b/internal/orchestrator/orchestrator_test.go index c8abc8053..0d3196b0d 100644 --- a/internal/orchestrator/orchestrator_test.go +++ b/internal/orchestrator/orchestrator_test.go @@ -155,6 +155,7 @@ func newTestOrchestrator() *testOrchestrator { tor.orchestrator.txHelper = tor.mth tor.orchestrator.defhandler = tor.mdh tor.orchestrator.defsender = tor.mds + tor.orchestrator.config.Multiparty.Enabled = true tor.orchestrator.plugins.Blockchain.Plugin = tor.mbi tor.orchestrator.plugins.SharedStorage.Plugin = tor.mps tor.orchestrator.plugins.DataExchange.Plugin = tor.mdx @@ -373,7 +374,6 @@ func TestStartBatchFail(t *testing.T) { or.mdi.On("GetNamespace", mock.Anything, "ns").Return(nil, nil) or.mdi.On("UpsertNamespace", mock.Anything, mock.Anything, true).Return(nil) or.mmp.On("ConfigureContract", mock.Anything, mock.Anything).Return(nil) - or.mbi.On("Start").Return(nil) or.mba.On("Start").Return(fmt.Errorf("pop")) err := or.Start() assert.EqualError(t, err, "pop") @@ -403,7 +403,12 @@ func TestStartBlockchainsFail(t *testing.T) { or := newTestOrchestrator() defer or.cleanup(t) or.mdi.On("GetNamespace", mock.Anything, "ns").Return(nil, nil) + or.mdi.On("UpsertNamespace", mock.Anything, mock.Anything, true).Return(nil) or.mmp.On("ConfigureContract", mock.Anything, &core.FireFlyContracts{}).Return(nil) + or.mbm.On("Start").Return(nil) + or.mpm.On("Start").Return(nil) + or.mba.On("Start").Return(nil) + or.msd.On("Start").Return(nil) or.mbi.On("Start").Return(fmt.Errorf("pop")) err := or.Start() assert.EqualError(t, err, "pop") @@ -463,3 +468,10 @@ func TestNetworkActionBadKey(t *testing.T) { err := or.SubmitNetworkAction(context.Background(), action) assert.EqualError(t, err, "pop") } + +func TestNetworkActionNonMultiparty(t *testing.T) { + or := newTestOrchestrator() + or.multiparty = nil + err := or.SubmitNetworkAction(context.Background(), &core.NetworkAction{Type: core.NetworkActionTerminate}) + assert.Regexp(t, "FF10413", err) +} diff --git a/internal/shareddownload/download_manager.go b/internal/shareddownload/download_manager.go index 1ba1e7003..751dc0e0e 100644 --- a/internal/shareddownload/download_manager.go +++ b/internal/shareddownload/download_manager.go @@ -53,7 +53,7 @@ type downloadManager struct { cancelFunc func() namespace string database database.Plugin - sharedstorage sharedstorage.Plugin + sharedstorage sharedstorage.Plugin // optional dataexchange dataexchange.Plugin operations operations.Manager callbacks Callbacks From 58d11f83e638dcc71d2cc08af90e7645eec451f0 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Thu, 23 Jun 2022 13:35:43 -0400 Subject: [PATCH 05/27] Add more config deprecation warnings Signed-off-by: Andrew Richardson --- internal/namespace/manager.go | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/internal/namespace/manager.go b/internal/namespace/manager.go index 723a3263f..8dce96c41 100644 --- a/internal/namespace/manager.go +++ b/internal/namespace/manager.go @@ -379,6 +379,7 @@ func (nm *namespaceManager) getDatabasePlugins(ctx context.Context) (plugins map if err != nil { return nil, err } + log.L(ctx).Warnf("Your database config uses a deprecated configuration structure - the database configuration has been moved under the 'plugins' section") name := "database_0" plugins[name] = databasePlugin{ config: deprecatedDatabaseConfig.SubSection(pluginType), @@ -431,13 +432,12 @@ func (nm *namespaceManager) getDataExchangePlugins(ctx context.Context) (plugins } if len(plugins) == 0 { - log.L(ctx).Warnf("Your data exchange config uses a deprecated configuration structure - the data exchange configuration has been moved under the 'plugins' section") pluginType := deprecatedDataexchangeConfig.GetString(coreconfig.PluginConfigType) plugin, err := dxfactory.GetPlugin(ctx, pluginType) if err != nil { return nil, err } - + log.L(ctx).Warnf("Your data exchange config uses a deprecated configuration structure - the data exchange configuration has been moved under the 'plugins' section") name := "dataexchange_0" plugins[name] = dataExchangePlugin{ config: deprecatedDataexchangeConfig.SubSection(pluginType), @@ -500,7 +500,7 @@ func (nm *namespaceManager) getBlockchainPlugins(ctx context.Context) (plugins m if err != nil { return nil, err } - + log.L(ctx).Warnf("Your blockchain config uses a deprecated configuration structure - the blockchain configuration has been moved under the 'plugins' section") name := "blockchain_0" plugins[name] = blockchainPlugin{ config: deprecatedBlockchainConfig.SubSection(pluginType), @@ -539,7 +539,7 @@ func (nm *namespaceManager) getSharedStoragePlugins(ctx context.Context) (plugin if err != nil { return nil, err } - + log.L(ctx).Warnf("Your shared storage config uses a deprecated configuration structure - the shared storage configuration has been moved under the 'plugins' section") name := "sharedstorage_0" plugins[name] = sharedStoragePlugin{ config: deprecatedSharedStorageConfig.SubSection(pluginType), @@ -623,16 +623,22 @@ func (nm *namespaceManager) loadNamespace(ctx context.Context, name string, inde 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) + orgKey := multipartyConf.GetString(coreconfig.NamespaceMultipartyOrgKey) + orgDesc := multipartyConf.GetString(coreconfig.NamespaceMultipartyOrgDescription) + deprecatedOrgName := config.GetString(coreconfig.OrgName) + deprecatedOrgKey := config.GetString(coreconfig.OrgKey) + deprecatedOrgDesc := config.GetString(coreconfig.OrgDescription) + if deprecatedOrgName != "" || deprecatedOrgKey != "" || deprecatedOrgDesc != "" { + log.L(ctx).Warnf("Your org config uses a deprecated configuration structure - the org configuration has been moved under the 'namespaces.predefined[].multiparty' section") + } if orgName == "" { - orgName = config.GetString(coreconfig.OrgName) + orgName = deprecatedOrgName } - orgKey := multipartyConf.GetString(coreconfig.NamespaceMultipartyOrgKey) if orgKey == "" { - orgKey = config.GetString(coreconfig.OrgKey) + orgKey = deprecatedOrgKey } - orgDesc := multipartyConf.GetString(coreconfig.NamespaceMultipartyOrgDescription) if orgDesc == "" { - orgDesc = config.GetString(coreconfig.OrgDescription) + orgDesc = deprecatedOrgDesc } multiparty := multipartyConf.Get(coreconfig.NamespaceMultipartyEnabled) if multiparty == nil { From 35d21d54c7512d726aad2e29660d6a1d595cc2cc Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Thu, 12 May 2022 16:57:10 -0400 Subject: [PATCH 06/27] Store definitions locally in gateway mode Signed-off-by: Andrew Richardson --- .../000094_allow_local_identity.down.sql | 1 + .../000094_allow_local_identity.up.sql | 6 ++ .../000094_allow_local_identity.down.sql | 1 + .../sqlite/000094_allow_local_identity.up.sql | 4 + internal/coremsgs/en_error_messages.go | 1 + internal/definitions/definition_handler.go | 13 ++- .../definition_handler_identity_claim.go | 11 ++- .../definition_handler_identity_claim_test.go | 77 +++++++++++++++- ...tion_handler_identity_verification_test.go | 2 + .../definition_handler_network_node_test.go | 2 + .../definition_handler_network_org_test.go | 2 + .../definitions/definition_handler_test.go | 15 ++- internal/defsender/datatype.go | 6 ++ internal/defsender/datatype_test.go | 16 ++++ internal/defsender/sender.go | 92 ++++++++++++------- internal/defsender/sender_test.go | 57 +++++++++++- internal/defsender/tokenpool_test.go | 1 + internal/identity/identitymanager.go | 12 ++- internal/identity/identitymanager_test.go | 21 ++++- internal/networkmap/register_identity.go | 5 +- internal/orchestrator/orchestrator.go | 5 +- internal/orchestrator/orchestrator_test.go | 1 + mocks/definitionsmocks/definition_handler.go | 14 +++ mocks/defsendermocks/sender.go | 6 ++ 24 files changed, 317 insertions(+), 54 deletions(-) create mode 100644 db/migrations/postgres/000094_allow_local_identity.down.sql create mode 100644 db/migrations/postgres/000094_allow_local_identity.up.sql create mode 100644 db/migrations/sqlite/000094_allow_local_identity.down.sql create mode 100644 db/migrations/sqlite/000094_allow_local_identity.up.sql diff --git a/db/migrations/postgres/000094_allow_local_identity.down.sql b/db/migrations/postgres/000094_allow_local_identity.down.sql new file mode 100644 index 000000000..b4cd87f28 --- /dev/null +++ b/db/migrations/postgres/000094_allow_local_identity.down.sql @@ -0,0 +1 @@ +-- No down migration (can't add back NOT NULL constraint) diff --git a/db/migrations/postgres/000094_allow_local_identity.up.sql b/db/migrations/postgres/000094_allow_local_identity.up.sql new file mode 100644 index 000000000..69fa7a962 --- /dev/null +++ b/db/migrations/postgres/000094_allow_local_identity.up.sql @@ -0,0 +1,6 @@ +BEGIN; +ALTER TABLE identities RENAME COLUMN messages_claim TO messages_claim_old; +ALTER TABLE identities ADD COLUMN messages_claim UUID; +UPDATE identities SET messages_claim = messages_claim_old; +ALTER TABLE identities DROP COLUMN messages_claim_old; +COMMIT; diff --git a/db/migrations/sqlite/000094_allow_local_identity.down.sql b/db/migrations/sqlite/000094_allow_local_identity.down.sql new file mode 100644 index 000000000..299c848d8 --- /dev/null +++ b/db/migrations/sqlite/000094_allow_local_identity.down.sql @@ -0,0 +1 @@ +-- No down migration (can't add back NOT NULL constraint) \ No newline at end of file diff --git a/db/migrations/sqlite/000094_allow_local_identity.up.sql b/db/migrations/sqlite/000094_allow_local_identity.up.sql new file mode 100644 index 000000000..cef04a1c0 --- /dev/null +++ b/db/migrations/sqlite/000094_allow_local_identity.up.sql @@ -0,0 +1,4 @@ +ALTER TABLE identities RENAME COLUMN messages_claim TO messages_claim_old; +ALTER TABLE identities ADD COLUMN messages_claim UUID; +UPDATE identities SET messages_claim = messages_claim_old; +ALTER TABLE identities DROP COLUMN messages_claim_old; diff --git a/internal/coremsgs/en_error_messages.go b/internal/coremsgs/en_error_messages.go index 33c8ef61e..347152793 100644 --- a/internal/coremsgs/en_error_messages.go +++ b/internal/coremsgs/en_error_messages.go @@ -253,4 +253,5 @@ var ( MsgInvalidNamespaceUUID = ffe("FF10411", "Expected 'namespace:' prefix on ID '%s'", 400) MsgSubscriptionIDInvalid = ffe("FF10412", "Invalid subscription ID: %s") MsgActionOnlyValidMultiparty = ffe("FF10413", "This action is only valid in a multiparty namespace", 400) + MsgDefinitionRejected = ffe("FF10414", "Definition rejected") ) diff --git a/internal/definitions/definition_handler.go b/internal/definitions/definition_handler.go index 020642d92..9f7424674 100644 --- a/internal/definitions/definition_handler.go +++ b/internal/definitions/definition_handler.go @@ -37,6 +37,7 @@ import ( type DefinitionHandler interface { HandleDefinitionBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) + HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error } type HandlerResult struct { @@ -78,6 +79,7 @@ func (dma DefinitionMessageAction) String() string { type definitionHandlers struct { namespace string + multiparty bool database database.Plugin blockchain blockchain.Plugin exchange dataexchange.Plugin // optional @@ -87,12 +89,13 @@ type definitionHandlers struct { contracts contracts.Manager } -func NewDefinitionHandler(ctx context.Context, ns string, di database.Plugin, bi blockchain.Plugin, dx dataexchange.Plugin, dm data.Manager, im identity.Manager, am assets.Manager, cm contracts.Manager) (DefinitionHandler, error) { +func NewDefinitionHandler(ctx context.Context, ns string, multiparty bool, di database.Plugin, bi blockchain.Plugin, dx dataexchange.Plugin, dm data.Manager, im identity.Manager, am assets.Manager, cm contracts.Manager) (DefinitionHandler, error) { if di == nil || bi == nil || dm == nil || im == nil || am == nil || cm == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "DefinitionHandler") } return &definitionHandlers{ namespace: ns, + multiparty: multiparty, database: di, blockchain: bi, exchange: dx, @@ -146,3 +149,11 @@ func (dh *definitionHandlers) getSystemBroadcastPayload(ctx context.Context, msg res.SetBroadcastMessage(msg.Header.ID) return true } + +func (dh *definitionHandlers) HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error { + result, err := dh.HandleDefinitionBroadcast(ctx, state, msg, core.DataArray{data}, nil) + if result.Action == ActionReject { + return i18n.WrapError(ctx, err, coremsgs.MsgDefinitionRejected) + } + return err +} diff --git a/internal/definitions/definition_handler_identity_claim.go b/internal/definitions/definition_handler_identity_claim.go index cbd797291..e2c8e59d5 100644 --- a/internal/definitions/definition_handler_identity_claim.go +++ b/internal/definitions/definition_handler_identity_claim.go @@ -146,9 +146,11 @@ func (dh *definitionHandlers) handleIdentityClaim(ctx context.Context, state *co return HandlerResult{Action: ActionWait}, nil } - // Check signature verification - if err := dh.verifyClaimSignature(ctx, msg, identity, parent); err != nil { - return HandlerResult{Action: ActionReject}, err + // For multi-party namespaces, check that the claim message was appropriately signed + if dh.multiparty { + if err := dh.verifyClaimSignature(ctx, msg, identity, parent); err != nil { + return HandlerResult{Action: ActionReject}, err + } } existingIdentity, err := dh.database.GetIdentityByName(ctx, identity.Type, identity.Namespace, identity.Name) @@ -175,7 +177,8 @@ func (dh *definitionHandlers) handleIdentityClaim(ctx context.Context, state *co return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedConflict, "identity verifier", verifierLabel, existingVerifierLabel) } - if parent != nil && identity.Type != core.IdentityTypeNode { + // For child identities in multi-party namespaces, check that the parent signed a verification message + if dh.multiparty && parent != nil && identity.Type != core.IdentityTypeNode { // The verification might be passed into this function, if we confirm the verification second, // or we might have to hunt for it, if we confirm the verification first. if verificationID == nil { diff --git a/internal/definitions/definition_handler_identity_claim_test.go b/internal/definitions/definition_handler_identity_claim_test.go index 8e7627dd3..ae4961020 100644 --- a/internal/definitions/definition_handler_identity_claim_test.go +++ b/internal/definitions/definition_handler_identity_claim_test.go @@ -97,10 +97,11 @@ func testCustomClaimAndVerification(t *testing.T) (*core.Identity, *core.Identit claimMsg := &core.Message{ Header: core.MessageHeader{ - ID: custom1.Messages.Claim, - Type: core.MessageTypeDefinition, - Tag: core.SystemTagIdentityClaim, - Topics: core.FFStringArray{custom1.Topic()}, + Namespace: "ns1", + ID: custom1.Messages.Claim, + Type: core.MessageTypeDefinition, + Tag: core.SystemTagIdentityClaim, + Topics: core.FFStringArray{custom1.Topic()}, SignerRef: core.SignerRef{ Author: custom1.DID, Key: "0x12345", @@ -173,6 +174,8 @@ func TestHandleDefinitionIdentityClaimCustomWithExistingParentVerificationOk(t * mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{verifyData}, false, nil).Once() mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{verifyData}, true, nil) + dh.multiparty = true + bs.AddPendingConfirm(verifyMsg.Header.ID, verifyMsg) action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) @@ -220,6 +223,8 @@ func TestHandleDefinitionIdentityClaimIdempotentReplay(t *testing.T) { mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{verifyData}, false, nil).Once() mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{verifyData}, true, nil) + dh.multiparty = true + bs.AddPendingConfirm(verifyMsg.Header.ID, verifyMsg) action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) @@ -254,6 +259,8 @@ func TestHandleDefinitionIdentityClaimFailInsertIdentity(t *testing.T) { mdm := dh.data.(*datamocks.Manager) mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{verifyData}, true, nil) + dh.multiparty = true + bs.AddPendingConfirm(verifyMsg.Header.ID, verifyMsg) action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) @@ -284,6 +291,8 @@ func TestHandleDefinitionIdentityClaimVerificationDataFail(t *testing.T) { mdm := dh.data.(*datamocks.Manager) mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(nil, false, fmt.Errorf("pop")) + dh.multiparty = true + bs.AddPendingConfirm(verifyMsg.Header.ID, verifyMsg) action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) @@ -314,6 +323,8 @@ func TestHandleDefinitionIdentityClaimVerificationMissingData(t *testing.T) { mdm := dh.data.(*datamocks.Manager) mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{}, true, nil) + dh.multiparty = true + bs.AddPendingConfirm(verifyMsg.Header.ID, verifyMsg) action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) @@ -345,6 +356,8 @@ func TestHandleDefinitionIdentityClaimFailInsertVerifier(t *testing.T) { mdm := dh.data.(*datamocks.Manager) mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{verifyData}, true, nil) + dh.multiparty = true + bs.AddPendingConfirm(verifyMsg.Header.ID, verifyMsg) action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) @@ -372,6 +385,8 @@ func TestHandleDefinitionIdentityClaimCustomMissingParentVerificationOk(t *testi mdi.On("GetVerifierByValue", ctx, core.VerifierTypeEthAddress, "ns1", "0x12345").Return(nil, nil) mdi.On("GetMessages", ctx, "ns1", mock.Anything).Return([]*core.Message{}, nil, nil) + dh.multiparty = true + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) // Just wait for the verification to come in later assert.NoError(t, err) @@ -396,6 +411,8 @@ func TestHandleDefinitionIdentityClaimCustomParentVerificationFail(t *testing.T) mdi.On("GetVerifierByValue", ctx, core.VerifierTypeEthAddress, "ns1", "0x12345").Return(nil, nil) mdi.On("GetMessages", ctx, "ns1", mock.Anything).Return(nil, nil, fmt.Errorf("pop")) + dh.multiparty = true + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -421,6 +438,8 @@ func TestHandleDefinitionIdentityClaimVerifierClash(t *testing.T) { Hash: fftypes.NewRandB32(), }, nil) + dh.multiparty = true + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -444,6 +463,8 @@ func TestHandleDefinitionIdentityClaimVerifierError(t *testing.T) { mdi.On("GetIdentityByID", ctx, "ns1", custom1.ID).Return(nil, nil) mdi.On("GetVerifierByValue", ctx, core.VerifierTypeEthAddress, "ns1", "0x12345").Return(nil, fmt.Errorf("pop")) + dh.multiparty = true + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -469,6 +490,8 @@ func TestHandleDefinitionIdentityClaimIdentityClash(t *testing.T) { }, }, nil) + dh.multiparty = true + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -491,6 +514,8 @@ func TestHandleDefinitionIdentityClaimIdentityError(t *testing.T) { mdi.On("GetIdentityByName", ctx, custom1.Type, custom1.Namespace, custom1.Name).Return(nil, nil) mdi.On("GetIdentityByID", ctx, "ns1", custom1.ID).Return(nil, fmt.Errorf("pop")) + dh.multiparty = true + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) @@ -510,6 +535,8 @@ func TestHandleDefinitionIdentityMissingAuthor(t *testing.T) { mim := dh.identity.(*identitymanagermocks.Manager) mim.On("VerifyIdentityChain", ctx, custom1).Return(org1, false, nil) + dh.multiparty = true + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -528,6 +555,8 @@ func TestHandleDefinitionIdentityClaimBadSignature(t *testing.T) { mim := dh.identity.(*identitymanagermocks.Manager) mim.On("VerifyIdentityChain", ctx, custom1).Return(org1, false, nil) + dh.multiparty = true + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, claimMsg, core.DataArray{claimData}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Error(t, err) @@ -585,3 +614,43 @@ func TestHandleDefinitionIdentityClaimBadData(t *testing.T) { bs.assertNoFinalizers() } + +func TestHandleDefinitionIdentityClaimGateway(t *testing.T) { + dh, bs := newTestDefinitionHandler(t) + ctx := context.Background() + + custom1, org1, claimMsg, claimData, _, _ := testCustomClaimAndVerification(t) + + mim := dh.identity.(*identitymanagermocks.Manager) + mim.On("VerifyIdentityChain", ctx, custom1).Return(org1, false, nil) + + mdi := dh.database.(*databasemocks.Plugin) + mdi.On("GetIdentityByName", ctx, custom1.Type, custom1.Namespace, custom1.Name).Return(nil, nil) + mdi.On("GetIdentityByID", ctx, "ns1", custom1.ID).Return(nil, nil) + mdi.On("GetVerifierByValue", ctx, core.VerifierTypeEthAddress, "ns1", "0x12345").Return(nil, nil) + mdi.On("UpsertIdentity", ctx, mock.MatchedBy(func(identity *core.Identity) bool { + assert.Equal(t, *claimMsg.Header.ID, *identity.Messages.Claim) + assert.Nil(t, identity.Messages.Verification) + return true + }), database.UpsertOptimizationNew).Return(nil) + mdi.On("UpsertVerifier", ctx, mock.MatchedBy(func(verifier *core.Verifier) bool { + assert.Equal(t, core.VerifierTypeEthAddress, verifier.Type) + assert.Equal(t, "0x12345", verifier.Value) + assert.Equal(t, *custom1.ID, *verifier.Identity) + return true + }), database.UpsertOptimizationNew).Return(nil) + mdi.On("InsertEvent", mock.Anything, mock.MatchedBy(func(event *core.Event) bool { + return event.Type == core.EventTypeIdentityConfirmed + })).Return(nil) + + err := dh.HandleDefinition(ctx, &bs.BatchState, claimMsg, claimData) + assert.NoError(t, err) + assert.Equal(t, bs.ConfirmedDIDClaims, []string{custom1.DID}) + + err = bs.RunFinalize(ctx) + assert.NoError(t, err) + + mdi.AssertExpectations(t) + mim.AssertExpectations(t) + +} diff --git a/internal/definitions/definition_handler_identity_verification_test.go b/internal/definitions/definition_handler_identity_verification_test.go index 71aaa2403..36a604c80 100644 --- a/internal/definitions/definition_handler_identity_verification_test.go +++ b/internal/definitions/definition_handler_identity_verification_test.go @@ -65,6 +65,8 @@ func TestHandleDefinitionIdentityVerificationWithExistingClaimOk(t *testing.T) { mdm := dh.data.(*datamocks.Manager) mdm.On("GetMessageDataCached", ctx, mock.Anything).Return(core.DataArray{claimData}, true, nil) + dh.multiparty = true + bs.AddPendingConfirm(claimMsg.Header.ID, claimMsg) action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, verifyMsg, core.DataArray{verifyData}, fftypes.NewUUID()) diff --git a/internal/definitions/definition_handler_network_node_test.go b/internal/definitions/definition_handler_network_node_test.go index 95567a944..258922008 100644 --- a/internal/definitions/definition_handler_network_node_test.go +++ b/internal/definitions/definition_handler_network_node_test.go @@ -130,6 +130,8 @@ func TestHandleDeprecatedNodeDefinitionOK(t *testing.T) { mdx := dh.exchange.(*dataexchangemocks.Plugin) mdx.On("AddPeer", ctx, node.DX.Endpoint).Return(nil) + dh.multiparty = true + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, msg, core.DataArray{data}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) diff --git a/internal/definitions/definition_handler_network_org_test.go b/internal/definitions/definition_handler_network_org_test.go index 8fe989de1..7b4a7928c 100644 --- a/internal/definitions/definition_handler_network_org_test.go +++ b/internal/definitions/definition_handler_network_org_test.go @@ -110,6 +110,8 @@ func TestHandleDeprecatedOrgDefinitionOK(t *testing.T) { return event.Type == core.EventTypeIdentityConfirmed })).Return(nil) + dh.multiparty = true + action, err := dh.HandleDefinitionBroadcast(ctx, &bs.BatchState, msg, core.DataArray{data}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionConfirm}, action) assert.NoError(t, err) diff --git a/internal/definitions/definition_handler_test.go b/internal/definitions/definition_handler_test.go index c159e70b3..38def011b 100644 --- a/internal/definitions/definition_handler_test.go +++ b/internal/definitions/definition_handler_test.go @@ -42,7 +42,7 @@ func newTestDefinitionHandler(t *testing.T) (*definitionHandlers, *testDefinitio mam := &assetmocks.Manager{} mcm := &contractmocks.Manager{} mbi.On("VerifierType").Return(core.VerifierTypeEthAddress).Maybe() - dh, _ := NewDefinitionHandler(context.Background(), "ns1", mdi, mbi, mdx, mdm, mim, mam, mcm) + dh, _ := NewDefinitionHandler(context.Background(), "ns1", false, mdi, mbi, mdx, mdm, mim, mam, mcm) return dh.(*definitionHandlers), newTestDefinitionBatchState(t) } @@ -68,7 +68,7 @@ func (bs *testDefinitionBatchState) assertNoFinalizers() { } func TestInitFail(t *testing.T) { - _, err := NewDefinitionHandler(context.Background(), "", nil, nil, nil, nil, nil, nil, nil) + _, err := NewDefinitionHandler(context.Background(), "", false, nil, nil, nil, nil, nil, nil, nil) assert.Regexp(t, "FF10128", err) } @@ -111,3 +111,14 @@ func TestActionEnum(t *testing.T) { assert.Equal(t, "wait", fmt.Sprintf("%s", ActionWait)) assert.Equal(t, "unknown", fmt.Sprintf("%s", DefinitionMessageAction(999))) } + +func TestHandleDefinitionReject(t *testing.T) { + dh, bs := newTestDefinitionHandler(t) + err := dh.HandleDefinition(context.Background(), &bs.BatchState, &core.Message{ + Header: core.MessageHeader{ + Tag: "unknown", + }, + }, &core.Data{}) + assert.Error(t, err) + bs.assertNoFinalizers() +} diff --git a/internal/defsender/datatype.go b/internal/defsender/datatype.go index a23087303..635629299 100644 --- a/internal/defsender/datatype.go +++ b/internal/defsender/datatype.go @@ -20,11 +20,17 @@ import ( "context" "github.com/hyperledger/firefly-common/pkg/fftypes" + "github.com/hyperledger/firefly-common/pkg/i18n" + "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/pkg/core" ) func (bm *definitionSender) CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (*core.Message, error) { + if !bm.multiparty { + return nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + } + // Validate the input data definition data datatype.ID = fftypes.NewUUID() datatype.Created = fftypes.Now() diff --git a/internal/defsender/datatype_test.go b/internal/defsender/datatype_test.go index 373469c7f..d66c04012 100644 --- a/internal/defsender/datatype_test.go +++ b/internal/defsender/datatype_test.go @@ -31,9 +31,17 @@ import ( "github.com/stretchr/testify/mock" ) +func TestCreateDatatypeGatewayMode(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + _, err := ds.CreateDatatype(context.Background(), &core.Datatype{}, false) + assert.Regexp(t, "FF10413", err) +} + func TestCreateDatatypeBadType(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() + ds.multiparty = true _, err := ds.CreateDatatype(context.Background(), &core.Datatype{ Validator: core.ValidatorType("wrong"), }, false) @@ -43,6 +51,7 @@ func TestCreateDatatypeBadType(t *testing.T) { func TestBroadcastDatatypeBadValue(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() + ds.multiparty = true mdm := ds.data.(*datamocks.Manager) mdm.On("CheckDatatype", mock.Anything, mock.Anything).Return(nil) mim := ds.identity.(*identitymanagermocks.Manager) @@ -54,11 +63,15 @@ func TestBroadcastDatatypeBadValue(t *testing.T) { Value: fftypes.JSONAnyPtr(`!unparsable`), }, false) assert.Regexp(t, "FF10137.*value", err) + + mdm.AssertExpectations(t) + mim.AssertExpectations(t) } func TestCreateDatatypeInvalid(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() + ds.multiparty = true mdm := ds.data.(*datamocks.Manager) mim := ds.identity.(*identitymanagermocks.Manager) @@ -72,11 +85,14 @@ func TestCreateDatatypeInvalid(t *testing.T) { Value: fftypes.JSONAnyPtr(`{"some": "data"}`), }, false) assert.EqualError(t, err, "pop") + + mdm.AssertExpectations(t) } func TestBroadcastOk(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() + ds.multiparty = true mdm := ds.data.(*datamocks.Manager) mim := ds.identity.(*identitymanagermocks.Manager) mbm := ds.broadcast.(*broadcastmocks.Manager) diff --git a/internal/defsender/sender.go b/internal/defsender/sender.go index e52dcbe96..c4f37e1f1 100644 --- a/internal/defsender/sender.go +++ b/internal/defsender/sender.go @@ -29,9 +29,14 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) +type DefinitionHandler interface { + HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error +} + type Sender interface { core.Named + Init(handler DefinitionHandler) CreateDefinition(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) CreateDefinitionWithIdentity(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (msg *core.Message, err error) @@ -40,23 +45,26 @@ type Sender interface { } type definitionSender struct { - ctx context.Context - namespace string - broadcast broadcast.Manager // optional - identity identity.Manager - data data.Manager + ctx context.Context + namespace string + multiparty bool + broadcast broadcast.Manager // optional + identity identity.Manager + data data.Manager + handler DefinitionHandler } -func NewDefinitionSender(ctx context.Context, ns string, bm broadcast.Manager, im identity.Manager, dm data.Manager) (Sender, error) { +func NewDefinitionSender(ctx context.Context, ns string, multiparty bool, bm broadcast.Manager, im identity.Manager, dm data.Manager) (Sender, error) { if im == nil || dm == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError) } return &definitionSender{ - ctx: ctx, - namespace: ns, - broadcast: bm, - identity: im, - data: dm, + ctx: ctx, + namespace: ns, + multiparty: multiparty, + broadcast: bm, + identity: im, + data: dm, }, nil } @@ -64,6 +72,10 @@ func (bm *definitionSender) Name() string { return "DefinitionSender" } +func (bm *definitionSender) Init(handler DefinitionHandler) { + bm.handler = handler +} + func (bm *definitionSender) CreateDefinition(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) { return bm.CreateDefinitionWithIdentity(ctx, def, &core.SignerRef{ /* resolve to node default */ }, tag, waitConfirm) } @@ -75,55 +87,71 @@ func (bm *definitionSender) CreateDefinitionWithIdentity(ctx context.Context, de return nil, err } - return bm.broadcastDefinitionCommon(ctx, def, signingIdentity, tag, waitConfirm) + return bm.createDefinitionCommon(ctx, def, signingIdentity, tag, waitConfirm) } // CreateIdentityClaim is a special form of CreateDefinition where the signing identity does not need to have been pre-registered // The blockchain "key" will be normalized, but the "author" will pass through unchecked func (bm *definitionSender) CreateIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { - signingIdentity.Key, err = bm.identity.NormalizeSigningKey(ctx, signingIdentity.Key, identity.KeyNormalizationBlockchainPlugin) - if err != nil { - return nil, err + if signingIdentity != nil { + signingIdentity.Key, err = bm.identity.NormalizeSigningKey(ctx, signingIdentity.Key, identity.KeyNormalizationBlockchainPlugin) + if err != nil { + return nil, err + } } - return bm.broadcastDefinitionCommon(ctx, def, signingIdentity, tag, waitConfirm) + return bm.createDefinitionCommon(ctx, def, signingIdentity, tag, waitConfirm) } -func (bm *definitionSender) broadcastDefinitionCommon(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { - - if bm.broadcast == nil { - return nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) - } +func (bm *definitionSender) createDefinitionCommon(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { b, err := json.Marshal(&def) if err != nil { return nil, i18n.WrapError(ctx, err, coremsgs.MsgSerializationFailed) } - + dataValue := fftypes.JSONAnyPtrBytes(b) message := &core.MessageInOut{ Message: core.Message{ Header: core.MessageHeader{ Namespace: bm.namespace, Type: core.MessageTypeDefinition, - SignerRef: *signingIdentity, Topics: core.FFStringArray{def.Topic()}, Tag: tag, TxType: core.TransactionTypeBatchPin, }, }, - InlineData: core.InlineData{ - &core.DataRefOrValue{ - Value: fftypes.JSONAnyPtrBytes(b), - }, - }, } - sender := bm.broadcast.NewBroadcast(message) + if signingIdentity != nil { + message.Header.SignerRef = *signingIdentity + } - if waitConfirm { - err = sender.SendAndWait(ctx) + if bm.multiparty { + message.InlineData = core.InlineData{ + &core.DataRefOrValue{Value: dataValue}, + } + sender := bm.broadcast.NewBroadcast(message) + if waitConfirm { + err = sender.SendAndWait(ctx) + } else { + err = sender.Send(ctx) + } } else { - err = sender.Send(ctx) + data := &core.Data{Value: dataValue} + err = bm.createDefinitionLocal(ctx, &message.Message, data) } + return &message.Message, err } + +func (bm *definitionSender) createDefinitionLocal(ctx context.Context, msg *core.Message, data *core.Data) (err error) { + state := &core.BatchState{ + PendingConfirms: make(map[fftypes.UUID]*core.Message), + } + if err = bm.handler.HandleDefinition(ctx, state, msg, data); err == nil { + if err = state.RunPreFinalize(ctx); err == nil { + err = state.RunFinalize(ctx) + } + } + return err +} diff --git a/internal/defsender/sender_test.go b/internal/defsender/sender_test.go index f42ea0c42..9eeafc388 100644 --- a/internal/defsender/sender_test.go +++ b/internal/defsender/sender_test.go @@ -31,19 +31,27 @@ import ( "github.com/stretchr/testify/mock" ) +type mockDefinitionHandler struct { + err error +} + +func (dh *mockDefinitionHandler) HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error { + return dh.err +} + func newTestDefinitionSender(t *testing.T) (*definitionSender, func()) { mbm := &broadcastmocks.Manager{} mim := &identitymanagermocks.Manager{} mdm := &datamocks.Manager{} ctx, cancel := context.WithCancel(context.Background()) - b, err := NewDefinitionSender(ctx, "ns1", mbm, mim, mdm) + b, err := NewDefinitionSender(ctx, "ns1", false, mbm, mim, mdm) assert.NoError(t, err) return b.(*definitionSender), cancel } func TestInitFail(t *testing.T) { - _, err := NewDefinitionSender(context.Background(), "", nil, nil, nil) + _, err := NewDefinitionSender(context.Background(), "", false, nil, nil, nil) assert.Regexp(t, "FF10128", err) } @@ -65,6 +73,7 @@ func TestCreateDefinitionConfirm(t *testing.T) { mbm.On("NewBroadcast", mock.Anything).Return(mms) mms.On("SendAndWait", mock.Anything).Return(nil) + ds.multiparty = true _, err := ds.CreateDefinition(ds.ctx, &core.Namespace{}, core.SystemTagDefineNamespace, true) assert.NoError(t, err) @@ -85,6 +94,8 @@ func TestCreateIdentityClaim(t *testing.T) { mbm.On("NewBroadcast", mock.Anything).Return(mms) mms.On("SendAndWait", mock.Anything).Return(nil) + ds.multiparty = true + _, err := ds.CreateIdentityClaim(ds.ctx, &core.IdentityClaim{ Identity: &core.Identity{}, }, &core.SignerRef{ @@ -127,6 +138,8 @@ func TestCreateDatatypeDefinitionAsNodeConfirm(t *testing.T) { mbm.On("NewBroadcast", mock.Anything).Return(mms) mms.On("SendAndWait", mock.Anything).Return(nil) + ds.multiparty = true + _, err := ds.CreateDefinition(ds.ctx, &core.Datatype{}, core.SystemTagDefineNamespace, true) assert.NoError(t, err) @@ -147,3 +160,43 @@ func TestCreateDefinitionBadIdentity(t *testing.T) { }, core.SystemTagDefineNamespace, false) assert.Regexp(t, "pop", err) } + +func TestCreateDefinitionLocal(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + + mim := ds.identity.(*identitymanagermocks.Manager) + mbm := ds.broadcast.(*broadcastmocks.Manager) + mms := &sysmessagingmocks.MessageSender{} + mdh := &mockDefinitionHandler{} + ds.Init(mdh) + + mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) + + _, err := ds.CreateDefinition(ds.ctx, &core.Datatype{}, core.SystemTagDefineDatatype, true) + assert.NoError(t, err) + + mim.AssertExpectations(t) + mbm.AssertExpectations(t) + mms.AssertExpectations(t) +} + +func TestCreateDefinitionLocalError(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + + mim := ds.identity.(*identitymanagermocks.Manager) + mbm := ds.broadcast.(*broadcastmocks.Manager) + mms := &sysmessagingmocks.MessageSender{} + mdh := &mockDefinitionHandler{err: fmt.Errorf("pop")} + ds.Init(mdh) + + mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) + + _, err := ds.CreateDefinition(ds.ctx, &core.Datatype{}, core.SystemTagDefineDatatype, true) + assert.EqualError(t, err, "pop") + + mim.AssertExpectations(t) + mbm.AssertExpectations(t) + mms.AssertExpectations(t) +} diff --git a/internal/defsender/tokenpool_test.go b/internal/defsender/tokenpool_test.go index 7cfbba8c0..f97b88a01 100644 --- a/internal/defsender/tokenpool_test.go +++ b/internal/defsender/tokenpool_test.go @@ -55,6 +55,7 @@ func TestBroadcastTokenPoolInvalid(t *testing.T) { func TestCreateTokenPoolOk(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() + ds.multiparty = true mdm := ds.data.(*datamocks.Manager) mim := ds.identity.(*identitymanagermocks.Manager) diff --git a/internal/identity/identitymanager.go b/internal/identity/identitymanager.go index 41c0b6359..0911c4730 100644 --- a/internal/identity/identitymanager.go +++ b/internal/identity/identitymanager.go @@ -215,6 +215,10 @@ func (im *identityManager) resolveDefaultSigningIdentity(ctx context.Context, si if err != nil { return err } + if im.multiparty == nil { + signerRef.Key = verifierRef.Value + return nil + } identity, err := im.GetMultipartyRootOrg(ctx) if err != nil { return err @@ -332,7 +336,7 @@ func (im *identityManager) VerifyIdentityChain(ctx context.Context, checkIdentit if err := im.validateParentType(ctx, current, parent); err != nil { return nil, false, err } - if parent.Messages.Claim == nil { + if im.multiparty != nil && parent.Messages.Claim == nil { return nil, false, i18n.NewError(ctx, coremsgs.MsgParentIdentityMissingClaim, parent.DID, parent.ID) } current = parent @@ -343,7 +347,11 @@ func (im *identityManager) VerifyIdentityChain(ctx context.Context, checkIdentit } -func (im *identityManager) ResolveIdentitySigner(ctx context.Context, identity *core.Identity) (parentSigner *core.SignerRef, err error) { +func (im *identityManager) ResolveIdentitySigner(ctx context.Context, identity *core.Identity) (signer *core.SignerRef, err error) { + if im.multiparty == nil { + return nil, nil + } + // Find the message that registered the identity msg, err := im.database.GetMessageByID(ctx, im.namespace, identity.Messages.Claim) if err != nil { diff --git a/internal/identity/identitymanager_test.go b/internal/identity/identitymanager_test.go index 055be5ef0..103740683 100644 --- a/internal/identity/identitymanager_test.go +++ b/internal/identity/identitymanager_test.go @@ -997,8 +997,8 @@ func TestVerifyIdentityChainCustomOrgOrgOk(t *testing.T) { mdi.On("GetIdentityByID", ctx, "ns1", idIntermediateCustom.ID).Return(idIntermediateCustom, nil).Once() mdi.On("GetIdentityByID", ctx, "ns1", idRoot.ID).Return(idRoot, nil).Once() - immeidateParent, _, err := im.VerifyIdentityChain(ctx, idLeaf) - assert.Equal(t, idIntermediateCustom, immeidateParent) + immediateParent, _, err := im.VerifyIdentityChain(ctx, idLeaf) + assert.Equal(t, idIntermediateCustom, immediateParent) assert.NoError(t, err) mdi.AssertExpectations(t) @@ -1341,6 +1341,23 @@ func TestResolveIdentitySignerNotFound(t *testing.T) { mdi.AssertExpectations(t) } +func TestResolveIdentitySignerGateway(t *testing.T) { + ctx, im := newTestIdentityManager(t) + im.multiparty = nil + + signer, err := im.ResolveIdentitySigner(ctx, &core.Identity{ + IdentityBase: core.IdentityBase{ + ID: fftypes.NewUUID(), + DID: "did:firefly:org/org1", + Namespace: "ns1", + Name: "org1", + Type: core.IdentityTypeOrg, + }, + }) + assert.NoError(t, err) + assert.Nil(t, signer) +} + func TestParseKeyNormalizationConfig(t *testing.T) { assert.Equal(t, KeyNormalizationBlockchainPlugin, ParseKeyNormalizationConfig("blockchain_Plugin")) assert.Equal(t, KeyNormalizationNone, ParseKeyNormalizationConfig("none")) diff --git a/internal/networkmap/register_identity.go b/internal/networkmap/register_identity.go index 2254a7baf..e7e4496c3 100644 --- a/internal/networkmap/register_identity.go +++ b/internal/networkmap/register_identity.go @@ -60,7 +60,6 @@ func (nm *networkMap) RegisterIdentity(ctx context.Context, dto *core.IdentityCr if identity.Type == "" { identity.Type = core.IdentityTypeCustom } - identity.DID, _ = identity.GenerateDID(ctx) // Verify the chain @@ -89,9 +88,9 @@ func (nm *networkMap) RegisterIdentity(ctx context.Context, dto *core.IdentityCr return nil, i18n.NewError(ctx, coremsgs.MsgBlockchainKeyNotSet) } claimSigner = &core.SignerRef{ - Key: dto.Key, + Key: dto.Key, + Author: identity.DID, } - claimSigner.Author = identity.DID } if waitConfirm { diff --git a/internal/orchestrator/orchestrator.go b/internal/orchestrator/orchestrator.go index 4e8bfa8d7..e35124550 100644 --- a/internal/orchestrator/orchestrator.go +++ b/internal/orchestrator/orchestrator.go @@ -456,7 +456,7 @@ func (or *orchestrator) initManagers(ctx context.Context) (err error) { } if or.defsender == nil { - or.defsender, err = defsender.NewDefinitionSender(ctx, or.namespace, or.broadcast, or.identity, or.data) + or.defsender, err = defsender.NewDefinitionSender(ctx, or.namespace, or.config.Multiparty.Enabled, or.broadcast, or.identity, or.data) if err != nil { return err } @@ -488,7 +488,7 @@ func (or *orchestrator) initManagers(ctx context.Context) (err error) { func (or *orchestrator) initHandlers(ctx context.Context) (err error) { if or.defhandler == nil { - or.defhandler, err = definitions.NewDefinitionHandler(ctx, or.namespace, or.database(), or.blockchain(), or.dataexchange(), or.data, or.identity, or.assets, or.contracts) + or.defhandler, err = definitions.NewDefinitionHandler(ctx, or.namespace, or.config.Multiparty.Enabled, or.database(), or.blockchain(), or.dataexchange(), or.data, or.identity, or.assets, or.contracts) if err != nil { return err } @@ -521,6 +521,7 @@ func (or *orchestrator) initComponents(ctx context.Context) (err error) { } or.syncasync.Init(or.events) + or.defsender.Init(or.defhandler) return nil } diff --git a/internal/orchestrator/orchestrator_test.go b/internal/orchestrator/orchestrator_test.go index 0d3196b0d..606dc655e 100644 --- a/internal/orchestrator/orchestrator_test.go +++ b/internal/orchestrator/orchestrator_test.go @@ -175,6 +175,7 @@ func newTestOrchestrator() *testOrchestrator { tor.mcm.On("Name").Return("mock-cm").Maybe() tor.mmi.On("Name").Return("mock-mm").Maybe() tor.mmp.On("Name").Return("mock-mp").Maybe() + tor.mds.On("Init", mock.Anything).Maybe() return tor } diff --git a/mocks/definitionsmocks/definition_handler.go b/mocks/definitionsmocks/definition_handler.go index 6e5a74d99..f17878456 100644 --- a/mocks/definitionsmocks/definition_handler.go +++ b/mocks/definitionsmocks/definition_handler.go @@ -18,6 +18,20 @@ type DefinitionHandler struct { mock.Mock } +// HandleDefinition provides a mock function with given fields: ctx, state, msg, data +func (_m *DefinitionHandler) HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error { + ret := _m.Called(ctx, state, msg, data) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *core.BatchState, *core.Message, *core.Data) error); ok { + r0 = rf(ctx, state, msg, data) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // HandleDefinitionBroadcast provides a mock function with given fields: ctx, state, msg, data, tx func (_m *DefinitionHandler) HandleDefinitionBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (definitions.HandlerResult, error) { ret := _m.Called(ctx, state, msg, data, tx) diff --git a/mocks/defsendermocks/sender.go b/mocks/defsendermocks/sender.go index f908270da..a006507b8 100644 --- a/mocks/defsendermocks/sender.go +++ b/mocks/defsendermocks/sender.go @@ -5,6 +5,7 @@ package defsendermocks import ( context "context" + defsender "github.com/hyperledger/firefly/internal/defsender" core "github.com/hyperledger/firefly/pkg/core" mock "github.com/stretchr/testify/mock" @@ -130,6 +131,11 @@ func (_m *Sender) CreateTokenPool(ctx context.Context, pool *core.TokenPoolAnnou return r0, r1 } +// Init provides a mock function with given fields: handler +func (_m *Sender) Init(handler defsender.DefinitionHandler) { + _m.Called(handler) +} + // Name provides a mock function with given fields: func (_m *Sender) Name() string { ret := _m.Called() From cd7c354218b8bd69f4523ae3aa2244ba85df7a20 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Thu, 23 Jun 2022 16:31:46 -0400 Subject: [PATCH 07/27] Use lowercase for nested array keys due to Viper bug Due to https://github.com/spf13/viper/issues/1386, array keys with mixed case are not parsed correctly. At least for the time being, mitigate by changing some keys to all lowercase. Signed-off-by: Andrew Richardson --- docs/reference/config.md | 4 ++-- internal/coreconfig/coreconfig.go | 4 ++-- internal/coremsgs/en_config_descriptions.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/reference/config.md b/docs/reference/config.md index b182b10b4..36e850442 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -585,11 +585,11 @@ nav_order: 2 |Key|Description|Type|Default Value| |---|-----------|----|-------------| -|defaultKey|A default signing key for blockchain transactions within this namespace|`string`|`` +|defaultkey|A default signing key for blockchain transactions within this namespace|`string`|`` |description|A description for the namespace|`string`|`` |name|The name of the namespace (must be unique)|`string`|`` |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`|`` +|remotename|The namespace name to be sent in plugin calls, if it differs from namespace name|`string`|`` ## namespaces.predefined[].multiparty diff --git a/internal/coreconfig/coreconfig.go b/internal/coreconfig/coreconfig.go index 2d78ac2d9..7b3028110 100644 --- a/internal/coreconfig/coreconfig.go +++ b/internal/coreconfig/coreconfig.go @@ -34,11 +34,11 @@ const ( // NamespaceName is the long description for a pre-defined namespace NamespaceDescription = "description" // NamespaceRemoteName is the namespace name to be sent in plugin calls - NamespaceRemoteName = "remoteName" + NamespaceRemoteName = "remotename" // NamespacePlugins is the list of namespace plugins NamespacePlugins = "plugins" // NamespaceDefaultKey is the default signing key for blockchain transactions within this namespace - NamespaceDefaultKey = "defaultKey" + NamespaceDefaultKey = "defaultkey" // 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 784862a18..49b7c0434 100644 --- a/internal/coremsgs/en_config_descriptions.go +++ b/internal/coremsgs/en_config_descriptions.go @@ -252,8 +252,8 @@ var ( ConfigNamespacesPredefinedName = ffc("config.namespaces.predefined[].name", "The name of the namespace (must be unique)", i18n.StringType) ConfigNamespacesPredefinedDescription = ffc("config.namespaces.predefined[].description", "A description for the namespace", i18n.StringType) 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) + 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) 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) From e974ce4295e58e8963eb86330830079ca1b3bf06 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Fri, 24 Jun 2022 14:15:09 -0400 Subject: [PATCH 08/27] Add helper for disabling routes based on orchestrator features Signed-off-by: Andrew Richardson --- internal/apiserver/route_get_data_blob.go | 4 ++ .../apiserver/route_get_data_blob_test.go | 2 + internal/apiserver/route_get_group_by_id.go | 11 +++-- internal/apiserver/route_get_groups.go | 11 +++-- .../route_get_status_batchmanager.go | 11 +++-- internal/apiserver/route_post_data.go | 4 ++ internal/apiserver/route_post_data_test.go | 9 ++++ .../apiserver/route_post_network_action.go | 4 ++ .../route_post_network_action_test.go | 2 + internal/apiserver/route_post_new_datatype.go | 4 ++ .../apiserver/route_post_new_datatype_test.go | 3 ++ .../route_post_new_message_broadcast.go | 11 +++-- .../route_post_new_message_private.go | 11 +++-- .../route_post_new_message_requestreply.go | 4 ++ ...oute_post_new_message_requestreply_test.go | 2 + .../apiserver/route_post_new_node_self.go | 4 ++ .../route_post_new_node_self_test.go | 2 + .../route_post_new_organization_self.go | 4 ++ .../route_post_new_organization_self_test.go | 2 + internal/apiserver/routes.go | 1 + internal/apiserver/server.go | 16 +++++--- internal/apiserver/server_test.go | 41 +++++++++++++++++++ internal/assets/token_transfer.go | 4 +- internal/coremsgs/en_error_messages.go | 5 ++- internal/data/blobstore.go | 4 +- .../definition_handler_identity_claim.go | 4 -- internal/defsender/datatype.go | 6 --- internal/defsender/datatype_test.go | 7 ---- internal/networkmap/register_node.go | 6 --- internal/orchestrator/message.go | 2 +- internal/orchestrator/orchestrator.go | 12 +++--- internal/orchestrator/orchestrator_test.go | 2 +- 32 files changed, 143 insertions(+), 72 deletions(-) diff --git a/internal/apiserver/route_get_data_blob.go b/internal/apiserver/route_get_data_blob.go index 3cd7388ff..993db912d 100644 --- a/internal/apiserver/route_get_data_blob.go +++ b/internal/apiserver/route_get_data_blob.go @@ -22,6 +22,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" "github.com/hyperledger/firefly/pkg/database" ) @@ -40,6 +41,9 @@ var getDataBlob = &ffapi.Route{ JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ FilterFactory: database.MessageQueryFactory, + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.MultiParty() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { blob, reader, err := cr.or.Data().DownloadBlob(cr.ctx, r.PP["dataid"]) if err == nil { diff --git a/internal/apiserver/route_get_data_blob_test.go b/internal/apiserver/route_get_data_blob_test.go index 9e823a435..01086c9af 100644 --- a/internal/apiserver/route_get_data_blob_test.go +++ b/internal/apiserver/route_get_data_blob_test.go @@ -24,6 +24,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/mocks/datamocks" + "github.com/hyperledger/firefly/mocks/multipartymocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -33,6 +34,7 @@ func TestGetDataBlob(t *testing.T) { o, r := newTestAPIServer() mdm := &datamocks.Manager{} o.On("Data").Return(mdm) + o.On("MultiParty").Return(&multipartymocks.Manager{}) req := httptest.NewRequest("GET", "/api/v1/namespaces/mynamespace/data/abcd1234/blob", nil) req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() diff --git a/internal/apiserver/route_get_group_by_id.go b/internal/apiserver/route_get_group_by_id.go index 198fe330f..1af934081 100644 --- a/internal/apiserver/route_get_group_by_id.go +++ b/internal/apiserver/route_get_group_by_id.go @@ -20,8 +20,8 @@ import ( "net/http" "github.com/hyperledger/firefly-common/pkg/ffapi" - "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -38,12 +38,11 @@ var getGroupByHash = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.Group{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.PrivateMessaging() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { - pm := cr.or.PrivateMessaging() - if pm == nil { - return nil, i18n.NewError(cr.ctx, coremsgs.MsgActionOnlyValidMultiparty) - } - return pm.GetGroupByID(cr.ctx, r.PP["hash"]) + return cr.or.PrivateMessaging().GetGroupByID(cr.ctx, r.PP["hash"]) }, }, } diff --git a/internal/apiserver/route_get_groups.go b/internal/apiserver/route_get_groups.go index cf75d4ee6..6afc20338 100644 --- a/internal/apiserver/route_get_groups.go +++ b/internal/apiserver/route_get_groups.go @@ -20,8 +20,8 @@ import ( "net/http" "github.com/hyperledger/firefly-common/pkg/ffapi" - "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" "github.com/hyperledger/firefly/pkg/database" ) @@ -38,12 +38,11 @@ var getGroups = &ffapi.Route{ JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ FilterFactory: database.GroupQueryFactory, + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.PrivateMessaging() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { - pm := cr.or.PrivateMessaging() - if pm == nil { - return nil, i18n.NewError(cr.ctx, coremsgs.MsgActionOnlyValidMultiparty) - } - return filterResult(pm.GetGroups(cr.ctx, cr.filter)) + return filterResult(cr.or.PrivateMessaging().GetGroups(cr.ctx, cr.filter)) }, }, } diff --git a/internal/apiserver/route_get_status_batchmanager.go b/internal/apiserver/route_get_status_batchmanager.go index ff7688a6c..ab1c3fe9f 100644 --- a/internal/apiserver/route_get_status_batchmanager.go +++ b/internal/apiserver/route_get_status_batchmanager.go @@ -20,9 +20,9 @@ import ( "net/http" "github.com/hyperledger/firefly-common/pkg/ffapi" - "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/batch" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" ) var getStatusBatchManager = &ffapi.Route{ @@ -36,12 +36,11 @@ var getStatusBatchManager = &ffapi.Route{ JSONOutputValue: func() interface{} { return &batch.ManagerStatus{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.BatchManager() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { - bm := cr.or.BatchManager() - if bm == nil { - return nil, i18n.NewError(cr.ctx, coremsgs.MsgActionOnlyValidMultiparty) - } - return bm.Status(), nil + return cr.or.BatchManager().Status(), nil }, }, } diff --git a/internal/apiserver/route_post_data.go b/internal/apiserver/route_post_data.go index 46e031211..fe0087ed8 100644 --- a/internal/apiserver/route_post_data.go +++ b/internal/apiserver/route_post_data.go @@ -25,6 +25,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -46,6 +47,9 @@ var postData = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.Data{} }, JSONOutputCodes: []int{http.StatusCreated}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.MultiParty() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { output, err = cr.or.Data().UploadJSON(cr.ctx, r.Input.(*core.DataRefOrValue)) return output, err diff --git a/internal/apiserver/route_post_data_test.go b/internal/apiserver/route_post_data_test.go index 9068f6159..b3b38333a 100644 --- a/internal/apiserver/route_post_data_test.go +++ b/internal/apiserver/route_post_data_test.go @@ -26,6 +26,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/log" "github.com/hyperledger/firefly/mocks/datamocks" + "github.com/hyperledger/firefly/mocks/multipartymocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -34,6 +35,7 @@ import ( func TestPostDataJSON(t *testing.T) { o, r := newTestAPIServer() mdm := &datamocks.Manager{} + o.On("MultiParty").Return(&multipartymocks.Manager{}) o.On("Data").Return(mdm) input := core.Data{} var buf bytes.Buffer @@ -52,6 +54,7 @@ func TestPostDataJSON(t *testing.T) { func TestPostDataJSONDefaultNS(t *testing.T) { o, r := newTestAPIServer() mdm := &datamocks.Manager{} + o.On("MultiParty").Return(&multipartymocks.Manager{}) o.On("Data").Return(mdm) input := core.Data{} var buf bytes.Buffer @@ -72,6 +75,7 @@ func TestPostDataBinary(t *testing.T) { o, r := newTestAPIServer() mdm := &datamocks.Manager{} + o.On("MultiParty").Return(&multipartymocks.Manager{}) o.On("Data").Return(mdm) var b bytes.Buffer @@ -97,6 +101,7 @@ func TestPostDataBinaryObjAutoMeta(t *testing.T) { o, r := newTestAPIServer() mdm := &datamocks.Manager{} + o.On("MultiParty").Return(&multipartymocks.Manager{}) o.On("Data").Return(mdm) var b bytes.Buffer @@ -143,6 +148,7 @@ func TestPostDataBinaryStringMetadata(t *testing.T) { o, r := newTestAPIServer() mdm := &datamocks.Manager{} + o.On("MultiParty").Return(&multipartymocks.Manager{}) o.On("Data").Return(mdm) var b bytes.Buffer @@ -176,6 +182,7 @@ func TestPostDataTrailingMetadata(t *testing.T) { o, r := newTestAPIServer() mdm := &datamocks.Manager{} + o.On("MultiParty").Return(&multipartymocks.Manager{}) o.On("Data").Return(mdm) var b bytes.Buffer @@ -207,6 +214,7 @@ func TestPostDataBinaryMissing(t *testing.T) { o, r := newTestAPIServer() mdm := &datamocks.Manager{} + o.On("MultiParty").Return(&multipartymocks.Manager{}) o.On("Data").Return(mdm) var b bytes.Buffer @@ -231,6 +239,7 @@ func TestPostDataBadForm(t *testing.T) { o, r := newTestAPIServer() mdm := &datamocks.Manager{} + o.On("MultiParty").Return(&multipartymocks.Manager{}) o.On("Data").Return(mdm) var b bytes.Buffer diff --git a/internal/apiserver/route_post_network_action.go b/internal/apiserver/route_post_network_action.go index 061ab9541..dcab6ac1e 100644 --- a/internal/apiserver/route_post_network_action.go +++ b/internal/apiserver/route_post_network_action.go @@ -21,6 +21,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -35,6 +36,9 @@ var postNetworkAction = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.NetworkAction{} }, JSONOutputCodes: []int{http.StatusAccepted}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.MultiParty() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { err = cr.or.SubmitNetworkAction(cr.ctx, r.Input.(*core.NetworkAction)) return r.Input, err diff --git a/internal/apiserver/route_post_network_action_test.go b/internal/apiserver/route_post_network_action_test.go index fe401d258..0c56f813e 100644 --- a/internal/apiserver/route_post_network_action_test.go +++ b/internal/apiserver/route_post_network_action_test.go @@ -22,6 +22,7 @@ import ( "net/http/httptest" "testing" + "github.com/hyperledger/firefly/mocks/multipartymocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -29,6 +30,7 @@ import ( func TestPostNetworkAction(t *testing.T) { o, r := newTestAPIServer() + o.On("MultiParty").Return(&multipartymocks.Manager{}) input := core.NetworkAction{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) diff --git a/internal/apiserver/route_post_new_datatype.go b/internal/apiserver/route_post_new_datatype.go index 328c55b44..7cd10e04d 100644 --- a/internal/apiserver/route_post_new_datatype.go +++ b/internal/apiserver/route_post_new_datatype.go @@ -22,6 +22,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -38,6 +39,9 @@ var postNewDatatype = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.Datatype{} }, JSONOutputCodes: []int{http.StatusAccepted, http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.MultiParty() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) diff --git a/internal/apiserver/route_post_new_datatype_test.go b/internal/apiserver/route_post_new_datatype_test.go index 58f5b21d4..e034c43b0 100644 --- a/internal/apiserver/route_post_new_datatype_test.go +++ b/internal/apiserver/route_post_new_datatype_test.go @@ -23,6 +23,7 @@ import ( "testing" "github.com/hyperledger/firefly/mocks/defsendermocks" + "github.com/hyperledger/firefly/mocks/multipartymocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -32,6 +33,7 @@ func TestPostNewDatatypes(t *testing.T) { o, r := newTestAPIServer() mds := &defsendermocks.Sender{} o.On("DefinitionSender").Return(mds) + o.On("MultiParty").Return(&multipartymocks.Manager{}) input := core.Datatype{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) @@ -50,6 +52,7 @@ func TestPostNewDatatypesSync(t *testing.T) { o, r := newTestAPIServer() mds := &defsendermocks.Sender{} o.On("DefinitionSender").Return(mds) + o.On("MultiParty").Return(&multipartymocks.Manager{}) input := core.Datatype{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) diff --git a/internal/apiserver/route_post_new_message_broadcast.go b/internal/apiserver/route_post_new_message_broadcast.go index b287e5152..bdc6c8bc0 100644 --- a/internal/apiserver/route_post_new_message_broadcast.go +++ b/internal/apiserver/route_post_new_message_broadcast.go @@ -21,8 +21,8 @@ import ( "strings" "github.com/hyperledger/firefly-common/pkg/ffapi" - "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -39,14 +39,13 @@ var postNewMessageBroadcast = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.Message{} }, JSONOutputCodes: []int{http.StatusAccepted, http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Broadcast() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) - bm := cr.or.Broadcast() - if bm == nil { - return nil, i18n.NewError(cr.ctx, coremsgs.MsgActionOnlyValidMultiparty) - } - output, err = bm.BroadcastMessage(cr.ctx, r.Input.(*core.MessageInOut), waitConfirm) + output, err = cr.or.Broadcast().BroadcastMessage(cr.ctx, r.Input.(*core.MessageInOut), waitConfirm) return output, err }, }, diff --git a/internal/apiserver/route_post_new_message_private.go b/internal/apiserver/route_post_new_message_private.go index 8a493376f..caab67131 100644 --- a/internal/apiserver/route_post_new_message_private.go +++ b/internal/apiserver/route_post_new_message_private.go @@ -21,8 +21,8 @@ import ( "strings" "github.com/hyperledger/firefly-common/pkg/ffapi" - "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -39,14 +39,13 @@ var postNewMessagePrivate = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.Message{} }, JSONOutputCodes: []int{http.StatusAccepted, http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.PrivateMessaging() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) - pm := cr.or.PrivateMessaging() - if pm == nil { - return nil, i18n.NewError(cr.ctx, coremsgs.MsgActionOnlyValidMultiparty) - } - return pm.SendMessage(cr.ctx, r.Input.(*core.MessageInOut), waitConfirm) + return cr.or.PrivateMessaging().SendMessage(cr.ctx, r.Input.(*core.MessageInOut), waitConfirm) }, }, } diff --git a/internal/apiserver/route_post_new_message_requestreply.go b/internal/apiserver/route_post_new_message_requestreply.go index dc5e98130..202c0a3bc 100644 --- a/internal/apiserver/route_post_new_message_requestreply.go +++ b/internal/apiserver/route_post_new_message_requestreply.go @@ -21,6 +21,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -35,6 +36,9 @@ var postNewMessageRequestReply = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.MessageInOut{} }, JSONOutputCodes: []int{http.StatusOK}, // Sync operation Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.PrivateMessaging() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { output, err = cr.or.RequestReply(cr.ctx, r.Input.(*core.MessageInOut)) return output, err diff --git a/internal/apiserver/route_post_new_message_requestreply_test.go b/internal/apiserver/route_post_new_message_requestreply_test.go index d6424013a..d8e43c7b1 100644 --- a/internal/apiserver/route_post_new_message_requestreply_test.go +++ b/internal/apiserver/route_post_new_message_requestreply_test.go @@ -22,6 +22,7 @@ import ( "net/http/httptest" "testing" + "github.com/hyperledger/firefly/mocks/privatemessagingmocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -29,6 +30,7 @@ import ( func TestPostNewMessageRequestReply(t *testing.T) { o, r := newTestAPIServer() + o.On("PrivateMessaging").Return(&privatemessagingmocks.Manager{}) o.On("RequestReply", mock.Anything, mock.Anything).Return(&core.MessageInOut{}, nil) input := &core.MessageInOut{} var buf bytes.Buffer diff --git a/internal/apiserver/route_post_new_node_self.go b/internal/apiserver/route_post_new_node_self.go index 47a24990a..ef25eb499 100644 --- a/internal/apiserver/route_post_new_node_self.go +++ b/internal/apiserver/route_post_new_node_self.go @@ -22,6 +22,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -38,6 +39,9 @@ var postNodesSelf = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.Identity{} }, JSONOutputCodes: []int{http.StatusAccepted, http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.MultiParty() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) diff --git a/internal/apiserver/route_post_new_node_self_test.go b/internal/apiserver/route_post_new_node_self_test.go index aa0ab0f69..66aa6f4c3 100644 --- a/internal/apiserver/route_post_new_node_self_test.go +++ b/internal/apiserver/route_post_new_node_self_test.go @@ -22,6 +22,7 @@ import ( "net/http/httptest" "testing" + "github.com/hyperledger/firefly/mocks/multipartymocks" "github.com/hyperledger/firefly/mocks/networkmapmocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" @@ -32,6 +33,7 @@ func TestPostNewNodeSelf(t *testing.T) { o, r := newTestAPIServer() mnm := &networkmapmocks.Manager{} o.On("NetworkMap").Return(mnm) + o.On("MultiParty").Return(&multipartymocks.Manager{}) input := core.EmptyInput{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) diff --git a/internal/apiserver/route_post_new_organization_self.go b/internal/apiserver/route_post_new_organization_self.go index 629aa6bc2..03ecd7e3b 100644 --- a/internal/apiserver/route_post_new_organization_self.go +++ b/internal/apiserver/route_post_new_organization_self.go @@ -22,6 +22,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -38,6 +39,9 @@ var postNewOrganizationSelf = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.Identity{} }, JSONOutputCodes: []int{http.StatusAccepted, http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.MultiParty() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) diff --git a/internal/apiserver/route_post_new_organization_self_test.go b/internal/apiserver/route_post_new_organization_self_test.go index e9900f1f8..e97962cb6 100644 --- a/internal/apiserver/route_post_new_organization_self_test.go +++ b/internal/apiserver/route_post_new_organization_self_test.go @@ -22,6 +22,7 @@ import ( "net/http/httptest" "testing" + "github.com/hyperledger/firefly/mocks/multipartymocks" "github.com/hyperledger/firefly/mocks/networkmapmocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" @@ -32,6 +33,7 @@ func TestNewOrganizationSelf(t *testing.T) { o, r := newTestAPIServer() mnm := &networkmapmocks.Manager{} o.On("NetworkMap").Return(mnm) + o.On("MultiParty").Return(&multipartymocks.Manager{}) input := core.EmptyInput{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) diff --git a/internal/apiserver/routes.go b/internal/apiserver/routes.go index 094ab816e..537907036 100644 --- a/internal/apiserver/routes.go +++ b/internal/apiserver/routes.go @@ -37,6 +37,7 @@ type coreRequest struct { type coreExtensions struct { FilterFactory database.QueryFactory + EnabledIf func(or orchestrator.Orchestrator) bool CoreJSONHandler func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) CoreFormUploadHandler func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) } diff --git a/internal/apiserver/server.go b/internal/apiserver/server.go index f9bc9a50e..58d4995aa 100644 --- a/internal/apiserver/server.go +++ b/internal/apiserver/server.go @@ -245,6 +245,14 @@ func (as *apiServer) routeHandler(hf *ffapi.HandlerFactory, mgr namespace.Manage // We also pass the Orchestrator context through ce := route.Extensions.(*coreExtensions) route.JSONHandler = func(r *ffapi.APIRequest) (output interface{}, err error) { + or, err := getOrchestrator(r.Req.Context(), mgr, route.Tag, r) + if err != nil { + return nil, err + } + if ce.EnabledIf != nil && !ce.EnabledIf(or) { + return nil, i18n.NewError(r.Req.Context(), coremsgs.MsgActionNotSupported) + } + var filter database.AndFilter if ce.FilterFactory != nil { filter, err = as.buildFilter(r.Req, ce.FilterFactory) @@ -253,11 +261,6 @@ func (as *apiServer) routeHandler(hf *ffapi.HandlerFactory, mgr namespace.Manage } } - or, err := getOrchestrator(r.Req.Context(), mgr, route.Tag, r) - if err != nil { - return nil, err - } - cr := &coreRequest{ mgr: mgr, or: or, @@ -273,6 +276,9 @@ func (as *apiServer) routeHandler(hf *ffapi.HandlerFactory, mgr namespace.Manage if err != nil { return nil, err } + if ce.EnabledIf != nil && !ce.EnabledIf(or) { + return nil, i18n.NewError(r.Req.Context(), coremsgs.MsgActionNotSupported) + } cr := &coreRequest{ mgr: mgr, diff --git a/internal/apiserver/server_test.go b/internal/apiserver/server_test.go index 38da684aa..74c4d73a7 100644 --- a/internal/apiserver/server_test.go +++ b/internal/apiserver/server_test.go @@ -393,3 +393,44 @@ func TestFormDataBadNamespace(t *testing.T) { assert.Equal(t, 404, res.Result().StatusCode) } + +func TestJSONDisabledRoute(t *testing.T) { + mgr, o, as := newTestServer() + r := as.createMuxRouter(context.Background(), mgr) + s := httptest.NewServer(r) + defer s.Close() + + o.On("PrivateMessaging").Return(nil) + + var b bytes.Buffer + req := httptest.NewRequest("GET", "/api/v1/namespaces/ns1/groups", &b) + req.Header.Set("Content-Type", "application/json; charset=utf-8") + res := httptest.NewRecorder() + + r.ServeHTTP(res, req) + + assert.Equal(t, 400, res.Result().StatusCode) +} + +func TestFormDataDisabledRoute(t *testing.T) { + mgr, o, as := newTestServer() + r := as.createMuxRouter(context.Background(), mgr) + s := httptest.NewServer(r) + defer s.Close() + + o.On("MultiParty").Return(nil) + + var b bytes.Buffer + w := multipart.NewWriter(&b) + writer, err := w.CreateFormFile("file", "filename.ext") + assert.NoError(t, err) + writer.Write([]byte(`some data`)) + w.Close() + req := httptest.NewRequest("POST", "/api/v1/namespaces/ns1/data", &b) + req.Header.Set("Content-Type", w.FormDataContentType()) + res := httptest.NewRecorder() + + r.ServeHTTP(res, req) + + assert.Equal(t, 400, res.Result().StatusCode) +} diff --git a/internal/assets/token_transfer.go b/internal/assets/token_transfer.go index c2ce91952..a0b17d065 100644 --- a/internal/assets/token_transfer.go +++ b/internal/assets/token_transfer.go @@ -271,12 +271,12 @@ func (s *transferSender) buildTransferMessage(ctx context.Context, in *core.Mess switch in.Header.Type { case core.MessageTypeTransferBroadcast: if s.mgr.broadcast == nil { - return nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + return nil, i18n.NewError(ctx, coremsgs.MsgMessagesNotSupported) } return s.mgr.broadcast.NewBroadcast(in), nil case core.MessageTypeTransferPrivate: if s.mgr.messaging == nil { - return nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + return nil, i18n.NewError(ctx, coremsgs.MsgMessagesNotSupported) } return s.mgr.messaging.NewMessage(in), nil default: diff --git a/internal/coremsgs/en_error_messages.go b/internal/coremsgs/en_error_messages.go index 347152793..f109a6320 100644 --- a/internal/coremsgs/en_error_messages.go +++ b/internal/coremsgs/en_error_messages.go @@ -252,6 +252,7 @@ var ( MsgDefRejectedHashMismatch = ffe("FF10410", "Rejected %s '%s' - hash mismatch: %s != %s") MsgInvalidNamespaceUUID = ffe("FF10411", "Expected 'namespace:' prefix on ID '%s'", 400) MsgSubscriptionIDInvalid = ffe("FF10412", "Invalid subscription ID: %s") - MsgActionOnlyValidMultiparty = ffe("FF10413", "This action is only valid in a multiparty namespace", 400) - MsgDefinitionRejected = ffe("FF10414", "Definition rejected") + MsgDefinitionRejected = ffe("FF10413", "Definition rejected") + MsgActionNotSupported = ffe("FF10414", "This action is not supported in this namespace", 400) + MsgMessagesNotSupported = ffe("FF10415", "Messages are not supported in this namespace", 400) ) diff --git a/internal/data/blobstore.go b/internal/data/blobstore.go index 0fd6387be..e4e5f6484 100644 --- a/internal/data/blobstore.go +++ b/internal/data/blobstore.go @@ -80,7 +80,7 @@ func (bs *blobStore) uploadVerifyBlob(ctx context.Context, id *fftypes.UUID, rea func (bs *blobStore) UploadBlob(ctx context.Context, inData *core.DataRefOrValue, mpart *ffapi.Multipart, autoMeta bool) (*core.Data, error) { if bs.exchange == nil { - return nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + return nil, i18n.NewError(ctx, coremsgs.MsgActionNotSupported) } data := &core.Data{ @@ -147,7 +147,7 @@ func (bs *blobStore) UploadBlob(ctx context.Context, inData *core.DataRefOrValue func (bs *blobStore) DownloadBlob(ctx context.Context, dataID string) (*core.Blob, io.ReadCloser, error) { if bs.exchange == nil { - return nil, nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + return nil, nil, i18n.NewError(ctx, coremsgs.MsgActionNotSupported) } id, err := fftypes.ParseUUID(ctx, dataID) diff --git a/internal/definitions/definition_handler_identity_claim.go b/internal/definitions/definition_handler_identity_claim.go index e2c8e59d5..90f8e81f0 100644 --- a/internal/definitions/definition_handler_identity_claim.go +++ b/internal/definitions/definition_handler_identity_claim.go @@ -129,10 +129,6 @@ func (dh *definitionHandlers) confirmVerificationForClaim(ctx context.Context, s func (dh *definitionHandlers) handleIdentityClaim(ctx context.Context, state *core.BatchState, msg *core.Message, identityClaim *core.IdentityClaim, verificationID *fftypes.UUID) (HandlerResult, error) { l := log.L(ctx) - if identityClaim.Identity.Type == core.IdentityTypeNode && dh.exchange == nil { - return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) - } - identity := identityClaim.Identity parent, retryable, err := dh.identity.VerifyIdentityChain(ctx, identity) if err != nil && retryable { diff --git a/internal/defsender/datatype.go b/internal/defsender/datatype.go index 635629299..a23087303 100644 --- a/internal/defsender/datatype.go +++ b/internal/defsender/datatype.go @@ -20,17 +20,11 @@ import ( "context" "github.com/hyperledger/firefly-common/pkg/fftypes" - "github.com/hyperledger/firefly-common/pkg/i18n" - "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/pkg/core" ) func (bm *definitionSender) CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (*core.Message, error) { - if !bm.multiparty { - return nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) - } - // Validate the input data definition data datatype.ID = fftypes.NewUUID() datatype.Created = fftypes.Now() diff --git a/internal/defsender/datatype_test.go b/internal/defsender/datatype_test.go index d66c04012..873dbe7db 100644 --- a/internal/defsender/datatype_test.go +++ b/internal/defsender/datatype_test.go @@ -31,13 +31,6 @@ import ( "github.com/stretchr/testify/mock" ) -func TestCreateDatatypeGatewayMode(t *testing.T) { - ds, cancel := newTestDefinitionSender(t) - defer cancel() - _, err := ds.CreateDatatype(context.Background(), &core.Datatype{}, false) - assert.Regexp(t, "FF10413", err) -} - func TestCreateDatatypeBadType(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() diff --git a/internal/networkmap/register_node.go b/internal/networkmap/register_node.go index 8ca18898d..c5a56ead4 100644 --- a/internal/networkmap/register_node.go +++ b/internal/networkmap/register_node.go @@ -21,18 +21,12 @@ import ( "fmt" "github.com/hyperledger/firefly-common/pkg/config" - "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/coreconfig" - "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/pkg/core" ) func (nm *networkMap) RegisterNode(ctx context.Context, waitConfirm bool) (identity *core.Identity, err error) { - if nm.exchange == nil { - return nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) - } - nodeOwningOrg, err := nm.identity.GetMultipartyRootOrg(ctx) if err != nil { return nil, err diff --git a/internal/orchestrator/message.go b/internal/orchestrator/message.go index 6bdde0f0e..993428425 100644 --- a/internal/orchestrator/message.go +++ b/internal/orchestrator/message.go @@ -27,7 +27,7 @@ import ( func (or *orchestrator) RequestReply(ctx context.Context, msg *core.MessageInOut) (reply *core.MessageInOut, err error) { pm := or.PrivateMessaging() if pm == nil { - return nil, i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + return nil, i18n.NewError(ctx, coremsgs.MsgMessagesNotSupported) } if msg.Header.Group == nil && (msg.Group == nil || len(msg.Group.Members) == 0) { return nil, i18n.NewError(ctx, coremsgs.MsgRequestMustBePrivate) diff --git a/internal/orchestrator/orchestrator.go b/internal/orchestrator/orchestrator.go index e35124550..e82b923e4 100644 --- a/internal/orchestrator/orchestrator.go +++ b/internal/orchestrator/orchestrator.go @@ -171,12 +171,14 @@ type orchestrator struct { namespace string config Config plugins Plugins + multiparty multiparty.Manager // only for multiparty + batch batch.Manager // only for multiparty + broadcast broadcast.Manager // only for multiparty + messaging privatemessaging.Manager // only for multiparty + sharedDownload shareddownload.Manager // only for multiparty identity identity.Manager events events.EventManager networkmap networkmap.Manager - batch batch.Manager - broadcast broadcast.Manager - messaging privatemessaging.Manager defhandler definitions.DefinitionHandler defsender defsender.Sender data data.Manager @@ -187,9 +189,7 @@ type orchestrator struct { node *fftypes.UUID metrics metrics.Manager operations operations.Manager - sharedDownload shareddownload.Manager txHelper txcommon.Helper - multiparty multiparty.Manager } func NewOrchestrator(ns string, config Config, plugins Plugins, metrics metrics.Manager) Orchestrator { @@ -528,7 +528,7 @@ func (or *orchestrator) initComponents(ctx context.Context) (err error) { func (or *orchestrator) SubmitNetworkAction(ctx context.Context, action *core.NetworkAction) error { if or.multiparty == nil { - return i18n.NewError(ctx, coremsgs.MsgActionOnlyValidMultiparty) + return i18n.NewError(ctx, coremsgs.MsgActionNotSupported) } key, err := or.identity.NormalizeSigningKey(ctx, "", identity.KeyNormalizationBlockchainPlugin) if err != nil { diff --git a/internal/orchestrator/orchestrator_test.go b/internal/orchestrator/orchestrator_test.go index 606dc655e..baeb70130 100644 --- a/internal/orchestrator/orchestrator_test.go +++ b/internal/orchestrator/orchestrator_test.go @@ -474,5 +474,5 @@ func TestNetworkActionNonMultiparty(t *testing.T) { or := newTestOrchestrator() or.multiparty = nil err := or.SubmitNetworkAction(context.Background(), &core.NetworkAction{Type: core.NetworkActionTerminate}) - assert.Regexp(t, "FF10413", err) + assert.Regexp(t, "FF10414", err) } From 37a58645f2aa6554474a76758558431dfeb6dd50 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Fri, 24 Jun 2022 14:50:36 -0400 Subject: [PATCH 09/27] Add some additional test coverage Signed-off-by: Andrew Richardson --- internal/assets/token_transfer_test.go | 67 ++++++++++++++++++++++ internal/data/blobstore_test.go | 23 ++++++++ internal/events/batch_pin_complete_test.go | 20 +++++++ internal/events/dx_callbacks_test.go | 17 ++++++ internal/events/reply_sender_test.go | 34 +++++++++++ internal/events/ss_callbacks_test.go | 18 ++++++ internal/orchestrator/message.go | 6 +- 7 files changed, 180 insertions(+), 5 deletions(-) diff --git a/internal/assets/token_transfer_test.go b/internal/assets/token_transfer_test.go index ac250eb4f..5f9ae6aa4 100644 --- a/internal/assets/token_transfer_test.go +++ b/internal/assets/token_transfer_test.go @@ -752,6 +752,39 @@ func TestTransferTokensWithBroadcastMessage(t *testing.T) { mom.AssertExpectations(t) } +func TestTransferTokensWithBroadcastMessageDisabled(t *testing.T) { + am, cancel := newTestAssets(t) + defer cancel() + am.broadcast = nil + + msgID := fftypes.NewUUID() + hash := fftypes.NewRandB32() + transfer := &core.TokenTransferInput{ + TokenTransfer: core.TokenTransfer{ + From: "A", + To: "B", + Amount: *fftypes.NewFFBigInt(5), + }, + Pool: "pool1", + Message: &core.MessageInOut{ + Message: core.Message{ + Header: core.MessageHeader{ + ID: msgID, + }, + Hash: hash, + }, + InlineData: core.InlineData{ + { + Value: fftypes.JSONAnyPtr("test data"), + }, + }, + }, + } + + _, err := am.TransferTokens(context.Background(), transfer, false) + assert.Regexp(t, "FF10415", err) +} + func TestTransferTokensWithBroadcastMessageSendFail(t *testing.T) { am, cancel := newTestAssets(t) defer cancel() @@ -907,6 +940,40 @@ func TestTransferTokensWithPrivateMessage(t *testing.T) { mom.AssertExpectations(t) } +func TestTransferTokensWithPrivateMessageDisabled(t *testing.T) { + am, cancel := newTestAssets(t) + defer cancel() + am.messaging = nil + + msgID := fftypes.NewUUID() + hash := fftypes.NewRandB32() + transfer := &core.TokenTransferInput{ + TokenTransfer: core.TokenTransfer{ + From: "A", + To: "B", + Amount: *fftypes.NewFFBigInt(5), + }, + Pool: "pool1", + Message: &core.MessageInOut{ + Message: core.Message{ + Header: core.MessageHeader{ + ID: msgID, + Type: core.MessageTypeTransferPrivate, + }, + Hash: hash, + }, + InlineData: core.InlineData{ + { + Value: fftypes.JSONAnyPtr("test data"), + }, + }, + }, + } + + _, err := am.TransferTokens(context.Background(), transfer, false) + assert.Regexp(t, "FF10415", err) +} + func TestTransferTokensWithInvalidMessage(t *testing.T) { am, cancel := newTestAssets(t) defer cancel() diff --git a/internal/data/blobstore_test.go b/internal/data/blobstore_test.go index c6246f27f..fff10348e 100644 --- a/internal/data/blobstore_test.go +++ b/internal/data/blobstore_test.go @@ -84,6 +84,18 @@ func TestUploadBlobOk(t *testing.T) { } +func TestUploadBlobDisabled(t *testing.T) { + + dm, ctx, cancel := newTestDataManager(t) + defer cancel() + dm.exchange = nil + + b := make([]byte, 10) + _, err := dm.UploadBlob(ctx, &core.DataRefOrValue{}, &ffapi.Multipart{Data: bytes.NewReader(b)}, false) + assert.Regexp(t, "FF10414", err) + +} + func TestUploadBlobAutoMetaOk(t *testing.T) { dm, ctx, cancel := newTestDataManager(t) @@ -283,6 +295,17 @@ func TestDownloadBlobOk(t *testing.T) { } +func TestDownloadBlobDisabled(t *testing.T) { + + dm, ctx, cancel := newTestDataManager(t) + defer cancel() + dm.exchange = nil + + _, _, err := dm.DownloadBlob(ctx, "") + assert.Regexp(t, "FF10414", err) + +} + func TestDownloadBlobNotFound(t *testing.T) { dm, ctx, cancel := newTestDataManager(t) diff --git a/internal/events/batch_pin_complete_test.go b/internal/events/batch_pin_complete_test.go index 7ded6ccb8..4d57d94fe 100644 --- a/internal/events/batch_pin_complete_test.go +++ b/internal/events/batch_pin_complete_test.go @@ -421,6 +421,26 @@ func TestBatchPinCompleteWrongNamespace(t *testing.T) { assert.NoError(t, err) } +func TestBatchPinCompleteNonMultiparty(t *testing.T) { + em, cancel := newTestEventManager(t) + defer cancel() + em.multiparty = nil + + batch := &blockchain.BatchPin{ + Namespace: "ns1", + TransactionID: fftypes.NewUUID(), + Event: blockchain.Event{ + BlockchainTXID: "0x12345", + }, + } + + err := em.BatchPinComplete(batch, &core.VerifierRef{ + Type: core.VerifierTypeEthAddress, + Value: "0x12345", + }) + assert.NoError(t, err) +} + func TestPersistBatchMissingID(t *testing.T) { em, cancel := newTestEventManager(t) defer cancel() diff --git a/internal/events/dx_callbacks_test.go b/internal/events/dx_callbacks_test.go index e797236c1..70f5366c3 100644 --- a/internal/events/dx_callbacks_test.go +++ b/internal/events/dx_callbacks_test.go @@ -254,6 +254,23 @@ func TestMessageReceivedWrongNS(t *testing.T) { } +func TestMessageReceivedNonMultiparty(t *testing.T) { + em, cancel := newTestEventManager(t) + defer cancel() + em.multiparty = nil + + _, b := sampleBatchTransfer(t, core.TransactionTypeBatchPin) + + mdx := &dataexchangemocks.Plugin{} + mdx.On("Name").Return("utdx") + + mde := newMessageReceived("peer1", b, "") + em.messageReceived(mdx, mde) + + mde.AssertExpectations(t) + +} + func TestMessageReceiveNodeLookupError(t *testing.T) { em, cancel := newTestEventManager(t) cancel() // to stop retry diff --git a/internal/events/reply_sender_test.go b/internal/events/reply_sender_test.go index e44dad0fe..46ee368ee 100644 --- a/internal/events/reply_sender_test.go +++ b/internal/events/reply_sender_test.go @@ -102,3 +102,37 @@ func TestSendReplyPrivateOk(t *testing.T) { mpm.AssertExpectations(t) mms.AssertExpectations(t) } + +func TestSendReplyBroadcastDisabled(t *testing.T) { + ed, cancel := newTestEventDispatcher(&subscription{ + definition: &core.Subscription{}, + }) + defer cancel() + ed.broadcast = nil + + ed.sendReply(context.Background(), &core.Event{ + ID: fftypes.NewUUID(), + Namespace: "ns1", + }, &core.MessageInOut{}) +} + +func TestSendReplyPrivateDisabled(t *testing.T) { + ed, cancel := newTestEventDispatcher(&subscription{ + definition: &core.Subscription{}, + }) + defer cancel() + ed.messaging = nil + + msg := &core.Message{ + Header: core.MessageHeader{ + Group: fftypes.NewRandB32(), + }, + } + + ed.sendReply(context.Background(), &core.Event{ + ID: fftypes.NewUUID(), + Namespace: "ns1", + }, &core.MessageInOut{ + Message: *msg, + }) +} diff --git a/internal/events/ss_callbacks_test.go b/internal/events/ss_callbacks_test.go index 4ada91bb9..a79963c40 100644 --- a/internal/events/ss_callbacks_test.go +++ b/internal/events/ss_callbacks_test.go @@ -106,6 +106,24 @@ func TestSharedStorageBatchDownloadedNSMismatch(t *testing.T) { } +func TestSharedStorageBatchDownloadedNonMultiparty(t *testing.T) { + + em, cancel := newTestEventManager(t) + defer cancel() + em.multiparty = nil + + data := &core.Data{ID: fftypes.NewUUID(), Value: fftypes.JSONAnyPtr(`"test"`)} + batch := sampleBatch(t, core.BatchTypeBroadcast, core.TransactionTypeBatchPin, core.DataArray{data}) + b, _ := json.Marshal(&batch) + + mss := &sharedstoragemocks.Plugin{} + _, err := em.SharedStorageBatchDownloaded(mss, "payload1", b) + assert.NoError(t, err) + + mss.AssertExpectations(t) + +} + func TestSharedStorageBatchDownloadedBadData(t *testing.T) { em, cancel := newTestEventManager(t) diff --git a/internal/orchestrator/message.go b/internal/orchestrator/message.go index 993428425..cf5369e74 100644 --- a/internal/orchestrator/message.go +++ b/internal/orchestrator/message.go @@ -25,12 +25,8 @@ import ( ) func (or *orchestrator) RequestReply(ctx context.Context, msg *core.MessageInOut) (reply *core.MessageInOut, err error) { - pm := or.PrivateMessaging() - if pm == nil { - return nil, i18n.NewError(ctx, coremsgs.MsgMessagesNotSupported) - } if msg.Header.Group == nil && (msg.Group == nil || len(msg.Group.Members) == 0) { return nil, i18n.NewError(ctx, coremsgs.MsgRequestMustBePrivate) } - return pm.RequestReply(ctx, msg) + return or.PrivateMessaging().RequestReply(ctx, msg) } From 09d4255c9f11cfa50f143314c3a90e33bac5f56b Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Fri, 24 Jun 2022 14:56:49 -0400 Subject: [PATCH 10/27] Disable identity resolution for local definitions Signed-off-by: Andrew Richardson --- internal/defsender/sender.go | 8 +++++--- internal/defsender/sender_test.go | 18 ++---------------- internal/identity/identitymanager.go | 4 ---- 3 files changed, 7 insertions(+), 23 deletions(-) diff --git a/internal/defsender/sender.go b/internal/defsender/sender.go index c4f37e1f1..a56019ab6 100644 --- a/internal/defsender/sender.go +++ b/internal/defsender/sender.go @@ -82,9 +82,11 @@ func (bm *definitionSender) CreateDefinition(ctx context.Context, def core.Defin func (bm *definitionSender) CreateDefinitionWithIdentity(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { - err = bm.identity.ResolveInputSigningIdentity(ctx, signingIdentity) - if err != nil { - return nil, err + if bm.multiparty { + err = bm.identity.ResolveInputSigningIdentity(ctx, signingIdentity) + if err != nil { + return nil, err + } } return bm.createDefinitionCommon(ctx, def, signingIdentity, tag, waitConfirm) diff --git a/internal/defsender/sender_test.go b/internal/defsender/sender_test.go index 9eeafc388..ef520b32c 100644 --- a/internal/defsender/sender_test.go +++ b/internal/defsender/sender_test.go @@ -152,6 +152,8 @@ func TestCreateDefinitionBadIdentity(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() + ds.multiparty = true + mim := ds.identity.(*identitymanagermocks.Manager) mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) _, err := ds.CreateDefinitionWithIdentity(ds.ctx, &core.Namespace{}, &core.SignerRef{ @@ -165,38 +167,22 @@ func TestCreateDefinitionLocal(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() - mim := ds.identity.(*identitymanagermocks.Manager) - mbm := ds.broadcast.(*broadcastmocks.Manager) - mms := &sysmessagingmocks.MessageSender{} mdh := &mockDefinitionHandler{} ds.Init(mdh) - mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) - _, err := ds.CreateDefinition(ds.ctx, &core.Datatype{}, core.SystemTagDefineDatatype, true) assert.NoError(t, err) - mim.AssertExpectations(t) - mbm.AssertExpectations(t) - mms.AssertExpectations(t) } func TestCreateDefinitionLocalError(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() - mim := ds.identity.(*identitymanagermocks.Manager) - mbm := ds.broadcast.(*broadcastmocks.Manager) - mms := &sysmessagingmocks.MessageSender{} mdh := &mockDefinitionHandler{err: fmt.Errorf("pop")} ds.Init(mdh) - mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) - _, err := ds.CreateDefinition(ds.ctx, &core.Datatype{}, core.SystemTagDefineDatatype, true) assert.EqualError(t, err, "pop") - mim.AssertExpectations(t) - mbm.AssertExpectations(t) - mms.AssertExpectations(t) } diff --git a/internal/identity/identitymanager.go b/internal/identity/identitymanager.go index 0911c4730..fc7ba0d45 100644 --- a/internal/identity/identitymanager.go +++ b/internal/identity/identitymanager.go @@ -215,10 +215,6 @@ func (im *identityManager) resolveDefaultSigningIdentity(ctx context.Context, si if err != nil { return err } - if im.multiparty == nil { - signerRef.Key = verifierRef.Value - return nil - } identity, err := im.GetMultipartyRootOrg(ctx) if err != nil { return err From 3ee09676864981de0781894a8d749f68602e99a9 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Fri, 24 Jun 2022 16:50:06 -0400 Subject: [PATCH 11/27] Allow plugin config to be omitted Signed-off-by: Andrew Richardson --- internal/namespace/manager.go | 81 +++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/internal/namespace/manager.go b/internal/namespace/manager.go index 8dce96c41..9bc79b4be 100644 --- a/internal/namespace/manager.go +++ b/internal/namespace/manager.go @@ -375,15 +375,17 @@ func (nm *namespaceManager) getDatabasePlugins(ctx context.Context) (plugins map // check for deprecated config if len(plugins) == 0 { pluginType := deprecatedDatabaseConfig.GetString(coreconfig.PluginConfigType) - plugin, err := difactory.GetPlugin(ctx, deprecatedDatabaseConfig.GetString(coreconfig.PluginConfigType)) - if err != nil { - return nil, err - } - log.L(ctx).Warnf("Your database config uses a deprecated configuration structure - the database configuration has been moved under the 'plugins' section") - name := "database_0" - plugins[name] = databasePlugin{ - config: deprecatedDatabaseConfig.SubSection(pluginType), - plugin: plugin, + if pluginType != "" { + plugin, err := difactory.GetPlugin(ctx, deprecatedDatabaseConfig.GetString(coreconfig.PluginConfigType)) + if err != nil { + return nil, err + } + log.L(ctx).Warnf("Your database config uses a deprecated configuration structure - the database configuration has been moved under the 'plugins' section") + name := "database_0" + plugins[name] = databasePlugin{ + config: deprecatedDatabaseConfig.SubSection(pluginType), + plugin: plugin, + } } } @@ -431,17 +433,20 @@ func (nm *namespaceManager) getDataExchangePlugins(ctx context.Context) (plugins } } + // check deprecated config if len(plugins) == 0 { pluginType := deprecatedDataexchangeConfig.GetString(coreconfig.PluginConfigType) - plugin, err := dxfactory.GetPlugin(ctx, pluginType) - if err != nil { - return nil, err - } - log.L(ctx).Warnf("Your data exchange config uses a deprecated configuration structure - the data exchange configuration has been moved under the 'plugins' section") - name := "dataexchange_0" - plugins[name] = dataExchangePlugin{ - config: deprecatedDataexchangeConfig.SubSection(pluginType), - plugin: plugin, + if pluginType != "" { + plugin, err := dxfactory.GetPlugin(ctx, pluginType) + if err != nil { + return nil, err + } + log.L(ctx).Warnf("Your data exchange config uses a deprecated configuration structure - the data exchange configuration has been moved under the 'plugins' section") + name := "dataexchange_0" + plugins[name] = dataExchangePlugin{ + config: deprecatedDataexchangeConfig.SubSection(pluginType), + plugin: plugin, + } } } @@ -496,15 +501,17 @@ func (nm *namespaceManager) getBlockchainPlugins(ctx context.Context) (plugins m // check deprecated config if len(plugins) == 0 { pluginType := deprecatedBlockchainConfig.GetString(coreconfig.PluginConfigType) - plugin, err := bifactory.GetPlugin(ctx, pluginType) - if err != nil { - return nil, err - } - log.L(ctx).Warnf("Your blockchain config uses a deprecated configuration structure - the blockchain configuration has been moved under the 'plugins' section") - name := "blockchain_0" - plugins[name] = blockchainPlugin{ - config: deprecatedBlockchainConfig.SubSection(pluginType), - plugin: plugin, + if pluginType != "" { + plugin, err := bifactory.GetPlugin(ctx, pluginType) + if err != nil { + return nil, err + } + log.L(ctx).Warnf("Your blockchain config uses a deprecated configuration structure - the blockchain configuration has been moved under the 'plugins' section") + name := "blockchain_0" + plugins[name] = blockchainPlugin{ + config: deprecatedBlockchainConfig.SubSection(pluginType), + plugin: plugin, + } } } @@ -535,15 +542,17 @@ func (nm *namespaceManager) getSharedStoragePlugins(ctx context.Context) (plugin // check deprecated config if len(plugins) == 0 { pluginType := deprecatedSharedStorageConfig.GetString(coreconfig.PluginConfigType) - plugin, err := ssfactory.GetPlugin(ctx, pluginType) - if err != nil { - return nil, err - } - log.L(ctx).Warnf("Your shared storage config uses a deprecated configuration structure - the shared storage configuration has been moved under the 'plugins' section") - name := "sharedstorage_0" - plugins[name] = sharedStoragePlugin{ - config: deprecatedSharedStorageConfig.SubSection(pluginType), - plugin: plugin, + if pluginType != "" { + plugin, err := ssfactory.GetPlugin(ctx, pluginType) + if err != nil { + return nil, err + } + log.L(ctx).Warnf("Your shared storage config uses a deprecated configuration structure - the shared storage configuration has been moved under the 'plugins' section") + name := "sharedstorage_0" + plugins[name] = sharedStoragePlugin{ + config: deprecatedSharedStorageConfig.SubSection(pluginType), + plugin: plugin, + } } } From 4fe64b6d8f0a29a48098400be1782f1a4cdd4b86 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Mon, 27 Jun 2022 16:22:17 -0400 Subject: [PATCH 12/27] Remove default value for "ffdx" Signed-off-by: Andrew Richardson --- docs/reference/config.md | 2 +- internal/dataexchange/dxfactory/factory.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/config.md b/docs/reference/config.md index 36e850442..693d296b0 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -336,7 +336,7 @@ nav_order: 2 |Key|Description|Type|Default Value| |---|-----------|----|-------------| -|type|The Data Exchange plugin to use|`string`|`ffdx` +|type|The Data Exchange plugin to use|`string`|`` ## dataexchange.ffdx diff --git a/internal/dataexchange/dxfactory/factory.go b/internal/dataexchange/dxfactory/factory.go index 13aaff658..8e995f4f7 100644 --- a/internal/dataexchange/dxfactory/factory.go +++ b/internal/dataexchange/dxfactory/factory.go @@ -44,7 +44,7 @@ func InitConfig(config config.ArraySection) { } func InitConfigDeprecated(config config.Section) { - config.AddKnownKey(coreconfig.PluginConfigType, NewFFDXPluginName) + config.AddKnownKey(coreconfig.PluginConfigType) for name, plugin := range pluginsByName { plugin().InitConfig(config.SubSection(name)) } From 82a04764a285d0b04761ee2a456f8d85a97d4875 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Mon, 27 Jun 2022 14:19:04 -0400 Subject: [PATCH 13/27] Move FFI/API creation methods into Definition Sender To align with other components, Definition Sender is the entry point for initiating the creation of contract FFIs/APIs, but it calls out to Contract Manager for validation. Signed-off-by: Andrew Richardson --- .../apiserver/route_post_new_contract_api.go | 2 +- .../route_post_new_contract_api_test.go | 14 +- .../route_post_new_contract_interface.go | 2 +- .../route_post_new_contract_interface_test.go | 14 +- internal/apiserver/route_put_contract_api.go | 2 +- .../apiserver/route_put_contract_api_test.go | 14 +- internal/contracts/manager.go | 112 +++----- internal/contracts/manager_test.go | 271 +++++------------- .../definition_handler_contracts.go | 2 +- .../definition_handler_contracts_test.go | 14 +- internal/defsender/contracts.go | 62 ++++ internal/defsender/contracts_test.go | 163 +++++++++++ internal/defsender/sender.go | 12 +- internal/defsender/sender_test.go | 8 +- internal/orchestrator/orchestrator.go | 16 +- mocks/contractmocks/manager.go | 88 ++---- mocks/defsendermocks/sender.go | 46 +++ 17 files changed, 468 insertions(+), 374 deletions(-) create mode 100644 internal/defsender/contracts.go create mode 100644 internal/defsender/contracts_test.go diff --git a/internal/apiserver/route_post_new_contract_api.go b/internal/apiserver/route_post_new_contract_api.go index a2d777fa4..317a76ea8 100644 --- a/internal/apiserver/route_post_new_contract_api.go +++ b/internal/apiserver/route_post_new_contract_api.go @@ -41,7 +41,7 @@ var postNewContractAPI = &ffapi.Route{ CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) - return cr.or.Contracts().BroadcastContractAPI(cr.ctx, cr.apiBaseURL, r.Input.(*core.ContractAPI), waitConfirm) + return cr.or.DefinitionSender().CreateContractAPI(cr.ctx, cr.apiBaseURL, r.Input.(*core.ContractAPI), waitConfirm) }, }, } diff --git a/internal/apiserver/route_post_new_contract_api_test.go b/internal/apiserver/route_post_new_contract_api_test.go index 127716835..d8d85005f 100644 --- a/internal/apiserver/route_post_new_contract_api_test.go +++ b/internal/apiserver/route_post_new_contract_api_test.go @@ -22,7 +22,7 @@ import ( "net/http/httptest" "testing" - "github.com/hyperledger/firefly/mocks/contractmocks" + "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -30,8 +30,8 @@ import ( func TestPostNewContractAPI(t *testing.T) { o, r := newTestAPIServer() - mcm := &contractmocks.Manager{} - o.On("Contracts").Return(mcm) + mds := &defsendermocks.Sender{} + o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) @@ -39,7 +39,7 @@ func TestPostNewContractAPI(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mcm.On("BroadcastContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), false). + mds.On("CreateContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), false). Return(&core.ContractAPI{}, nil) r.ServeHTTP(res, req) @@ -48,8 +48,8 @@ func TestPostNewContractAPI(t *testing.T) { func TestPostNewContractAPISync(t *testing.T) { o, r := newTestAPIServer() - mcm := &contractmocks.Manager{} - o.On("Contracts").Return(mcm) + mds := &defsendermocks.Sender{} + o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) @@ -57,7 +57,7 @@ func TestPostNewContractAPISync(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mcm.On("BroadcastContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), true). + mds.On("CreateContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), true). Return(&core.ContractAPI{}, nil) r.ServeHTTP(res, req) diff --git a/internal/apiserver/route_post_new_contract_interface.go b/internal/apiserver/route_post_new_contract_interface.go index fb761eef4..12e3944e9 100644 --- a/internal/apiserver/route_post_new_contract_interface.go +++ b/internal/apiserver/route_post_new_contract_interface.go @@ -41,7 +41,7 @@ var postNewContractInterface = &ffapi.Route{ CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) - return cr.or.Contracts().BroadcastFFI(cr.ctx, r.Input.(*core.FFI), waitConfirm) + return cr.or.DefinitionSender().CreateFFI(cr.ctx, r.Input.(*core.FFI), waitConfirm) }, }, } diff --git a/internal/apiserver/route_post_new_contract_interface_test.go b/internal/apiserver/route_post_new_contract_interface_test.go index 1b3dfa48b..0329bca47 100644 --- a/internal/apiserver/route_post_new_contract_interface_test.go +++ b/internal/apiserver/route_post_new_contract_interface_test.go @@ -22,7 +22,7 @@ import ( "net/http/httptest" "testing" - "github.com/hyperledger/firefly/mocks/contractmocks" + "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -30,8 +30,8 @@ import ( func TestPostNewContractInterface(t *testing.T) { o, r := newTestAPIServer() - mcm := &contractmocks.Manager{} - o.On("Contracts").Return(mcm) + mds := &defsendermocks.Sender{} + o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) @@ -39,7 +39,7 @@ func TestPostNewContractInterface(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mcm.On("BroadcastFFI", mock.Anything, mock.AnythingOfType("*core.FFI"), false). + mds.On("CreateFFI", mock.Anything, mock.AnythingOfType("*core.FFI"), false). Return(&core.FFI{}, nil) r.ServeHTTP(res, req) @@ -48,8 +48,8 @@ func TestPostNewContractInterface(t *testing.T) { func TestPostNewContractInterfaceSync(t *testing.T) { o, r := newTestAPIServer() - mcm := &contractmocks.Manager{} - o.On("Contracts").Return(mcm) + mds := &defsendermocks.Sender{} + o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) @@ -57,7 +57,7 @@ func TestPostNewContractInterfaceSync(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mcm.On("BroadcastFFI", mock.Anything, mock.AnythingOfType("*core.FFI"), true). + mds.On("CreateFFI", mock.Anything, mock.AnythingOfType("*core.FFI"), true). Return(&core.FFI{}, nil) r.ServeHTTP(res, req) diff --git a/internal/apiserver/route_put_contract_api.go b/internal/apiserver/route_put_contract_api.go index 90a0707ed..7c93d6da5 100644 --- a/internal/apiserver/route_put_contract_api.go +++ b/internal/apiserver/route_put_contract_api.go @@ -48,7 +48,7 @@ var putContractAPI = &ffapi.Route{ api.ID, err = fftypes.ParseUUID(cr.ctx, r.PP["id"]) var res interface{} if err == nil { - res, err = cr.or.Contracts().BroadcastContractAPI(cr.ctx, cr.apiBaseURL, api, waitConfirm) + res, err = cr.or.DefinitionSender().CreateContractAPI(cr.ctx, cr.apiBaseURL, api, waitConfirm) } return res, err }, diff --git a/internal/apiserver/route_put_contract_api_test.go b/internal/apiserver/route_put_contract_api_test.go index 9b5a495bb..b79d3b14f 100644 --- a/internal/apiserver/route_put_contract_api_test.go +++ b/internal/apiserver/route_put_contract_api_test.go @@ -22,7 +22,7 @@ import ( "net/http/httptest" "testing" - "github.com/hyperledger/firefly/mocks/contractmocks" + "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -30,8 +30,8 @@ import ( func TestPutContractAPI(t *testing.T) { o, r := newTestAPIServer() - mcm := &contractmocks.Manager{} - o.On("Contracts").Return(mcm) + mds := &defsendermocks.Sender{} + o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) @@ -39,7 +39,7 @@ func TestPutContractAPI(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mcm.On("BroadcastContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), false). + mds.On("CreateContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), false). Return(&core.ContractAPI{}, nil) r.ServeHTTP(res, req) @@ -48,8 +48,8 @@ func TestPutContractAPI(t *testing.T) { func TestPutContractAPISync(t *testing.T) { o, r := newTestAPIServer() - mcm := &contractmocks.Manager{} - o.On("Contracts").Return(mcm) + mds := &defsendermocks.Sender{} + o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) @@ -57,7 +57,7 @@ func TestPutContractAPISync(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mcm.On("BroadcastContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), true). + mds.On("CreateContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), true). Return(&core.ContractAPI{}, nil) r.ServeHTTP(res, req) diff --git a/internal/contracts/manager.go b/internal/contracts/manager.go index 2c7097d79..461a2d13d 100644 --- a/internal/contracts/manager.go +++ b/internal/contracts/manager.go @@ -24,7 +24,6 @@ import ( "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/coremsgs" - "github.com/hyperledger/firefly/internal/defsender" "github.com/hyperledger/firefly/internal/identity" "github.com/hyperledger/firefly/internal/operations" "github.com/hyperledger/firefly/internal/syncasync" @@ -38,21 +37,19 @@ import ( type Manager interface { core.Named - BroadcastFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) (output *core.FFI, err error) GetFFI(ctx context.Context, name, version string) (*core.FFI, error) GetFFIWithChildren(ctx context.Context, name, version string) (*core.FFI, error) GetFFIByID(ctx context.Context, id *fftypes.UUID) (*core.FFI, error) GetFFIByIDWithChildren(ctx context.Context, id *fftypes.UUID) (*core.FFI, error) GetFFIs(ctx context.Context, filter database.AndFilter) ([]*core.FFI, *database.FilterResult, error) + ResolveFFI(ctx context.Context, ffi *core.FFI) error InvokeContract(ctx context.Context, req *core.ContractCallRequest, waitConfirm bool) (interface{}, error) InvokeContractAPI(ctx context.Context, apiName, methodPath string, req *core.ContractCallRequest, waitConfirm bool) (interface{}, error) GetContractAPI(ctx context.Context, httpServerURL, apiName string) (*core.ContractAPI, error) GetContractAPIInterface(ctx context.Context, apiName string) (*core.FFI, error) GetContractAPIs(ctx context.Context, httpServerURL string, filter database.AndFilter) ([]*core.ContractAPI, *database.FilterResult, error) - BroadcastContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) (output *core.ContractAPI, err error) - - ValidateFFIAndSetPathnames(ctx context.Context, ffi *core.FFI) error + ResolveContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI) error AddContractListener(ctx context.Context, listener *core.ContractListenerInput) (output *core.ContractListener, err error) AddContractAPIListener(ctx context.Context, apiName, eventPath string, listener *core.ContractListener) (output *core.ContractListener, err error) @@ -71,7 +68,6 @@ type contractManager struct { namespace string database database.Plugin txHelper txcommon.Helper - defsender defsender.Sender identity identity.Manager blockchain blockchain.Plugin ffiParamValidator core.FFIParamValidator @@ -79,8 +75,8 @@ type contractManager struct { syncasync syncasync.Bridge } -func NewContractManager(ctx context.Context, ns string, di database.Plugin, bi blockchain.Plugin, ds defsender.Sender, im identity.Manager, om operations.Manager, txHelper txcommon.Helper, sa syncasync.Bridge) (Manager, error) { - if di == nil || ds == nil || im == nil || bi == nil || om == nil || txHelper == nil || sa == nil { +func NewContractManager(ctx context.Context, ns string, di database.Plugin, bi blockchain.Plugin, im identity.Manager, om operations.Manager, txHelper txcommon.Helper, sa syncasync.Bridge) (Manager, error) { + if di == nil || im == nil || bi == nil || om == nil || txHelper == nil || sa == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "ContractManager") } v, err := bi.GetFFIParamValidator(ctx) @@ -92,7 +88,6 @@ func NewContractManager(ctx context.Context, ns string, di database.Plugin, bi b namespace: ns, database: di, txHelper: txHelper, - defsender: ds, identity: im, blockchain: bi, ffiParamValidator: v, @@ -119,34 +114,6 @@ func (cm *contractManager) newFFISchemaCompiler() *jsonschema.Compiler { return c } -func (cm *contractManager) BroadcastFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) (output *core.FFI, err error) { - ffi.ID = fftypes.NewUUID() - ffi.Namespace = cm.namespace - - existing, err := cm.database.GetFFI(ctx, cm.namespace, ffi.Name, ffi.Version) - if existing != nil && err == nil { - return nil, i18n.NewError(ctx, coremsgs.MsgContractInterfaceExists, ffi.Namespace, ffi.Name, ffi.Version) - } - - for _, method := range ffi.Methods { - method.ID = fftypes.NewUUID() - } - for _, event := range ffi.Events { - event.ID = fftypes.NewUUID() - } - if err := cm.ValidateFFIAndSetPathnames(ctx, ffi); err != nil { - return nil, err - } - - output = ffi - msg, err := cm.defsender.CreateDefinition(ctx, ffi, core.SystemTagDefineFFI, waitConfirm) - if err != nil { - return nil, err - } - output.Message = msg.Header.ID - return ffi, nil -} - func (cm *contractManager) GetFFI(ctx context.Context, name, version string) (*core.FFI, error) { return cm.database.GetFFI(ctx, cm.namespace, name, version) } @@ -317,6 +284,34 @@ func (cm *contractManager) GetContractAPIs(ctx context.Context, httpServerURL st return apis, fr, err } +func (cm *contractManager) ResolveContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI) (err error) { + if api.Location != nil { + if api.Location, err = cm.blockchain.NormalizeContractLocation(ctx, api.Location); err != nil { + return err + } + } + + err = cm.database.RunAsGroup(ctx, func(ctx context.Context) (err error) { + existing, err := cm.database.GetContractAPIByName(ctx, api.Namespace, api.Name) + if existing != nil && err == nil { + if !api.LocationAndLedgerEquals(existing) { + return i18n.NewError(ctx, coremsgs.MsgContractLocationExists) + } + } + + if err := cm.resolveFFIReference(ctx, api.Interface); err != nil { + return err + } + return nil + }) + if err != nil { + return err + } + + cm.addContractURLs(httpServerURL, api) + return nil +} + func (cm *contractManager) resolveFFIReference(ctx context.Context, ref *core.FFIReference) error { switch { case ref == nil: @@ -346,42 +341,6 @@ func (cm *contractManager) resolveFFIReference(ctx context.Context, ref *core.FF } } -func (cm *contractManager) BroadcastContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) (output *core.ContractAPI, err error) { - api.ID = fftypes.NewUUID() - api.Namespace = cm.namespace - - if api.Location != nil { - if api.Location, err = cm.blockchain.NormalizeContractLocation(ctx, api.Location); err != nil { - return nil, err - } - } - - err = cm.database.RunAsGroup(ctx, func(ctx context.Context) (err error) { - existing, err := cm.database.GetContractAPIByName(ctx, api.Namespace, api.Name) - if existing != nil && err == nil { - if !api.LocationAndLedgerEquals(existing) { - return i18n.NewError(ctx, coremsgs.MsgContractLocationExists) - } - } - - if err := cm.resolveFFIReference(ctx, api.Interface); err != nil { - return err - } - return nil - }) - if err != nil { - return nil, err - } - - msg, err := cm.defsender.CreateDefinition(ctx, api, core.SystemTagDefineContractAPI, waitConfirm) - if err != nil { - return nil, err - } - api.Message = msg.Header.ID - cm.addContractURLs(httpServerURL, api) - return api, nil -} - func (cm *contractManager) uniquePathName(name string, usedNames map[string]bool) string { pathName := name for counter := 1; ; counter++ { @@ -394,11 +353,16 @@ func (cm *contractManager) uniquePathName(name string, usedNames map[string]bool } } -func (cm *contractManager) ValidateFFIAndSetPathnames(ctx context.Context, ffi *core.FFI) error { +func (cm *contractManager) ResolveFFI(ctx context.Context, ffi *core.FFI) error { if err := ffi.Validate(ctx, false); err != nil { return err } + existing, err := cm.database.GetFFI(ctx, cm.namespace, ffi.Name, ffi.Version) + if existing != nil && err == nil { + return i18n.NewError(ctx, coremsgs.MsgContractInterfaceExists, ffi.Namespace, ffi.Name, ffi.Version) + } + methodPathNames := map[string]bool{} for _, method := range ffi.Methods { method.Interface = ffi.ID diff --git a/internal/contracts/manager_test.go b/internal/contracts/manager_test.go index 5af03db1e..86037f931 100644 --- a/internal/contracts/manager_test.go +++ b/internal/contracts/manager_test.go @@ -29,7 +29,6 @@ import ( "github.com/hyperledger/firefly/mocks/blockchainmocks" "github.com/hyperledger/firefly/mocks/databasemocks" "github.com/hyperledger/firefly/mocks/datamocks" - "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/mocks/operationmocks" "github.com/hyperledger/firefly/mocks/syncasyncmocks" @@ -44,7 +43,6 @@ import ( func newTestContractManager() *contractManager { mdi := &databasemocks.Plugin{} mdm := &datamocks.Manager{} - mds := &defsendermocks.Sender{} mim := &identitymanagermocks.Manager{} mbi := &blockchainmocks.Plugin{} mom := &operationmocks.Manager{} @@ -61,13 +59,13 @@ func newTestContractManager() *contractManager { a[1].(func(context.Context) error)(a[0].(context.Context)), } } - cm, _ := NewContractManager(context.Background(), "ns1", mdi, mbi, mds, mim, mom, txHelper, msa) + cm, _ := NewContractManager(context.Background(), "ns1", mdi, mbi, mim, mom, txHelper, msa) cm.(*contractManager).txHelper = &txcommonmocks.Helper{} return cm.(*contractManager) } func TestNewContractManagerFail(t *testing.T) { - _, err := NewContractManager(context.Background(), "", nil, nil, nil, nil, nil, nil, nil) + _, err := NewContractManager(context.Background(), "", nil, nil, nil, nil, nil, nil) assert.Regexp(t, "FF10128", err) } @@ -79,21 +77,19 @@ func TestName(t *testing.T) { func TestNewContractManagerFFISchemaLoaderFail(t *testing.T) { mdi := &databasemocks.Plugin{} mdm := &datamocks.Manager{} - mds := &defsendermocks.Sender{} mim := &identitymanagermocks.Manager{} mbi := &blockchainmocks.Plugin{} mom := &operationmocks.Manager{} txHelper := txcommon.NewTransactionHelper("ns1", mdi, mdm) msa := &syncasyncmocks.Bridge{} mbi.On("GetFFIParamValidator", mock.Anything).Return(nil, fmt.Errorf("pop")) - _, err := NewContractManager(context.Background(), "ns1", mdi, mbi, mds, mim, mom, txHelper, msa) + _, err := NewContractManager(context.Background(), "ns1", mdi, mbi, mim, mom, txHelper, msa) assert.Regexp(t, "pop", err) } func TestNewContractManagerFFISchemaLoader(t *testing.T) { mdi := &databasemocks.Plugin{} mdm := &datamocks.Manager{} - mds := &defsendermocks.Sender{} mim := &identitymanagermocks.Manager{} mbi := &blockchainmocks.Plugin{} mom := &operationmocks.Manager{} @@ -101,29 +97,21 @@ func TestNewContractManagerFFISchemaLoader(t *testing.T) { msa := &syncasyncmocks.Bridge{} mbi.On("GetFFIParamValidator", mock.Anything).Return(ðereum.FFIParamValidator{}, nil) mom.On("RegisterHandler", mock.Anything, mock.Anything, mock.Anything) - _, err := NewContractManager(context.Background(), "ns1", mdi, mbi, mds, mim, mom, txHelper, msa) + _, err := NewContractManager(context.Background(), "ns1", mdi, mbi, mim, mom, txHelper, msa) assert.NoError(t, err) } -func TestBroadcastFFI(t *testing.T) { +func TestResolveFFI(t *testing.T) { cm := newTestContractManager() mdb := cm.database.(*databasemocks.Plugin) - mim := cm.identity.(*identitymanagermocks.Manager) - mds := cm.defsender.(*defsendermocks.Sender) mdb.On("GetFFI", mock.Anything, "ns1", "test", "1.0.0").Return(nil, nil) - mim.On("GetOrgKey", mock.Anything).Return("key", nil) - msg := &core.Message{ - Header: core.MessageHeader{ - ID: fftypes.NewUUID(), - }, - } - mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) ffi := &core.FFI{ - Name: "test", - Version: "1.0.0", - ID: fftypes.NewUUID(), + Namespace: "ns1", + Name: "test", + Version: "1.0.0", + ID: fftypes.NewUUID(), Methods: []*core.FFIMethod{ { Name: "sum", @@ -137,27 +125,22 @@ func TestBroadcastFFI(t *testing.T) { }, }, } - _, err := cm.BroadcastFFI(context.Background(), ffi, false) + + err := cm.ResolveFFI(context.Background(), ffi) assert.NoError(t, err) } func TestBroadcastFFIInvalid(t *testing.T) { cm := newTestContractManager() mdb := cm.database.(*databasemocks.Plugin) - mds := cm.defsender.(*defsendermocks.Sender) mdb.On("GetFFI", mock.Anything, "ns1", "test", "1.0.0").Return(nil, nil) - msg := &core.Message{ - Header: core.MessageHeader{ - ID: fftypes.NewUUID(), - }, - } - mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) ffi := &core.FFI{ - Name: "test", - Version: "1.0.0", - ID: fftypes.NewUUID(), + Namespace: "ns1", + Name: "test", + Version: "1.0.0", + ID: fftypes.NewUUID(), Methods: []*core.FFIMethod{ { Name: "sum", @@ -170,54 +153,40 @@ func TestBroadcastFFIInvalid(t *testing.T) { }, }, } - _, err := cm.BroadcastFFI(context.Background(), ffi, false) - assert.Regexp(t, "does not validate", err) -} - -func TestBroadcastFFIExists(t *testing.T) { - cm := newTestContractManager() - mdb := cm.database.(*databasemocks.Plugin) - mds := &defsendermocks.Sender{} - mdb.On("GetFFI", mock.Anything, "ns1", "test", "1.0.0").Return(&core.FFI{}, nil) + err := cm.ResolveFFI(context.Background(), ffi) + assert.Regexp(t, "does not validate", err) - msg := &core.Message{ - Header: core.MessageHeader{ - ID: fftypes.NewUUID(), - }, - } - mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(msg, nil) - ffi := &core.FFI{ - Name: "test", - Version: "1.0.0", - ID: fftypes.NewUUID(), - } - _, err := cm.BroadcastFFI(context.Background(), ffi, false) - assert.Regexp(t, "FF10302", err) + mdb.AssertExpectations(t) } -func TestBroadcastFFIFail(t *testing.T) { +func TestResolveFFIExists(t *testing.T) { cm := newTestContractManager() mdb := cm.database.(*databasemocks.Plugin) - mds := cm.defsender.(*defsendermocks.Sender) - mim := cm.identity.(*identitymanagermocks.Manager) - mdb.On("GetFFI", mock.Anything, "ns1", "test", "1.0.0").Return(nil, nil) - mim.On("GetOrgKey", mock.Anything).Return("key", nil) + mdb.On("GetFFI", mock.Anything, "ns1", "test", "1.0.0").Return(&core.FFI{}, nil) - mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.FFI"), core.SystemTagDefineFFI, false).Return(nil, fmt.Errorf("pop")) ffi := &core.FFI{ - Name: "test", - Version: "1.0.0", - ID: fftypes.NewUUID(), + Namespace: "ns1", + Name: "test", + Version: "1.0.0", + ID: fftypes.NewUUID(), Methods: []*core.FFIMethod{ { Name: "sum", }, }, + Events: []*core.FFIEvent{ + { + FFIEventDefinition: core.FFIEventDefinition{ + Name: "changed", + }, + }, + }, } - _, err := cm.BroadcastFFI(context.Background(), ffi, false) - assert.Regexp(t, "pop", err) + + err := cm.ResolveFFI(context.Background(), ffi) + assert.Regexp(t, "FF10302", err) } func TestValidateInvokeContractRequest(t *testing.T) { @@ -350,6 +319,8 @@ func TestValidateInvokeContractRequestInvalidParam(t *testing.T) { func TestValidateFFI(t *testing.T) { cm := newTestContractManager() + mdi := cm.database.(*databasemocks.Plugin) + ffi := &core.FFI{ Name: "math", Version: "1.0.0", @@ -403,7 +374,9 @@ func TestValidateFFI(t *testing.T) { }, } - err := cm.ValidateFFIAndSetPathnames(context.Background(), ffi) + mdi.On("GetFFI", context.Background(), "ns1", "math", "1.0.0").Return(nil, nil) + + err := cm.ResolveFFI(context.Background(), ffi) assert.NoError(t, err) assert.Equal(t, "sum", ffi.Methods[0].Pathname) @@ -414,6 +387,8 @@ func TestValidateFFI(t *testing.T) { func TestValidateFFIFail(t *testing.T) { cm := newTestContractManager() + mdi := cm.database.(*databasemocks.Plugin) + ffi := &core.FFI{ Namespace: "default", Methods: []*core.FFIMethod{ @@ -465,12 +440,16 @@ func TestValidateFFIFail(t *testing.T) { }, } - err := cm.ValidateFFIAndSetPathnames(context.Background(), ffi) + mdi.On("GetFFI", context.Background(), "ns1", "math", "1.0.0").Return(nil, nil) + + err := cm.ResolveFFI(context.Background(), ffi) assert.Regexp(t, "FF00140", err) } func TestValidateFFIBadMethod(t *testing.T) { cm := newTestContractManager() + mdi := cm.database.(*databasemocks.Plugin) + ffi := &core.FFI{ Name: "math", Version: "1.0.0", @@ -511,12 +490,16 @@ func TestValidateFFIBadMethod(t *testing.T) { }, } - err := cm.ValidateFFIAndSetPathnames(context.Background(), ffi) + mdi.On("GetFFI", context.Background(), "ns1", "math", "1.0.0").Return(nil, nil) + + err := cm.ResolveFFI(context.Background(), ffi) assert.Regexp(t, "FF10320", err) } func TestValidateFFIBadEventParam(t *testing.T) { cm := newTestContractManager() + mdi := cm.database.(*databasemocks.Plugin) + ffi := &core.FFI{ Name: "math", Version: "1.0.0", @@ -557,7 +540,9 @@ func TestValidateFFIBadEventParam(t *testing.T) { }, } - err := cm.ValidateFFIAndSetPathnames(context.Background(), ffi) + mdi.On("GetFFI", context.Background(), "ns1", "math", "1.0.0").Return(nil, nil) + + err := cm.ResolveFFI(context.Background(), ffi) assert.Regexp(t, "FF10319", err) } @@ -1922,17 +1907,11 @@ func TestGetContractAPIInterfaceFail(t *testing.T) { mdb.AssertExpectations(t) } -func TestBroadcastContractAPI(t *testing.T) { +func TestResolveContractAPI(t *testing.T) { cm := newTestContractManager() mbi := cm.blockchain.(*blockchainmocks.Plugin) mdb := cm.database.(*databasemocks.Plugin) - mds := cm.defsender.(*defsendermocks.Sender) - msg := &core.Message{ - Header: core.MessageHeader{ - ID: fftypes.NewUUID(), - }, - } api := &core.ContractAPI{ ID: fftypes.NewUUID(), Namespace: "ns1", @@ -1946,21 +1925,15 @@ func TestBroadcastContractAPI(t *testing.T) { mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) mdb.On("GetFFIByID", mock.Anything, "ns1", api.Interface.ID).Return(&core.FFI{}, nil) - mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) - - api, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) + err := cm.ResolveContractAPI(context.Background(), "http://localhost/api", api) assert.NoError(t, err) - assert.NotNil(t, api) - assert.NotEmpty(t, api.URLs.OpenAPI) - assert.NotEmpty(t, api.URLs.UI) mbi.AssertExpectations(t) mdb.AssertExpectations(t) - mds.AssertExpectations(t) } -func TestBroadcastContractAPIBadLocation(t *testing.T) { +func TestResolveContractAPIBadLocation(t *testing.T) { cm := newTestContractManager() mbi := cm.blockchain.(*blockchainmocks.Plugin) @@ -1974,61 +1947,15 @@ func TestBroadcastContractAPIBadLocation(t *testing.T) { }, } - mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(nil, fmt.Errorf("pop")) - - _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) + mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, fmt.Errorf("pop")) + err := cm.ResolveContractAPI(context.Background(), "http://localhost/api", api) assert.EqualError(t, err, "pop") mbi.AssertExpectations(t) } -func TestBroadcastContractAPIExisting(t *testing.T) { - cm := newTestContractManager() - mbi := cm.blockchain.(*blockchainmocks.Plugin) - mdb := cm.database.(*databasemocks.Plugin) - mds := cm.defsender.(*defsendermocks.Sender) - - msg := &core.Message{ - Header: core.MessageHeader{ - ID: fftypes.NewUUID(), - }, - } - apiID := fftypes.NewUUID() - existing := &core.ContractAPI{ - ID: apiID, - Namespace: "ns1", - Location: fftypes.JSONAnyPtr(""), - Name: "banana", - Interface: &core.FFIReference{ - ID: fftypes.NewUUID(), - }, - } - api := &core.ContractAPI{ - ID: apiID, - Namespace: "ns1", - Location: fftypes.JSONAnyPtr(""), - Name: "banana", - Interface: &core.FFIReference{ - ID: fftypes.NewUUID(), - }, - } - - mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) - mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(existing, nil) - mdb.On("GetFFIByID", mock.Anything, "ns1", api.Interface.ID).Return(&core.FFI{}, nil) - mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) - - _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) - - assert.NoError(t, err) - - mbi.AssertExpectations(t) - mdb.AssertExpectations(t) - mds.AssertExpectations(t) -} - -func TestBroadcastContractAPICannotChangeLocation(t *testing.T) { +func TestResolveContractAPICannotChangeLocation(t *testing.T) { cm := newTestContractManager() mbi := cm.blockchain.(*blockchainmocks.Plugin) mdb := cm.database.(*databasemocks.Plugin) @@ -2056,25 +1983,18 @@ func TestBroadcastContractAPICannotChangeLocation(t *testing.T) { mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(existing, nil) - _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) - + err := cm.ResolveContractAPI(context.Background(), "http://localhost/api", api) assert.Regexp(t, "FF10316", err) mbi.AssertExpectations(t) mdb.AssertExpectations(t) } -func TestBroadcastContractAPIInterfaceName(t *testing.T) { +func TestResolveContractAPIInterfaceName(t *testing.T) { cm := newTestContractManager() mbi := cm.blockchain.(*blockchainmocks.Plugin) mdb := cm.database.(*databasemocks.Plugin) - mds := cm.defsender.(*defsendermocks.Sender) - msg := &core.Message{ - Header: core.MessageHeader{ - ID: fftypes.NewUUID(), - }, - } api := &core.ContractAPI{ ID: fftypes.NewUUID(), Namespace: "ns1", @@ -2090,72 +2010,37 @@ func TestBroadcastContractAPIInterfaceName(t *testing.T) { mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) mdb.On("GetFFI", mock.Anything, "ns1", "my-ffi", "1").Return(&core.FFI{ID: interfaceID}, nil) - mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(msg, nil) - - _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) + err := cm.ResolveContractAPI(context.Background(), "http://localhost/api", api) assert.NoError(t, err) - assert.Equal(t, *interfaceID, *api.Interface.ID) mbi.AssertExpectations(t) mdb.AssertExpectations(t) - mds.AssertExpectations(t) } -func TestBroadcastContractAPIFail(t *testing.T) { +func TestResolveContractAPINoInterface(t *testing.T) { cm := newTestContractManager() mbi := cm.blockchain.(*blockchainmocks.Plugin) mdb := cm.database.(*databasemocks.Plugin) - mds := cm.defsender.(*defsendermocks.Sender) api := &core.ContractAPI{ ID: fftypes.NewUUID(), Namespace: "ns1", Location: fftypes.JSONAnyPtr(""), Name: "banana", - Interface: &core.FFIReference{ - ID: fftypes.NewUUID(), - }, } mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) - mdb.On("GetFFIByID", mock.Anything, "ns1", api.Interface.ID).Return(&core.FFI{}, nil) - mds.On("CreateDefinition", mock.Anything, mock.AnythingOfType("*core.ContractAPI"), core.SystemTagDefineContractAPI, false).Return(nil, fmt.Errorf("pop")) - - _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) - - assert.Regexp(t, "pop", err) - - mbi.AssertExpectations(t) - mdb.AssertExpectations(t) - mds.AssertExpectations(t) -} - -func TestBroadcastContractAPINoInterface(t *testing.T) { - cm := newTestContractManager() - mbi := cm.blockchain.(*blockchainmocks.Plugin) - mdb := cm.database.(*databasemocks.Plugin) - - api := &core.ContractAPI{ - ID: fftypes.NewUUID(), - Namespace: "ns1", - Location: fftypes.JSONAnyPtr(""), - Name: "banana", - } - - mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) - mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) - - _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) + err := cm.ResolveContractAPI(context.Background(), "http://localhost/api", api) assert.Regexp(t, "FF10303", err) mbi.AssertExpectations(t) mdb.AssertExpectations(t) } -func TestBroadcastContractAPIInterfaceIDFail(t *testing.T) { +func TestResolveContractAPIInterfaceIDFail(t *testing.T) { cm := newTestContractManager() mbi := cm.blockchain.(*blockchainmocks.Plugin) mdb := cm.database.(*databasemocks.Plugin) @@ -2174,15 +2059,14 @@ func TestBroadcastContractAPIInterfaceIDFail(t *testing.T) { mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) mdb.On("GetFFIByID", mock.Anything, "ns1", api.Interface.ID).Return(nil, fmt.Errorf("pop")) - _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) - + err := cm.ResolveContractAPI(context.Background(), "http://localhost/api", api) assert.EqualError(t, err, "pop") mbi.AssertExpectations(t) mdb.AssertExpectations(t) } -func TestBroadcastContractAPIInterfaceIDNotFound(t *testing.T) { +func TestResolveContractAPIInterfaceIDNotFound(t *testing.T) { cm := newTestContractManager() mbi := cm.blockchain.(*blockchainmocks.Plugin) mdb := cm.database.(*databasemocks.Plugin) @@ -2201,15 +2085,14 @@ func TestBroadcastContractAPIInterfaceIDNotFound(t *testing.T) { mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) mdb.On("GetFFIByID", mock.Anything, "ns1", api.Interface.ID).Return(nil, nil) - _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) - + err := cm.ResolveContractAPI(context.Background(), "http://localhost/api", api) assert.Regexp(t, "FF10303.*"+api.Interface.ID.String(), err) mbi.AssertExpectations(t) mdb.AssertExpectations(t) } -func TestBroadcastContractAPIInterfaceNameFail(t *testing.T) { +func TestResolveContractAPIInterfaceNameFail(t *testing.T) { cm := newTestContractManager() mbi := cm.blockchain.(*blockchainmocks.Plugin) mdb := cm.database.(*databasemocks.Plugin) @@ -2229,15 +2112,14 @@ func TestBroadcastContractAPIInterfaceNameFail(t *testing.T) { mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) mdb.On("GetFFI", mock.Anything, "ns1", "my-ffi", "1").Return(nil, fmt.Errorf("pop")) - _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) - + err := cm.ResolveContractAPI(context.Background(), "http://localhost/api", api) assert.EqualError(t, err, "pop") mbi.AssertExpectations(t) mdb.AssertExpectations(t) } -func TestBroadcastContractAPIInterfaceNameNotFound(t *testing.T) { +func TestResolveContractAPIInterfaceNameNotFound(t *testing.T) { cm := newTestContractManager() mbi := cm.blockchain.(*blockchainmocks.Plugin) mdb := cm.database.(*databasemocks.Plugin) @@ -2257,15 +2139,14 @@ func TestBroadcastContractAPIInterfaceNameNotFound(t *testing.T) { mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) mdb.On("GetFFI", mock.Anything, "ns1", "my-ffi", "1").Return(nil, nil) - _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) - + err := cm.ResolveContractAPI(context.Background(), "http://localhost/api", api) assert.Regexp(t, "FF10303.*my-ffi", err) mbi.AssertExpectations(t) mdb.AssertExpectations(t) } -func TestBroadcastContractAPIInterfaceNoVersion(t *testing.T) { +func TestResolveContractAPIInterfaceNoVersion(t *testing.T) { cm := newTestContractManager() mbi := cm.blockchain.(*blockchainmocks.Plugin) mdb := cm.database.(*databasemocks.Plugin) @@ -2283,8 +2164,7 @@ func TestBroadcastContractAPIInterfaceNoVersion(t *testing.T) { mbi.On("NormalizeContractLocation", context.Background(), api.Location).Return(api.Location, nil) mdb.On("GetContractAPIByName", mock.Anything, api.Namespace, api.Name).Return(nil, nil) - _, err := cm.BroadcastContractAPI(context.Background(), "http://localhost/api", api, false) - + err := cm.ResolveContractAPI(context.Background(), "http://localhost/api", api) assert.Regexp(t, "FF10303.*my-ffi", err) mbi.AssertExpectations(t) @@ -2324,7 +2204,6 @@ func TestCheckParamSchemaCompileFail(t *testing.T) { func TestAddJSONSchemaExtension(t *testing.T) { cm := &contractManager{ database: &databasemocks.Plugin{}, - defsender: &defsendermocks.Sender{}, identity: &identitymanagermocks.Manager{}, blockchain: &blockchainmocks.Plugin{}, ffiParamValidator: &MockFFIParamValidator{}, diff --git a/internal/definitions/definition_handler_contracts.go b/internal/definitions/definition_handler_contracts.go index fa9f5b5ce..e3bc9fd40 100644 --- a/internal/definitions/definition_handler_contracts.go +++ b/internal/definitions/definition_handler_contracts.go @@ -28,7 +28,7 @@ import ( ) func (dh *definitionHandlers) persistFFI(ctx context.Context, ffi *core.FFI) (err error) { - if err = dh.contracts.ValidateFFIAndSetPathnames(ctx, ffi); err != nil { + if err = dh.contracts.ResolveFFI(ctx, ffi); err != nil { log.L(ctx).Warnf("Unable to process FFI %s - validate failed: %s", ffi.ID, err) return nil } diff --git a/internal/definitions/definition_handler_contracts_test.go b/internal/definitions/definition_handler_contracts_test.go index 570261640..750a6bc97 100644 --- a/internal/definitions/definition_handler_contracts_test.go +++ b/internal/definitions/definition_handler_contracts_test.go @@ -102,7 +102,7 @@ func TestHandleFFIBroadcastOk(t *testing.T) { mbi.On("UpsertFFIEvent", mock.Anything, mock.Anything).Return(nil) mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) mcm := dh.contracts.(*contractmocks.Manager) - mcm.On("ValidateFFIAndSetPathnames", mock.Anything, mock.Anything).Return(nil) + mcm.On("ResolveFFI", mock.Anything, mock.Anything).Return(nil) action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ @@ -119,7 +119,7 @@ func TestHandleFFIBroadcastOk(t *testing.T) { func TestPersistFFIValidateFFIFail(t *testing.T) { dh, _ := newTestDefinitionHandler(t) mcm := dh.contracts.(*contractmocks.Manager) - mcm.On("ValidateFFIAndSetPathnames", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) + mcm.On("ResolveFFI", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) err := dh.persistFFI(context.Background(), testFFI()) assert.NoError(t, err) mcm.AssertExpectations(t) @@ -130,7 +130,7 @@ func TestHandleFFIBroadcastReject(t *testing.T) { mbi := dh.database.(*databasemocks.Plugin) mcm := dh.contracts.(*contractmocks.Manager) mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) - mcm.On("ValidateFFIAndSetPathnames", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) + mcm.On("ResolveFFI", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) action, err := dh.handleFFIBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineFFI, @@ -146,7 +146,7 @@ func TestPersistFFIUpsertFFIFail(t *testing.T) { mbi := dh.database.(*databasemocks.Plugin) mbi.On("UpsertFFI", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) mcm := dh.contracts.(*contractmocks.Manager) - mcm.On("ValidateFFIAndSetPathnames", mock.Anything, mock.Anything).Return(nil) + mcm.On("ResolveFFI", mock.Anything, mock.Anything).Return(nil) err := dh.persistFFI(context.Background(), testFFI()) assert.Regexp(t, "pop", err) mbi.AssertExpectations(t) @@ -159,7 +159,7 @@ func TestPersistFFIUpsertFFIMethodFail(t *testing.T) { mbi.On("UpsertFFI", mock.Anything, mock.Anything).Return(nil) mbi.On("UpsertFFIMethod", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) mcm := dh.contracts.(*contractmocks.Manager) - mcm.On("ValidateFFIAndSetPathnames", mock.Anything, mock.Anything).Return(nil) + mcm.On("ResolveFFI", mock.Anything, mock.Anything).Return(nil) err := dh.persistFFI(context.Background(), testFFI()) assert.Regexp(t, "pop", err) mbi.AssertExpectations(t) @@ -173,7 +173,7 @@ func TestPersistFFIUpsertFFIEventFail(t *testing.T) { mbi.On("UpsertFFIMethod", mock.Anything, mock.Anything).Return(nil) mbi.On("UpsertFFIEvent", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) mcm := dh.contracts.(*contractmocks.Manager) - mcm.On("ValidateFFIAndSetPathnames", mock.Anything, mock.Anything).Return(nil) + mcm.On("ResolveFFI", mock.Anything, mock.Anything).Return(nil) err := dh.persistFFI(context.Background(), testFFI()) assert.Regexp(t, "pop", err) mbi.AssertExpectations(t) @@ -213,7 +213,7 @@ func TestHandleFFIBroadcastPersistFail(t *testing.T) { mdi.On("UpsertFFI", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) mdi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) mcm := dh.contracts.(*contractmocks.Manager) - mcm.On("ValidateFFIAndSetPathnames", mock.Anything, mock.Anything).Return(nil) + mcm.On("ResolveFFI", mock.Anything, mock.Anything).Return(nil) action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineFFI, diff --git a/internal/defsender/contracts.go b/internal/defsender/contracts.go new file mode 100644 index 000000000..d4f70f11d --- /dev/null +++ b/internal/defsender/contracts.go @@ -0,0 +1,62 @@ +// 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 defsender + +import ( + "context" + + "github.com/hyperledger/firefly-common/pkg/fftypes" + "github.com/hyperledger/firefly/pkg/core" +) + +func (bm *definitionSender) CreateFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) (output *core.FFI, err error) { + ffi.ID = fftypes.NewUUID() + ffi.Namespace = bm.namespace + for _, method := range ffi.Methods { + method.ID = fftypes.NewUUID() + } + for _, event := range ffi.Events { + event.ID = fftypes.NewUUID() + } + + if err := bm.contracts.ResolveFFI(ctx, ffi); err != nil { + return nil, err + } + + msg, err := bm.CreateDefinition(ctx, ffi, core.SystemTagDefineFFI, waitConfirm) + if err != nil { + return nil, err + } + ffi.Message = msg.Header.ID + return ffi, nil +} + +func (bm *definitionSender) CreateContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) (output *core.ContractAPI, err error) { + api.ID = fftypes.NewUUID() + api.Namespace = bm.namespace + + if err := bm.contracts.ResolveContractAPI(ctx, httpServerURL, api); err != nil { + return nil, err + } + + msg, err := bm.CreateDefinition(ctx, api, core.SystemTagDefineContractAPI, waitConfirm) + if err != nil { + return nil, err + } + api.Message = msg.Header.ID + return api, nil +} diff --git a/internal/defsender/contracts_test.go b/internal/defsender/contracts_test.go new file mode 100644 index 000000000..d38d02544 --- /dev/null +++ b/internal/defsender/contracts_test.go @@ -0,0 +1,163 @@ +// 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 defsender + +import ( + "context" + "fmt" + "testing" + + "github.com/hyperledger/firefly/mocks/broadcastmocks" + "github.com/hyperledger/firefly/mocks/contractmocks" + "github.com/hyperledger/firefly/mocks/identitymanagermocks" + "github.com/hyperledger/firefly/mocks/sysmessagingmocks" + "github.com/hyperledger/firefly/pkg/core" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestCreateFFIResolveFail(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + ds.multiparty = true + + ffi := &core.FFI{ + Methods: []*core.FFIMethod{{}}, + Events: []*core.FFIEvent{{}}, + } + + mcm := ds.contracts.(*contractmocks.Manager) + mcm.On("ResolveFFI", context.Background(), ffi).Return(fmt.Errorf("pop")) + + _, err := ds.CreateFFI(context.Background(), ffi, false) + assert.EqualError(t, err, "pop") + + mcm.AssertExpectations(t) +} + +func TestCreateFFIFail(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + ds.multiparty = true + + ffi := &core.FFI{} + + mcm := ds.contracts.(*contractmocks.Manager) + mcm.On("ResolveFFI", context.Background(), ffi).Return(nil) + + mim := ds.identity.(*identitymanagermocks.Manager) + mim.On("ResolveInputSigningIdentity", context.Background(), mock.Anything).Return(fmt.Errorf("pop")) + + _, err := ds.CreateFFI(context.Background(), ffi, false) + assert.EqualError(t, err, "pop") + + mcm.AssertExpectations(t) + mim.AssertExpectations(t) +} + +func TestCreateFFIOk(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + ds.multiparty = true + + ffi := &core.FFI{} + + mcm := ds.contracts.(*contractmocks.Manager) + mcm.On("ResolveFFI", context.Background(), ffi).Return(nil) + + mim := ds.identity.(*identitymanagermocks.Manager) + mim.On("ResolveInputSigningIdentity", context.Background(), mock.Anything).Return(nil) + + mbm := ds.broadcast.(*broadcastmocks.Manager) + mms := &sysmessagingmocks.MessageSender{} + mbm.On("NewBroadcast", mock.Anything).Return(mms) + mms.On("Send", context.Background()).Return(nil) + + _, err := ds.CreateFFI(context.Background(), ffi, false) + assert.NoError(t, err) + + mcm.AssertExpectations(t) + mim.AssertExpectations(t) + mbm.AssertExpectations(t) + mms.AssertExpectations(t) +} + +func TestCreateContractAPIResolveFail(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + ds.multiparty = true + + url := "http://firefly" + api := &core.ContractAPI{} + + mcm := ds.contracts.(*contractmocks.Manager) + mcm.On("ResolveContractAPI", context.Background(), url, api).Return(fmt.Errorf("pop")) + + _, err := ds.CreateContractAPI(context.Background(), url, api, false) + assert.EqualError(t, err, "pop") + + mcm.AssertExpectations(t) +} + +func TestCreateContractAPIFail(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + ds.multiparty = true + + url := "http://firefly" + api := &core.ContractAPI{} + + mcm := ds.contracts.(*contractmocks.Manager) + mcm.On("ResolveContractAPI", context.Background(), url, api).Return(nil) + + mim := ds.identity.(*identitymanagermocks.Manager) + mim.On("ResolveInputSigningIdentity", context.Background(), mock.Anything).Return(fmt.Errorf("pop")) + + _, err := ds.CreateContractAPI(context.Background(), url, api, false) + assert.EqualError(t, err, "pop") + + mcm.AssertExpectations(t) + mim.AssertExpectations(t) +} + +func TestCreateContractAPIOk(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + ds.multiparty = true + + url := "http://firefly" + api := &core.ContractAPI{} + + mcm := ds.contracts.(*contractmocks.Manager) + mcm.On("ResolveContractAPI", context.Background(), url, api).Return(nil) + + mim := ds.identity.(*identitymanagermocks.Manager) + mim.On("ResolveInputSigningIdentity", context.Background(), mock.Anything).Return(nil) + + mbm := ds.broadcast.(*broadcastmocks.Manager) + mms := &sysmessagingmocks.MessageSender{} + mbm.On("NewBroadcast", mock.Anything).Return(mms) + mms.On("Send", context.Background()).Return(nil) + + _, err := ds.CreateContractAPI(context.Background(), url, api, false) + assert.NoError(t, err) + + mcm.AssertExpectations(t) + mim.AssertExpectations(t) + mbm.AssertExpectations(t) + mms.AssertExpectations(t) +} diff --git a/internal/defsender/sender.go b/internal/defsender/sender.go index a56019ab6..72d60a39e 100644 --- a/internal/defsender/sender.go +++ b/internal/defsender/sender.go @@ -23,10 +23,12 @@ import ( "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/contracts" "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/internal/data" "github.com/hyperledger/firefly/internal/identity" "github.com/hyperledger/firefly/pkg/core" + "github.com/hyperledger/firefly/pkg/database" ) type DefinitionHandler interface { @@ -42,29 +44,35 @@ type Sender interface { CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (msg *core.Message, err error) CreateIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) CreateTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (msg *core.Message, err error) + CreateFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) (output *core.FFI, err error) + CreateContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) (output *core.ContractAPI, err error) } type definitionSender struct { ctx context.Context namespace string multiparty bool + database database.Plugin broadcast broadcast.Manager // optional identity identity.Manager data data.Manager + contracts contracts.Manager handler DefinitionHandler } -func NewDefinitionSender(ctx context.Context, ns string, multiparty bool, bm broadcast.Manager, im identity.Manager, dm data.Manager) (Sender, error) { - if im == nil || dm == nil { +func NewDefinitionSender(ctx context.Context, ns string, multiparty bool, di database.Plugin, bm broadcast.Manager, im identity.Manager, dm data.Manager, cm contracts.Manager) (Sender, error) { + if di == nil || im == nil || dm == nil || cm == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError) } return &definitionSender{ ctx: ctx, namespace: ns, multiparty: multiparty, + database: di, broadcast: bm, identity: im, data: dm, + contracts: cm, }, nil } diff --git a/internal/defsender/sender_test.go b/internal/defsender/sender_test.go index ef520b32c..0d8d92171 100644 --- a/internal/defsender/sender_test.go +++ b/internal/defsender/sender_test.go @@ -23,6 +23,8 @@ import ( "github.com/hyperledger/firefly/internal/identity" "github.com/hyperledger/firefly/mocks/broadcastmocks" + "github.com/hyperledger/firefly/mocks/contractmocks" + "github.com/hyperledger/firefly/mocks/databasemocks" "github.com/hyperledger/firefly/mocks/datamocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/mocks/sysmessagingmocks" @@ -40,18 +42,20 @@ func (dh *mockDefinitionHandler) HandleDefinition(ctx context.Context, state *co } func newTestDefinitionSender(t *testing.T) (*definitionSender, func()) { + mdi := &databasemocks.Plugin{} mbm := &broadcastmocks.Manager{} mim := &identitymanagermocks.Manager{} mdm := &datamocks.Manager{} + mcm := &contractmocks.Manager{} ctx, cancel := context.WithCancel(context.Background()) - b, err := NewDefinitionSender(ctx, "ns1", false, mbm, mim, mdm) + b, err := NewDefinitionSender(ctx, "ns1", false, mdi, mbm, mim, mdm, mcm) assert.NoError(t, err) return b.(*definitionSender), cancel } func TestInitFail(t *testing.T) { - _, err := NewDefinitionSender(context.Background(), "", false, nil, nil, nil) + _, err := NewDefinitionSender(context.Background(), "", false, nil, nil, nil, nil, nil) assert.Regexp(t, "FF10128", err) } diff --git a/internal/orchestrator/orchestrator.go b/internal/orchestrator/orchestrator.go index e82b923e4..469f17625 100644 --- a/internal/orchestrator/orchestrator.go +++ b/internal/orchestrator/orchestrator.go @@ -455,29 +455,29 @@ func (or *orchestrator) initManagers(ctx context.Context) (err error) { } } - if or.defsender == nil { - or.defsender, err = defsender.NewDefinitionSender(ctx, or.namespace, or.config.Multiparty.Enabled, or.broadcast, or.identity, or.data) + if or.assets == nil { + or.assets, err = assets.NewAssetManager(ctx, or.namespace, or.database(), or.tokens(), or.identity, or.syncasync, or.broadcast, or.messaging, or.metrics, or.operations, or.txHelper) if err != nil { return err } } - if or.networkmap == nil { - or.networkmap, err = networkmap.NewNetworkMap(ctx, or.namespace, or.database(), or.dataexchange(), or.defsender, or.identity, or.syncasync, or.multiparty) + if or.contracts == nil { + or.contracts, err = contracts.NewContractManager(ctx, or.namespace, or.database(), or.blockchain(), or.identity, or.operations, or.txHelper, or.syncasync) if err != nil { return err } } - if or.assets == nil { - or.assets, err = assets.NewAssetManager(ctx, or.namespace, or.database(), or.tokens(), or.identity, or.syncasync, or.broadcast, or.messaging, or.metrics, or.operations, or.txHelper) + if or.defsender == nil { + or.defsender, err = defsender.NewDefinitionSender(ctx, or.namespace, or.config.Multiparty.Enabled, or.database(), or.broadcast, or.identity, or.data, or.contracts) if err != nil { return err } } - if or.contracts == nil { - or.contracts, err = contracts.NewContractManager(ctx, or.namespace, or.database(), or.blockchain(), or.defsender, or.identity, or.operations, or.txHelper, or.syncasync) + if or.networkmap == nil { + or.networkmap, err = networkmap.NewNetworkMap(ctx, or.namespace, or.database(), or.dataexchange(), or.defsender, or.identity, or.syncasync, or.multiparty) if err != nil { return err } diff --git a/mocks/contractmocks/manager.go b/mocks/contractmocks/manager.go index 5a65fedde..bdc6171ba 100644 --- a/mocks/contractmocks/manager.go +++ b/mocks/contractmocks/manager.go @@ -65,52 +65,6 @@ func (_m *Manager) AddContractListener(ctx context.Context, listener *core.Contr return r0, r1 } -// BroadcastContractAPI provides a mock function with given fields: ctx, httpServerURL, api, waitConfirm -func (_m *Manager) BroadcastContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) (*core.ContractAPI, error) { - ret := _m.Called(ctx, httpServerURL, api, waitConfirm) - - var r0 *core.ContractAPI - if rf, ok := ret.Get(0).(func(context.Context, string, *core.ContractAPI, bool) *core.ContractAPI); ok { - r0 = rf(ctx, httpServerURL, api, waitConfirm) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*core.ContractAPI) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, string, *core.ContractAPI, bool) error); ok { - r1 = rf(ctx, httpServerURL, api, waitConfirm) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// BroadcastFFI provides a mock function with given fields: ctx, ffi, waitConfirm -func (_m *Manager) BroadcastFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) (*core.FFI, error) { - ret := _m.Called(ctx, ffi, waitConfirm) - - var r0 *core.FFI - if rf, ok := ret.Get(0).(func(context.Context, *core.FFI, bool) *core.FFI); ok { - r0 = rf(ctx, ffi, waitConfirm) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*core.FFI) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *core.FFI, bool) error); ok { - r1 = rf(ctx, ffi, waitConfirm) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // DeleteContractListenerByNameOrID provides a mock function with given fields: ctx, nameOrID func (_m *Manager) DeleteContractListenerByNameOrID(ctx context.Context, nameOrID string) error { ret := _m.Called(ctx, nameOrID) @@ -520,6 +474,34 @@ func (_m *Manager) PrepareOperation(ctx context.Context, op *core.Operation) (*c return r0, r1 } +// ResolveContractAPI provides a mock function with given fields: ctx, httpServerURL, api +func (_m *Manager) ResolveContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI) error { + ret := _m.Called(ctx, httpServerURL, api) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, *core.ContractAPI) error); ok { + r0 = rf(ctx, httpServerURL, api) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ResolveFFI provides a mock function with given fields: ctx, ffi +func (_m *Manager) ResolveFFI(ctx context.Context, ffi *core.FFI) error { + ret := _m.Called(ctx, ffi) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *core.FFI) error); ok { + r0 = rf(ctx, ffi) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // RunOperation provides a mock function with given fields: ctx, op func (_m *Manager) RunOperation(ctx context.Context, op *core.PreparedOperation) (fftypes.JSONObject, bool, error) { ret := _m.Called(ctx, op) @@ -549,17 +531,3 @@ func (_m *Manager) RunOperation(ctx context.Context, op *core.PreparedOperation) return r0, r1, r2 } - -// ValidateFFIAndSetPathnames provides a mock function with given fields: ctx, ffi -func (_m *Manager) ValidateFFIAndSetPathnames(ctx context.Context, ffi *core.FFI) error { - ret := _m.Called(ctx, ffi) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *core.FFI) error); ok { - r0 = rf(ctx, ffi) - } else { - r0 = ret.Error(0) - } - - return r0 -} diff --git a/mocks/defsendermocks/sender.go b/mocks/defsendermocks/sender.go index a006507b8..a2a607c6e 100644 --- a/mocks/defsendermocks/sender.go +++ b/mocks/defsendermocks/sender.go @@ -16,6 +16,29 @@ type Sender struct { mock.Mock } +// CreateContractAPI provides a mock function with given fields: ctx, httpServerURL, api, waitConfirm +func (_m *Sender) CreateContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) (*core.ContractAPI, error) { + ret := _m.Called(ctx, httpServerURL, api, waitConfirm) + + var r0 *core.ContractAPI + if rf, ok := ret.Get(0).(func(context.Context, string, *core.ContractAPI, bool) *core.ContractAPI); ok { + r0 = rf(ctx, httpServerURL, api, waitConfirm) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*core.ContractAPI) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, string, *core.ContractAPI, bool) error); ok { + r1 = rf(ctx, httpServerURL, api, waitConfirm) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // CreateDatatype provides a mock function with given fields: ctx, datatype, waitConfirm func (_m *Sender) CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (*core.Message, error) { ret := _m.Called(ctx, datatype, waitConfirm) @@ -85,6 +108,29 @@ func (_m *Sender) CreateDefinitionWithIdentity(ctx context.Context, def core.Def return r0, r1 } +// CreateFFI provides a mock function with given fields: ctx, ffi, waitConfirm +func (_m *Sender) CreateFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) (*core.FFI, error) { + ret := _m.Called(ctx, ffi, waitConfirm) + + var r0 *core.FFI + if rf, ok := ret.Get(0).(func(context.Context, *core.FFI, bool) *core.FFI); ok { + r0 = rf(ctx, ffi, waitConfirm) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*core.FFI) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *core.FFI, bool) error); ok { + r1 = rf(ctx, ffi, waitConfirm) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // CreateIdentityClaim provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm func (_m *Sender) CreateIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { ret := _m.Called(ctx, def, signingIdentity, tag, waitConfirm) From dced5c55e968e5e5969933a846c60a69183b89b3 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Mon, 27 Jun 2022 22:55:28 -0400 Subject: [PATCH 14/27] Combine defsender into definitions package Signed-off-by: Andrew Richardson --- Makefile | 2 +- .../route_post_new_contract_api_test.go | 6 ++-- .../route_post_new_contract_interface_test.go | 6 ++-- .../apiserver/route_post_new_datatype_test.go | 6 ++-- .../apiserver/route_put_contract_api_test.go | 6 ++-- internal/{defsender => definitions}/sender.go | 6 +--- .../sender_contracts.go} | 2 +- .../sender_contracts_test.go} | 2 +- .../sender_datatype.go} | 2 +- .../sender_datatype_test.go} | 2 +- .../{defsender => definitions}/sender_test.go | 36 ++----------------- .../sender_tokenpool.go} | 2 +- .../sender_tokenpool_test.go} | 2 +- internal/events/event_manager.go | 5 ++- internal/events/event_manager_test.go | 5 ++- internal/events/token_pool_created_test.go | 4 +-- internal/networkmap/manager.go | 6 ++-- internal/networkmap/manager_test.go | 4 +-- internal/networkmap/register_identity_test.go | 10 +++--- internal/networkmap/register_node_test.go | 4 +-- internal/networkmap/register_org_test.go | 4 +-- internal/networkmap/update_identity_test.go | 6 ++-- internal/orchestrator/orchestrator.go | 9 +++-- internal/orchestrator/orchestrator_test.go | 5 ++- .../sender.go | 6 ++-- mocks/orchestratormocks/orchestrator.go | 10 +++--- 26 files changed, 59 insertions(+), 99 deletions(-) rename internal/{defsender => definitions}/sender.go (97%) rename internal/{defsender/contracts.go => definitions/sender_contracts.go} (98%) rename internal/{defsender/contracts_test.go => definitions/sender_contracts_test.go} (99%) rename internal/{defsender/datatype.go => definitions/sender_datatype.go} (98%) rename internal/{defsender/datatype_test.go => definitions/sender_datatype_test.go} (99%) rename internal/{defsender => definitions}/sender_test.go (85%) rename internal/{defsender/tokenpool.go => definitions/sender_tokenpool.go} (98%) rename internal/{defsender/tokenpool_test.go => definitions/sender_tokenpool_test.go} (99%) rename mocks/{defsendermocks => definitionsmocks}/sender.go (97%) diff --git a/Makefile b/Makefile index ba33e7093..d18ca2929 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,7 @@ $(eval $(call makemock, internal/privatemessaging, Manager, privateme $(eval $(call makemock, internal/shareddownload, Manager, shareddownloadmocks)) $(eval $(call makemock, internal/shareddownload, Callbacks, shareddownloadmocks)) $(eval $(call makemock, internal/definitions, DefinitionHandler, definitionsmocks)) -$(eval $(call makemock, internal/defsender, Sender, defsendermocks)) +$(eval $(call makemock, internal/definitions, Sender, definitionsmocks)) $(eval $(call makemock, internal/events, EventManager, eventmocks)) $(eval $(call makemock, internal/namespace, Manager, namespacemocks)) $(eval $(call makemock, internal/networkmap, Manager, networkmapmocks)) diff --git a/internal/apiserver/route_post_new_contract_api_test.go b/internal/apiserver/route_post_new_contract_api_test.go index d8d85005f..b7fecad6d 100644 --- a/internal/apiserver/route_post_new_contract_api_test.go +++ b/internal/apiserver/route_post_new_contract_api_test.go @@ -22,7 +22,7 @@ import ( "net/http/httptest" "testing" - "github.com/hyperledger/firefly/mocks/defsendermocks" + "github.com/hyperledger/firefly/mocks/definitionsmocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -30,7 +30,7 @@ import ( func TestPostNewContractAPI(t *testing.T) { o, r := newTestAPIServer() - mds := &defsendermocks.Sender{} + mds := &definitionsmocks.Sender{} o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer @@ -48,7 +48,7 @@ func TestPostNewContractAPI(t *testing.T) { func TestPostNewContractAPISync(t *testing.T) { o, r := newTestAPIServer() - mds := &defsendermocks.Sender{} + mds := &definitionsmocks.Sender{} o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer diff --git a/internal/apiserver/route_post_new_contract_interface_test.go b/internal/apiserver/route_post_new_contract_interface_test.go index 0329bca47..9366064f7 100644 --- a/internal/apiserver/route_post_new_contract_interface_test.go +++ b/internal/apiserver/route_post_new_contract_interface_test.go @@ -22,7 +22,7 @@ import ( "net/http/httptest" "testing" - "github.com/hyperledger/firefly/mocks/defsendermocks" + "github.com/hyperledger/firefly/mocks/definitionsmocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -30,7 +30,7 @@ import ( func TestPostNewContractInterface(t *testing.T) { o, r := newTestAPIServer() - mds := &defsendermocks.Sender{} + mds := &definitionsmocks.Sender{} o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer @@ -48,7 +48,7 @@ func TestPostNewContractInterface(t *testing.T) { func TestPostNewContractInterfaceSync(t *testing.T) { o, r := newTestAPIServer() - mds := &defsendermocks.Sender{} + mds := &definitionsmocks.Sender{} o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer diff --git a/internal/apiserver/route_post_new_datatype_test.go b/internal/apiserver/route_post_new_datatype_test.go index e034c43b0..7df163f3c 100644 --- a/internal/apiserver/route_post_new_datatype_test.go +++ b/internal/apiserver/route_post_new_datatype_test.go @@ -22,7 +22,7 @@ import ( "net/http/httptest" "testing" - "github.com/hyperledger/firefly/mocks/defsendermocks" + "github.com/hyperledger/firefly/mocks/definitionsmocks" "github.com/hyperledger/firefly/mocks/multipartymocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" @@ -31,7 +31,7 @@ import ( func TestPostNewDatatypes(t *testing.T) { o, r := newTestAPIServer() - mds := &defsendermocks.Sender{} + mds := &definitionsmocks.Sender{} o.On("DefinitionSender").Return(mds) o.On("MultiParty").Return(&multipartymocks.Manager{}) input := core.Datatype{} @@ -50,7 +50,7 @@ func TestPostNewDatatypes(t *testing.T) { func TestPostNewDatatypesSync(t *testing.T) { o, r := newTestAPIServer() - mds := &defsendermocks.Sender{} + mds := &definitionsmocks.Sender{} o.On("DefinitionSender").Return(mds) o.On("MultiParty").Return(&multipartymocks.Manager{}) input := core.Datatype{} diff --git a/internal/apiserver/route_put_contract_api_test.go b/internal/apiserver/route_put_contract_api_test.go index b79d3b14f..3df50b305 100644 --- a/internal/apiserver/route_put_contract_api_test.go +++ b/internal/apiserver/route_put_contract_api_test.go @@ -22,7 +22,7 @@ import ( "net/http/httptest" "testing" - "github.com/hyperledger/firefly/mocks/defsendermocks" + "github.com/hyperledger/firefly/mocks/definitionsmocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -30,7 +30,7 @@ import ( func TestPutContractAPI(t *testing.T) { o, r := newTestAPIServer() - mds := &defsendermocks.Sender{} + mds := &definitionsmocks.Sender{} o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer @@ -48,7 +48,7 @@ func TestPutContractAPI(t *testing.T) { func TestPutContractAPISync(t *testing.T) { o, r := newTestAPIServer() - mds := &defsendermocks.Sender{} + mds := &definitionsmocks.Sender{} o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer diff --git a/internal/defsender/sender.go b/internal/definitions/sender.go similarity index 97% rename from internal/defsender/sender.go rename to internal/definitions/sender.go index 72d60a39e..552e3097e 100644 --- a/internal/defsender/sender.go +++ b/internal/definitions/sender.go @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package defsender +package definitions import ( "context" @@ -31,10 +31,6 @@ import ( "github.com/hyperledger/firefly/pkg/database" ) -type DefinitionHandler interface { - HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error -} - type Sender interface { core.Named diff --git a/internal/defsender/contracts.go b/internal/definitions/sender_contracts.go similarity index 98% rename from internal/defsender/contracts.go rename to internal/definitions/sender_contracts.go index d4f70f11d..c60132a8e 100644 --- a/internal/defsender/contracts.go +++ b/internal/definitions/sender_contracts.go @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package defsender +package definitions import ( "context" diff --git a/internal/defsender/contracts_test.go b/internal/definitions/sender_contracts_test.go similarity index 99% rename from internal/defsender/contracts_test.go rename to internal/definitions/sender_contracts_test.go index d38d02544..db35e7e8d 100644 --- a/internal/defsender/contracts_test.go +++ b/internal/definitions/sender_contracts_test.go @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package defsender +package definitions import ( "context" diff --git a/internal/defsender/datatype.go b/internal/definitions/sender_datatype.go similarity index 98% rename from internal/defsender/datatype.go rename to internal/definitions/sender_datatype.go index a23087303..79182c69a 100644 --- a/internal/defsender/datatype.go +++ b/internal/definitions/sender_datatype.go @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package defsender +package definitions import ( "context" diff --git a/internal/defsender/datatype_test.go b/internal/definitions/sender_datatype_test.go similarity index 99% rename from internal/defsender/datatype_test.go rename to internal/definitions/sender_datatype_test.go index 873dbe7db..214aa51d5 100644 --- a/internal/defsender/datatype_test.go +++ b/internal/definitions/sender_datatype_test.go @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package defsender +package definitions import ( "context" diff --git a/internal/defsender/sender_test.go b/internal/definitions/sender_test.go similarity index 85% rename from internal/defsender/sender_test.go rename to internal/definitions/sender_test.go index 0d8d92171..4142689ad 100644 --- a/internal/defsender/sender_test.go +++ b/internal/definitions/sender_test.go @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package defsender +package definitions import ( "context" @@ -33,14 +33,6 @@ import ( "github.com/stretchr/testify/mock" ) -type mockDefinitionHandler struct { - err error -} - -func (dh *mockDefinitionHandler) HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error { - return dh.err -} - func newTestDefinitionSender(t *testing.T) (*definitionSender, func()) { mdi := &databasemocks.Plugin{} mbm := &broadcastmocks.Manager{} @@ -54,7 +46,7 @@ func newTestDefinitionSender(t *testing.T) (*definitionSender, func()) { return b.(*definitionSender), cancel } -func TestInitFail(t *testing.T) { +func TestInitSenderFail(t *testing.T) { _, err := NewDefinitionSender(context.Background(), "", false, nil, nil, nil, nil, nil) assert.Regexp(t, "FF10128", err) } @@ -166,27 +158,3 @@ func TestCreateDefinitionBadIdentity(t *testing.T) { }, core.SystemTagDefineNamespace, false) assert.Regexp(t, "pop", err) } - -func TestCreateDefinitionLocal(t *testing.T) { - ds, cancel := newTestDefinitionSender(t) - defer cancel() - - mdh := &mockDefinitionHandler{} - ds.Init(mdh) - - _, err := ds.CreateDefinition(ds.ctx, &core.Datatype{}, core.SystemTagDefineDatatype, true) - assert.NoError(t, err) - -} - -func TestCreateDefinitionLocalError(t *testing.T) { - ds, cancel := newTestDefinitionSender(t) - defer cancel() - - mdh := &mockDefinitionHandler{err: fmt.Errorf("pop")} - ds.Init(mdh) - - _, err := ds.CreateDefinition(ds.ctx, &core.Datatype{}, core.SystemTagDefineDatatype, true) - assert.EqualError(t, err, "pop") - -} diff --git a/internal/defsender/tokenpool.go b/internal/definitions/sender_tokenpool.go similarity index 98% rename from internal/defsender/tokenpool.go rename to internal/definitions/sender_tokenpool.go index 625c1d90e..b75e5f577 100644 --- a/internal/defsender/tokenpool.go +++ b/internal/definitions/sender_tokenpool.go @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package defsender +package definitions import ( "context" diff --git a/internal/defsender/tokenpool_test.go b/internal/definitions/sender_tokenpool_test.go similarity index 99% rename from internal/defsender/tokenpool_test.go rename to internal/definitions/sender_tokenpool_test.go index f97b88a01..e091fbbf9 100644 --- a/internal/defsender/tokenpool_test.go +++ b/internal/definitions/sender_tokenpool_test.go @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package defsender +package definitions import ( "context" diff --git a/internal/events/event_manager.go b/internal/events/event_manager.go index f3e586c87..46f8c473b 100644 --- a/internal/events/event_manager.go +++ b/internal/events/event_manager.go @@ -34,7 +34,6 @@ import ( "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/internal/data" "github.com/hyperledger/firefly/internal/definitions" - "github.com/hyperledger/firefly/internal/defsender" "github.com/hyperledger/firefly/internal/events/eifactory" "github.com/hyperledger/firefly/internal/events/system" "github.com/hyperledger/firefly/internal/identity" @@ -95,7 +94,7 @@ type eventManager struct { database database.Plugin txHelper txcommon.Helper identity identity.Manager - defsender defsender.Sender + defsender definitions.Sender defhandler definitions.DefinitionHandler data data.Manager subManager *subscriptionManager @@ -116,7 +115,7 @@ type eventManager struct { multiparty multiparty.Manager // optional } -func NewEventManager(ctx context.Context, ns string, ni sysmessaging.LocalNodeInfo, di database.Plugin, bi blockchain.Plugin, im identity.Manager, dh definitions.DefinitionHandler, dm data.Manager, ds defsender.Sender, bm broadcast.Manager, pm privatemessaging.Manager, am assets.Manager, sd shareddownload.Manager, mm metrics.Manager, txHelper txcommon.Helper, transports map[string]events.Plugin, mp multiparty.Manager) (EventManager, error) { +func NewEventManager(ctx context.Context, ns string, ni sysmessaging.LocalNodeInfo, di database.Plugin, bi blockchain.Plugin, im identity.Manager, dh definitions.DefinitionHandler, dm data.Manager, ds definitions.Sender, bm broadcast.Manager, pm privatemessaging.Manager, am assets.Manager, sd shareddownload.Manager, mm metrics.Manager, txHelper txcommon.Helper, transports map[string]events.Plugin, mp multiparty.Manager) (EventManager, error) { if ni == nil || di == nil || bi == nil || im == nil || dh == nil || dm == nil || ds == nil || am == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "EventManager") } diff --git a/internal/events/event_manager_test.go b/internal/events/event_manager_test.go index 43d180fad..b04f859bb 100644 --- a/internal/events/event_manager_test.go +++ b/internal/events/event_manager_test.go @@ -32,7 +32,6 @@ import ( "github.com/hyperledger/firefly/mocks/databasemocks" "github.com/hyperledger/firefly/mocks/datamocks" "github.com/hyperledger/firefly/mocks/definitionsmocks" - "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/mocks/eventsmocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/mocks/metricsmocks" @@ -75,7 +74,7 @@ func newTestEventManagerCommon(t *testing.T, metrics, dbconcurrency bool) (*even met := &eventsmocks.Plugin{} mdm := &datamocks.Manager{} msh := &definitionsmocks.DefinitionHandler{} - mds := &defsendermocks.Sender{} + mds := &definitionsmocks.Sender{} mbm := &broadcastmocks.Manager{} mpm := &privatemessagingmocks.Manager{} mam := &assetmocks.Manager{} @@ -144,7 +143,7 @@ func TestStartStopEventListenerFail(t *testing.T) { mim := &identitymanagermocks.Manager{} mdm := &datamocks.Manager{} msh := &definitionsmocks.DefinitionHandler{} - mds := &defsendermocks.Sender{} + mds := &definitionsmocks.Sender{} mbm := &broadcastmocks.Manager{} mpm := &privatemessagingmocks.Manager{} mni := &sysmessagingmocks.LocalNodeInfo{} diff --git a/internal/events/token_pool_created_test.go b/internal/events/token_pool_created_test.go index 960e36963..5c006662a 100644 --- a/internal/events/token_pool_created_test.go +++ b/internal/events/token_pool_created_test.go @@ -24,7 +24,7 @@ import ( "github.com/hyperledger/firefly/mocks/assetmocks" "github.com/hyperledger/firefly/mocks/databasemocks" "github.com/hyperledger/firefly/mocks/datamocks" - "github.com/hyperledger/firefly/mocks/defsendermocks" + "github.com/hyperledger/firefly/mocks/definitionsmocks" "github.com/hyperledger/firefly/mocks/tokenmocks" "github.com/hyperledger/firefly/mocks/txcommonmocks" "github.com/hyperledger/firefly/pkg/blockchain" @@ -472,7 +472,7 @@ func TestTokenPoolCreatedAnnounce(t *testing.T) { defer cancel() mdi := em.database.(*databasemocks.Plugin) mti := &tokenmocks.Plugin{} - mds := em.defsender.(*defsendermocks.Sender) + mds := em.defsender.(*definitionsmocks.Sender) poolID := fftypes.NewUUID() txID := fftypes.NewUUID() diff --git a/internal/networkmap/manager.go b/internal/networkmap/manager.go index 091b748ef..feaafda3f 100644 --- a/internal/networkmap/manager.go +++ b/internal/networkmap/manager.go @@ -21,7 +21,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/coremsgs" - "github.com/hyperledger/firefly/internal/defsender" + "github.com/hyperledger/firefly/internal/definitions" "github.com/hyperledger/firefly/internal/identity" "github.com/hyperledger/firefly/internal/multiparty" "github.com/hyperledger/firefly/internal/syncasync" @@ -59,14 +59,14 @@ type networkMap struct { ctx context.Context namespace string database database.Plugin - defsender defsender.Sender + defsender definitions.Sender exchange dataexchange.Plugin // optional identity identity.Manager syncasync syncasync.Bridge multiparty multiparty.Manager // optional } -func NewNetworkMap(ctx context.Context, ns string, di database.Plugin, dx dataexchange.Plugin, ds defsender.Sender, im identity.Manager, sa syncasync.Bridge, mm multiparty.Manager) (Manager, error) { +func NewNetworkMap(ctx context.Context, ns string, di database.Plugin, dx dataexchange.Plugin, ds definitions.Sender, im identity.Manager, sa syncasync.Bridge, mm multiparty.Manager) (Manager, error) { if di == nil || ds == nil || im == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "NetworkMap") } diff --git a/internal/networkmap/manager_test.go b/internal/networkmap/manager_test.go index 48c031395..204bc5f62 100644 --- a/internal/networkmap/manager_test.go +++ b/internal/networkmap/manager_test.go @@ -23,7 +23,7 @@ import ( "github.com/hyperledger/firefly/internal/coreconfig" "github.com/hyperledger/firefly/mocks/databasemocks" "github.com/hyperledger/firefly/mocks/dataexchangemocks" - "github.com/hyperledger/firefly/mocks/defsendermocks" + "github.com/hyperledger/firefly/mocks/definitionsmocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/mocks/multipartymocks" "github.com/hyperledger/firefly/mocks/syncasyncmocks" @@ -34,7 +34,7 @@ func newTestNetworkmap(t *testing.T) (*networkMap, func()) { coreconfig.Reset() ctx, cancel := context.WithCancel(context.Background()) mdi := &databasemocks.Plugin{} - mds := &defsendermocks.Sender{} + mds := &definitionsmocks.Sender{} mdx := &dataexchangemocks.Plugin{} mim := &identitymanagermocks.Manager{} msa := &syncasyncmocks.Bridge{} diff --git a/internal/networkmap/register_identity_test.go b/internal/networkmap/register_identity_test.go index 39009ad8b..6a8d79bf5 100644 --- a/internal/networkmap/register_identity_test.go +++ b/internal/networkmap/register_identity_test.go @@ -23,7 +23,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/syncasync" - "github.com/hyperledger/firefly/mocks/defsendermocks" + "github.com/hyperledger/firefly/mocks/definitionsmocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/mocks/syncasyncmocks" "github.com/hyperledger/firefly/pkg/core" @@ -46,7 +46,7 @@ func TestRegisterIdentityOrgWithParentOk(t *testing.T) { mockMsg1 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mockMsg2 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mds := nm.defsender.(*defsendermocks.Sender) + mds := nm.defsender.(*definitionsmocks.Sender) mds.On("CreateIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), @@ -100,7 +100,7 @@ func TestRegisterIdentityOrgWithParentWaitConfirmOk(t *testing.T) { mockMsg1 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mockMsg2 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mds := nm.defsender.(*defsendermocks.Sender) + mds := nm.defsender.(*definitionsmocks.Sender) mds.On("CreateIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), @@ -148,7 +148,7 @@ func TestRegisterIdentityCustomWithParentFail(t *testing.T) { }, nil) mockMsg := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mds := nm.defsender.(*defsendermocks.Sender) + mds := nm.defsender.(*definitionsmocks.Sender) mds.On("CreateIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), @@ -204,7 +204,7 @@ func TestRegisterIdentityRootBroadcastFail(t *testing.T) { mim := nm.identity.(*identitymanagermocks.Manager) mim.On("VerifyIdentityChain", nm.ctx, mock.AnythingOfType("*core.Identity")).Return(nil, false, nil) - mds := nm.defsender.(*defsendermocks.Sender) + mds := nm.defsender.(*definitionsmocks.Sender) mds.On("CreateIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { diff --git a/internal/networkmap/register_node_test.go b/internal/networkmap/register_node_test.go index 15050460b..b9c51dbd4 100644 --- a/internal/networkmap/register_node_test.go +++ b/internal/networkmap/register_node_test.go @@ -24,7 +24,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/coreconfig" "github.com/hyperledger/firefly/mocks/dataexchangemocks" - "github.com/hyperledger/firefly/mocks/defsendermocks" + "github.com/hyperledger/firefly/mocks/definitionsmocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" @@ -55,7 +55,7 @@ func TestRegisterNodeOk(t *testing.T) { }, nil) mockMsg := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mds := nm.defsender.(*defsendermocks.Sender) + mds := nm.defsender.(*definitionsmocks.Sender) mds.On("CreateIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), signerRef, diff --git a/internal/networkmap/register_org_test.go b/internal/networkmap/register_org_test.go index 33c6d364e..d617167c7 100644 --- a/internal/networkmap/register_org_test.go +++ b/internal/networkmap/register_org_test.go @@ -23,7 +23,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/multiparty" - "github.com/hyperledger/firefly/mocks/defsendermocks" + "github.com/hyperledger/firefly/mocks/definitionsmocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/mocks/multipartymocks" "github.com/hyperledger/firefly/pkg/core" @@ -68,7 +68,7 @@ func TestRegisterNodeOrgOk(t *testing.T) { mmp.On("RootOrg").Return(multiparty.RootOrg{Name: "org0"}) mockMsg := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mds := nm.defsender.(*defsendermocks.Sender) + mds := nm.defsender.(*definitionsmocks.Sender) mds.On("CreateIdentityClaim", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { diff --git a/internal/networkmap/update_identity_test.go b/internal/networkmap/update_identity_test.go index aac84a9b6..5a9072a29 100644 --- a/internal/networkmap/update_identity_test.go +++ b/internal/networkmap/update_identity_test.go @@ -21,7 +21,7 @@ import ( "testing" "github.com/hyperledger/firefly-common/pkg/fftypes" - "github.com/hyperledger/firefly/mocks/defsendermocks" + "github.com/hyperledger/firefly/mocks/definitionsmocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" @@ -41,7 +41,7 @@ func TestUpdateIdentityProfileOk(t *testing.T) { mim.On("ResolveIdentitySigner", nm.ctx, identity).Return(signerRef, nil) mockMsg1 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mds := nm.defsender.(*defsendermocks.Sender) + mds := nm.defsender.(*definitionsmocks.Sender) mds.On("CreateDefinitionWithIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityUpdate"), @@ -75,7 +75,7 @@ func TestUpdateIdentityProfileBroadcastFail(t *testing.T) { signerRef := &core.SignerRef{Key: "0x12345"} mim.On("ResolveIdentitySigner", nm.ctx, identity).Return(signerRef, nil) - mds := nm.defsender.(*defsendermocks.Sender) + mds := nm.defsender.(*definitionsmocks.Sender) mds.On("CreateDefinitionWithIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityUpdate"), mock.MatchedBy(func(sr *core.SignerRef) bool { diff --git a/internal/orchestrator/orchestrator.go b/internal/orchestrator/orchestrator.go index 469f17625..46521823d 100644 --- a/internal/orchestrator/orchestrator.go +++ b/internal/orchestrator/orchestrator.go @@ -29,7 +29,6 @@ import ( "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/internal/data" "github.com/hyperledger/firefly/internal/definitions" - "github.com/hyperledger/firefly/internal/defsender" "github.com/hyperledger/firefly/internal/events" "github.com/hyperledger/firefly/internal/identity" "github.com/hyperledger/firefly/internal/metrics" @@ -61,7 +60,7 @@ type Orchestrator interface { Broadcast() broadcast.Manager // only for multiparty PrivateMessaging() privatemessaging.Manager // only for multiparty Assets() assets.Manager - DefinitionSender() defsender.Sender + DefinitionSender() definitions.Sender Contracts() contracts.Manager Data() data.Manager Events() events.EventManager @@ -180,7 +179,7 @@ type orchestrator struct { events events.EventManager networkmap networkmap.Manager defhandler definitions.DefinitionHandler - defsender defsender.Sender + defsender definitions.Sender data data.Manager syncasync syncasync.Bridge assets assets.Manager @@ -325,7 +324,7 @@ func (or *orchestrator) PrivateMessaging() privatemessaging.Manager { return or.messaging } -func (or *orchestrator) DefinitionSender() defsender.Sender { +func (or *orchestrator) DefinitionSender() definitions.Sender { return or.defsender } @@ -470,7 +469,7 @@ func (or *orchestrator) initManagers(ctx context.Context) (err error) { } if or.defsender == nil { - or.defsender, err = defsender.NewDefinitionSender(ctx, or.namespace, or.config.Multiparty.Enabled, or.database(), or.broadcast, or.identity, or.data, or.contracts) + or.defsender, err = definitions.NewDefinitionSender(ctx, or.namespace, or.config.Multiparty.Enabled, or.database(), or.broadcast, or.identity, or.data, or.contracts) if err != nil { return err } diff --git a/internal/orchestrator/orchestrator_test.go b/internal/orchestrator/orchestrator_test.go index baeb70130..21b9eb498 100644 --- a/internal/orchestrator/orchestrator_test.go +++ b/internal/orchestrator/orchestrator_test.go @@ -32,7 +32,6 @@ import ( "github.com/hyperledger/firefly/mocks/dataexchangemocks" "github.com/hyperledger/firefly/mocks/datamocks" "github.com/hyperledger/firefly/mocks/definitionsmocks" - "github.com/hyperledger/firefly/mocks/defsendermocks" "github.com/hyperledger/firefly/mocks/eventmocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/mocks/identitymocks" @@ -78,7 +77,7 @@ type testOrchestrator struct { mae *spieventsmocks.Manager mdh *definitionsmocks.DefinitionHandler mmp *multipartymocks.Manager - mds *defsendermocks.Sender + mds *definitionsmocks.Sender } func (tor *testOrchestrator) cleanup(t *testing.T) { @@ -137,7 +136,7 @@ func newTestOrchestrator() *testOrchestrator { mae: &spieventsmocks.Manager{}, mdh: &definitionsmocks.DefinitionHandler{}, mmp: &multipartymocks.Manager{}, - mds: &defsendermocks.Sender{}, + mds: &definitionsmocks.Sender{}, } tor.orchestrator.multiparty = tor.mmp tor.orchestrator.data = tor.mdm diff --git a/mocks/defsendermocks/sender.go b/mocks/definitionsmocks/sender.go similarity index 97% rename from mocks/defsendermocks/sender.go rename to mocks/definitionsmocks/sender.go index a2a607c6e..68e4c88cc 100644 --- a/mocks/defsendermocks/sender.go +++ b/mocks/definitionsmocks/sender.go @@ -1,11 +1,11 @@ // Code generated by mockery v1.0.0. DO NOT EDIT. -package defsendermocks +package definitionsmocks import ( context "context" - defsender "github.com/hyperledger/firefly/internal/defsender" + definitions "github.com/hyperledger/firefly/internal/definitions" core "github.com/hyperledger/firefly/pkg/core" mock "github.com/stretchr/testify/mock" @@ -178,7 +178,7 @@ func (_m *Sender) CreateTokenPool(ctx context.Context, pool *core.TokenPoolAnnou } // Init provides a mock function with given fields: handler -func (_m *Sender) Init(handler defsender.DefinitionHandler) { +func (_m *Sender) Init(handler definitions.DefinitionHandler) { _m.Called(handler) } diff --git a/mocks/orchestratormocks/orchestrator.go b/mocks/orchestratormocks/orchestrator.go index 36364dbc6..cfb6babde 100644 --- a/mocks/orchestratormocks/orchestrator.go +++ b/mocks/orchestratormocks/orchestrator.go @@ -18,7 +18,7 @@ import ( database "github.com/hyperledger/firefly/pkg/database" - defsender "github.com/hyperledger/firefly/internal/defsender" + definitions "github.com/hyperledger/firefly/internal/definitions" events "github.com/hyperledger/firefly/internal/events" @@ -165,15 +165,15 @@ func (_m *Orchestrator) Data() data.Manager { } // DefinitionSender provides a mock function with given fields: -func (_m *Orchestrator) DefinitionSender() defsender.Sender { +func (_m *Orchestrator) DefinitionSender() definitions.Sender { ret := _m.Called() - var r0 defsender.Sender - if rf, ok := ret.Get(0).(func() defsender.Sender); ok { + var r0 definitions.Sender + if rf, ok := ret.Get(0).(func() definitions.Sender); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(defsender.Sender) + r0 = ret.Get(0).(definitions.Sender) } } From a8e080ee98191a62e69772481bbe565c2756bbb4 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Mon, 27 Jun 2022 23:01:25 -0400 Subject: [PATCH 15/27] Shorten definition handler filenames Signed-off-by: Andrew Richardson --- Makefile | 2 +- .../{definition_handler.go => handler.go} | 14 +++++++------- ...n_handler_contracts.go => handler_contracts.go} | 8 ++++---- ...contracts_test.go => handler_contracts_test.go} | 0 ...ion_handler_datatype.go => handler_datatype.go} | 2 +- ...r_datatype_test.go => handler_datatype_test.go} | 0 ...identity_claim.go => handler_identity_claim.go} | 10 +++++----- ...laim_test.go => handler_identity_claim_test.go} | 0 ...entity_update.go => handler_identity_update.go} | 2 +- ...ate_test.go => handler_identity_update_test.go} | 0 ...ication.go => handler_identity_verification.go} | 2 +- ...st.go => handler_identity_verification_test.go} | 0 ...n_handler_namespace.go => handler_namespace.go} | 2 +- ...namespace_test.go => handler_namespace_test.go} | 0 ...ler_network_node.go => handler_network_node.go} | 2 +- ...k_node_test.go => handler_network_node_test.go} | 0 ...ndler_network_org.go => handler_network_org.go} | 2 +- ...ork_org_test.go => handler_network_org_test.go} | 0 ...{definition_handler_test.go => handler_test.go} | 4 ++-- ...n_handler_tokenpool.go => handler_tokenpool.go} | 2 +- ...tokenpool_test.go => handler_tokenpool_test.go} | 0 internal/definitions/sender.go | 6 +++--- internal/events/aggregator.go | 4 ++-- internal/events/aggregator_test.go | 10 +++++----- internal/events/event_manager.go | 4 ++-- internal/events/event_manager_test.go | 4 ++-- internal/orchestrator/orchestrator.go | 2 +- internal/orchestrator/orchestrator_test.go | 4 ++-- .../{definition_handler.go => handler.go} | 8 ++++---- mocks/definitionsmocks/sender.go | 2 +- 30 files changed, 48 insertions(+), 48 deletions(-) rename internal/definitions/{definition_handler.go => handler.go} (89%) rename internal/definitions/{definition_handler_contracts.go => handler_contracts.go} (87%) rename internal/definitions/{definition_handler_contracts_test.go => handler_contracts_test.go} (100%) rename internal/definitions/{definition_handler_datatype.go => handler_datatype.go} (92%) rename internal/definitions/{definition_handler_datatype_test.go => handler_datatype_test.go} (100%) rename internal/definitions/{definition_handler_identity_claim.go => handler_identity_claim.go} (91%) rename internal/definitions/{definition_handler_identity_claim_test.go => handler_identity_claim_test.go} (100%) rename internal/definitions/{definition_handler_identity_update.go => handler_identity_update.go} (93%) rename internal/definitions/{definition_handler_identity_update_test.go => handler_identity_update_test.go} (100%) rename internal/definitions/{definition_handler_identity_verification.go => handler_identity_verification.go} (95%) rename internal/definitions/{definition_handler_identity_verification_test.go => handler_identity_verification_test.go} (100%) rename internal/definitions/{definition_handler_namespace.go => handler_namespace.go} (92%) rename internal/definitions/{definition_handler_namespace_test.go => handler_namespace_test.go} (100%) rename internal/definitions/{definition_handler_network_node.go => handler_network_node.go} (90%) rename internal/definitions/{definition_handler_network_node_test.go => handler_network_node_test.go} (100%) rename internal/definitions/{definition_handler_network_org.go => handler_network_org.go} (86%) rename internal/definitions/{definition_handler_network_org_test.go => handler_network_org_test.go} (100%) rename internal/definitions/{definition_handler_test.go => handler_test.go} (96%) rename internal/definitions/{definition_handler_tokenpool.go => handler_tokenpool.go} (94%) rename internal/definitions/{definition_handler_tokenpool_test.go => handler_tokenpool_test.go} (100%) rename mocks/definitionsmocks/{definition_handler.go => handler.go} (74%) diff --git a/Makefile b/Makefile index d18ca2929..dfee557d9 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,7 @@ $(eval $(call makemock, internal/broadcast, Manager, broadcast $(eval $(call makemock, internal/privatemessaging, Manager, privatemessagingmocks)) $(eval $(call makemock, internal/shareddownload, Manager, shareddownloadmocks)) $(eval $(call makemock, internal/shareddownload, Callbacks, shareddownloadmocks)) -$(eval $(call makemock, internal/definitions, DefinitionHandler, definitionsmocks)) +$(eval $(call makemock, internal/definitions, Handler, definitionsmocks)) $(eval $(call makemock, internal/definitions, Sender, definitionsmocks)) $(eval $(call makemock, internal/events, EventManager, eventmocks)) $(eval $(call makemock, internal/namespace, Manager, namespacemocks)) diff --git a/internal/definitions/definition_handler.go b/internal/definitions/handler.go similarity index 89% rename from internal/definitions/definition_handler.go rename to internal/definitions/handler.go index 9f7424674..97698ff4e 100644 --- a/internal/definitions/definition_handler.go +++ b/internal/definitions/handler.go @@ -35,7 +35,7 @@ import ( "github.com/hyperledger/firefly/pkg/dataexchange" ) -type DefinitionHandler interface { +type Handler interface { HandleDefinitionBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error } @@ -77,7 +77,7 @@ func (dma DefinitionMessageAction) String() string { } } -type definitionHandlers struct { +type definitionHandler struct { namespace string multiparty bool database database.Plugin @@ -89,11 +89,11 @@ type definitionHandlers struct { contracts contracts.Manager } -func NewDefinitionHandler(ctx context.Context, ns string, multiparty bool, di database.Plugin, bi blockchain.Plugin, dx dataexchange.Plugin, dm data.Manager, im identity.Manager, am assets.Manager, cm contracts.Manager) (DefinitionHandler, error) { +func NewDefinitionHandler(ctx context.Context, ns string, multiparty bool, di database.Plugin, bi blockchain.Plugin, dx dataexchange.Plugin, dm data.Manager, im identity.Manager, am assets.Manager, cm contracts.Manager) (Handler, error) { if di == nil || bi == nil || dm == nil || im == nil || am == nil || cm == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "DefinitionHandler") } - return &definitionHandlers{ + return &definitionHandler{ namespace: ns, multiparty: multiparty, database: di, @@ -106,7 +106,7 @@ func NewDefinitionHandler(ctx context.Context, ns string, multiparty bool, di da }, nil } -func (dh *definitionHandlers) HandleDefinitionBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (msgAction HandlerResult, err error) { +func (dh *definitionHandler) HandleDefinitionBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (msgAction HandlerResult, err error) { l := log.L(ctx) l.Infof("Processing system definition '%s' [%s]", msg.Header.Tag, msg.Header.ID) switch msg.Header.Tag { @@ -135,7 +135,7 @@ func (dh *definitionHandlers) HandleDefinitionBroadcast(ctx context.Context, sta } } -func (dh *definitionHandlers) getSystemBroadcastPayload(ctx context.Context, msg *core.Message, data core.DataArray, res core.Definition) (valid bool) { +func (dh *definitionHandler) getSystemBroadcastPayload(ctx context.Context, msg *core.Message, data core.DataArray, res core.Definition) (valid bool) { l := log.L(ctx) if len(data) != 1 { l.Warnf("Unable to process system definition %s - expecting 1 attachment, found %d", msg.Header.ID, len(data)) @@ -150,7 +150,7 @@ func (dh *definitionHandlers) getSystemBroadcastPayload(ctx context.Context, msg return true } -func (dh *definitionHandlers) HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error { +func (dh *definitionHandler) HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error { result, err := dh.HandleDefinitionBroadcast(ctx, state, msg, core.DataArray{data}, nil) if result.Action == ActionReject { return i18n.WrapError(ctx, err, coremsgs.MsgDefinitionRejected) diff --git a/internal/definitions/definition_handler_contracts.go b/internal/definitions/handler_contracts.go similarity index 87% rename from internal/definitions/definition_handler_contracts.go rename to internal/definitions/handler_contracts.go index e3bc9fd40..372555ea8 100644 --- a/internal/definitions/definition_handler_contracts.go +++ b/internal/definitions/handler_contracts.go @@ -27,7 +27,7 @@ import ( "github.com/hyperledger/firefly/pkg/database" ) -func (dh *definitionHandlers) persistFFI(ctx context.Context, ffi *core.FFI) (err error) { +func (dh *definitionHandler) persistFFI(ctx context.Context, ffi *core.FFI) (err error) { if err = dh.contracts.ResolveFFI(ctx, ffi); err != nil { log.L(ctx).Warnf("Unable to process FFI %s - validate failed: %s", ffi.ID, err) return nil @@ -55,7 +55,7 @@ func (dh *definitionHandlers) persistFFI(ctx context.Context, ffi *core.FFI) (er return nil } -func (dh *definitionHandlers) persistContractAPI(ctx context.Context, api *core.ContractAPI) (retry bool, err error) { +func (dh *definitionHandler) persistContractAPI(ctx context.Context, api *core.ContractAPI) (retry bool, err error) { existing, err := dh.database.GetContractAPIByName(ctx, api.Namespace, api.Name) if err != nil { return true, err @@ -75,7 +75,7 @@ func (dh *definitionHandlers) persistContractAPI(ctx context.Context, api *core. return false, nil } -func (dh *definitionHandlers) handleFFIBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { +func (dh *definitionHandler) handleFFIBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { l := log.L(ctx) var ffi core.FFI if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &ffi); !valid { @@ -98,7 +98,7 @@ func (dh *definitionHandlers) handleFFIBroadcast(ctx context.Context, state *cor return HandlerResult{Action: ActionConfirm}, nil } -func (dh *definitionHandlers) handleContractAPIBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { +func (dh *definitionHandler) handleContractAPIBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { l := log.L(ctx) var api core.ContractAPI if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &api); !valid { diff --git a/internal/definitions/definition_handler_contracts_test.go b/internal/definitions/handler_contracts_test.go similarity index 100% rename from internal/definitions/definition_handler_contracts_test.go rename to internal/definitions/handler_contracts_test.go diff --git a/internal/definitions/definition_handler_datatype.go b/internal/definitions/handler_datatype.go similarity index 92% rename from internal/definitions/definition_handler_datatype.go rename to internal/definitions/handler_datatype.go index 1730d6894..bb99dde0f 100644 --- a/internal/definitions/definition_handler_datatype.go +++ b/internal/definitions/handler_datatype.go @@ -25,7 +25,7 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (dh *definitionHandlers) handleDatatypeBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { +func (dh *definitionHandler) handleDatatypeBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { var dt core.Datatype valid := dh.getSystemBroadcastPayload(ctx, msg, data, &dt) if !valid { diff --git a/internal/definitions/definition_handler_datatype_test.go b/internal/definitions/handler_datatype_test.go similarity index 100% rename from internal/definitions/definition_handler_datatype_test.go rename to internal/definitions/handler_datatype_test.go diff --git a/internal/definitions/definition_handler_identity_claim.go b/internal/definitions/handler_identity_claim.go similarity index 91% rename from internal/definitions/definition_handler_identity_claim.go rename to internal/definitions/handler_identity_claim.go index 90f8e81f0..4940850c7 100644 --- a/internal/definitions/definition_handler_identity_claim.go +++ b/internal/definitions/handler_identity_claim.go @@ -28,7 +28,7 @@ import ( "github.com/hyperledger/firefly/pkg/database" ) -func (dh *definitionHandlers) handleIdentityClaimBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, verificationID *fftypes.UUID) (HandlerResult, error) { +func (dh *definitionHandler) handleIdentityClaimBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, verificationID *fftypes.UUID) (HandlerResult, error) { var claim core.IdentityClaim if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &claim); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "identity claim", msg.Header.ID) @@ -36,7 +36,7 @@ func (dh *definitionHandlers) handleIdentityClaimBroadcast(ctx context.Context, return dh.handleIdentityClaim(ctx, state, msg, &claim, verificationID) } -func (dh *definitionHandlers) verifyClaimSignature(ctx context.Context, msg *core.Message, identity *core.Identity, parent *core.Identity) error { +func (dh *definitionHandler) verifyClaimSignature(ctx context.Context, msg *core.Message, identity *core.Identity, parent *core.Identity) error { author := msg.Header.Author if author == "" { return i18n.NewError(ctx, coremsgs.MsgDefRejectedAuthorBlank, "identity claim", msg.Header.ID) @@ -60,7 +60,7 @@ func (dh *definitionHandlers) verifyClaimSignature(ctx context.Context, msg *cor return nil } -func (dh *definitionHandlers) getClaimVerifier(msg *core.Message, identity *core.Identity) *core.Verifier { +func (dh *definitionHandler) getClaimVerifier(msg *core.Message, identity *core.Identity) *core.Verifier { verifier := &core.Verifier{ Identity: identity.ID, Namespace: identity.Namespace, @@ -77,7 +77,7 @@ func (dh *definitionHandlers) getClaimVerifier(msg *core.Message, identity *core return verifier } -func (dh *definitionHandlers) confirmVerificationForClaim(ctx context.Context, state *core.BatchState, msg *core.Message, identity, parent *core.Identity) (*fftypes.UUID, error) { +func (dh *definitionHandler) confirmVerificationForClaim(ctx context.Context, state *core.BatchState, msg *core.Message, identity, parent *core.Identity) (*fftypes.UUID, error) { // Query for messages on the topic for this DID, signed by the right identity idTopic := identity.Topic() fb := database.MessageQueryFactory.NewFilter(ctx) @@ -126,7 +126,7 @@ func (dh *definitionHandlers) confirmVerificationForClaim(ctx context.Context, s return nil, nil } -func (dh *definitionHandlers) handleIdentityClaim(ctx context.Context, state *core.BatchState, msg *core.Message, identityClaim *core.IdentityClaim, verificationID *fftypes.UUID) (HandlerResult, error) { +func (dh *definitionHandler) handleIdentityClaim(ctx context.Context, state *core.BatchState, msg *core.Message, identityClaim *core.IdentityClaim, verificationID *fftypes.UUID) (HandlerResult, error) { l := log.L(ctx) identity := identityClaim.Identity diff --git a/internal/definitions/definition_handler_identity_claim_test.go b/internal/definitions/handler_identity_claim_test.go similarity index 100% rename from internal/definitions/definition_handler_identity_claim_test.go rename to internal/definitions/handler_identity_claim_test.go diff --git a/internal/definitions/definition_handler_identity_update.go b/internal/definitions/handler_identity_update.go similarity index 93% rename from internal/definitions/definition_handler_identity_update.go rename to internal/definitions/handler_identity_update.go index 5846292fa..72dc10615 100644 --- a/internal/definitions/definition_handler_identity_update.go +++ b/internal/definitions/handler_identity_update.go @@ -25,7 +25,7 @@ import ( "github.com/hyperledger/firefly/pkg/database" ) -func (dh *definitionHandlers) handleIdentityUpdateBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { +func (dh *definitionHandler) handleIdentityUpdateBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { var update core.IdentityUpdate if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &update); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "identity update", msg.Header.ID) diff --git a/internal/definitions/definition_handler_identity_update_test.go b/internal/definitions/handler_identity_update_test.go similarity index 100% rename from internal/definitions/definition_handler_identity_update_test.go rename to internal/definitions/handler_identity_update_test.go diff --git a/internal/definitions/definition_handler_identity_verification.go b/internal/definitions/handler_identity_verification.go similarity index 95% rename from internal/definitions/definition_handler_identity_verification.go rename to internal/definitions/handler_identity_verification.go index 88bab6846..013ebd935 100644 --- a/internal/definitions/definition_handler_identity_verification.go +++ b/internal/definitions/handler_identity_verification.go @@ -24,7 +24,7 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (dh *definitionHandlers) handleIdentityVerificationBroadcast(ctx context.Context, state *core.BatchState, verifyMsg *core.Message, data core.DataArray) (HandlerResult, error) { +func (dh *definitionHandler) handleIdentityVerificationBroadcast(ctx context.Context, state *core.BatchState, verifyMsg *core.Message, data core.DataArray) (HandlerResult, error) { var verification core.IdentityVerification valid := dh.getSystemBroadcastPayload(ctx, verifyMsg, data, &verification) if !valid { diff --git a/internal/definitions/definition_handler_identity_verification_test.go b/internal/definitions/handler_identity_verification_test.go similarity index 100% rename from internal/definitions/definition_handler_identity_verification_test.go rename to internal/definitions/handler_identity_verification_test.go diff --git a/internal/definitions/definition_handler_namespace.go b/internal/definitions/handler_namespace.go similarity index 92% rename from internal/definitions/definition_handler_namespace.go rename to internal/definitions/handler_namespace.go index 9725906a8..1bf7ea5f0 100644 --- a/internal/definitions/definition_handler_namespace.go +++ b/internal/definitions/handler_namespace.go @@ -25,7 +25,7 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (dh *definitionHandlers) handleNamespaceBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { +func (dh *definitionHandler) handleNamespaceBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { var ns core.Namespace if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &ns); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "namespace", msg.Header.ID) diff --git a/internal/definitions/definition_handler_namespace_test.go b/internal/definitions/handler_namespace_test.go similarity index 100% rename from internal/definitions/definition_handler_namespace_test.go rename to internal/definitions/handler_namespace_test.go diff --git a/internal/definitions/definition_handler_network_node.go b/internal/definitions/handler_network_node.go similarity index 90% rename from internal/definitions/definition_handler_network_node.go rename to internal/definitions/handler_network_node.go index fe33b8c33..eb73bc377 100644 --- a/internal/definitions/definition_handler_network_node.go +++ b/internal/definitions/handler_network_node.go @@ -24,7 +24,7 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (dh *definitionHandlers) handleDeprecatedNodeBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { +func (dh *definitionHandler) handleDeprecatedNodeBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { var nodeOld core.DeprecatedNode if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &nodeOld); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "node", msg.Header.ID) diff --git a/internal/definitions/definition_handler_network_node_test.go b/internal/definitions/handler_network_node_test.go similarity index 100% rename from internal/definitions/definition_handler_network_node_test.go rename to internal/definitions/handler_network_node_test.go diff --git a/internal/definitions/definition_handler_network_org.go b/internal/definitions/handler_network_org.go similarity index 86% rename from internal/definitions/definition_handler_network_org.go rename to internal/definitions/handler_network_org.go index 87c7df3a2..20bcfd396 100644 --- a/internal/definitions/definition_handler_network_org.go +++ b/internal/definitions/handler_network_org.go @@ -24,7 +24,7 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (dh *definitionHandlers) handleDeprecatedOrganizationBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { +func (dh *definitionHandler) handleDeprecatedOrganizationBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { var orgOld core.DeprecatedOrganization valid := dh.getSystemBroadcastPayload(ctx, msg, data, &orgOld) diff --git a/internal/definitions/definition_handler_network_org_test.go b/internal/definitions/handler_network_org_test.go similarity index 100% rename from internal/definitions/definition_handler_network_org_test.go rename to internal/definitions/handler_network_org_test.go diff --git a/internal/definitions/definition_handler_test.go b/internal/definitions/handler_test.go similarity index 96% rename from internal/definitions/definition_handler_test.go rename to internal/definitions/handler_test.go index 38def011b..f859dd426 100644 --- a/internal/definitions/definition_handler_test.go +++ b/internal/definitions/handler_test.go @@ -33,7 +33,7 @@ import ( "github.com/stretchr/testify/assert" ) -func newTestDefinitionHandler(t *testing.T) (*definitionHandlers, *testDefinitionBatchState) { +func newTestDefinitionHandler(t *testing.T) (*definitionHandler, *testDefinitionBatchState) { mdi := &databasemocks.Plugin{} mbi := &blockchainmocks.Plugin{} mdx := &dataexchangemocks.Plugin{} @@ -43,7 +43,7 @@ func newTestDefinitionHandler(t *testing.T) (*definitionHandlers, *testDefinitio mcm := &contractmocks.Manager{} mbi.On("VerifierType").Return(core.VerifierTypeEthAddress).Maybe() dh, _ := NewDefinitionHandler(context.Background(), "ns1", false, mdi, mbi, mdx, mdm, mim, mam, mcm) - return dh.(*definitionHandlers), newTestDefinitionBatchState(t) + return dh.(*definitionHandler), newTestDefinitionBatchState(t) } type testDefinitionBatchState struct { diff --git a/internal/definitions/definition_handler_tokenpool.go b/internal/definitions/handler_tokenpool.go similarity index 94% rename from internal/definitions/definition_handler_tokenpool.go rename to internal/definitions/handler_tokenpool.go index bd05291b0..5c49cd7bd 100644 --- a/internal/definitions/definition_handler_tokenpool.go +++ b/internal/definitions/handler_tokenpool.go @@ -26,7 +26,7 @@ import ( "github.com/hyperledger/firefly/pkg/database" ) -func (dh *definitionHandlers) handleTokenPoolBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { +func (dh *definitionHandler) handleTokenPoolBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { var announce core.TokenPoolAnnouncement if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &announce); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "token pool", msg.Header.ID) diff --git a/internal/definitions/definition_handler_tokenpool_test.go b/internal/definitions/handler_tokenpool_test.go similarity index 100% rename from internal/definitions/definition_handler_tokenpool_test.go rename to internal/definitions/handler_tokenpool_test.go diff --git a/internal/definitions/sender.go b/internal/definitions/sender.go index 552e3097e..07f5a8c2f 100644 --- a/internal/definitions/sender.go +++ b/internal/definitions/sender.go @@ -34,7 +34,7 @@ import ( type Sender interface { core.Named - Init(handler DefinitionHandler) + Init(handler Handler) CreateDefinition(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) CreateDefinitionWithIdentity(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (msg *core.Message, err error) @@ -53,7 +53,7 @@ type definitionSender struct { identity identity.Manager data data.Manager contracts contracts.Manager - handler DefinitionHandler + handler Handler } func NewDefinitionSender(ctx context.Context, ns string, multiparty bool, di database.Plugin, bm broadcast.Manager, im identity.Manager, dm data.Manager, cm contracts.Manager) (Sender, error) { @@ -76,7 +76,7 @@ func (bm *definitionSender) Name() string { return "DefinitionSender" } -func (bm *definitionSender) Init(handler DefinitionHandler) { +func (bm *definitionSender) Init(handler Handler) { bm.handler = handler } diff --git a/internal/events/aggregator.go b/internal/events/aggregator.go index 345261e13..2d123bd4c 100644 --- a/internal/events/aggregator.go +++ b/internal/events/aggregator.go @@ -48,7 +48,7 @@ type aggregator struct { namespace string database database.Plugin messaging privatemessaging.Manager - definitions definitions.DefinitionHandler + definitions definitions.Handler identity identity.Manager data data.Manager eventPoller *eventPoller @@ -65,7 +65,7 @@ type batchCacheEntry struct { manifest *core.BatchManifest } -func newAggregator(ctx context.Context, ns string, di database.Plugin, bi blockchain.Plugin, pm privatemessaging.Manager, sh definitions.DefinitionHandler, im identity.Manager, dm data.Manager, en *eventNotifier, mm metrics.Manager) *aggregator { +func newAggregator(ctx context.Context, ns string, di database.Plugin, bi blockchain.Plugin, pm privatemessaging.Manager, sh definitions.Handler, im identity.Manager, dm data.Manager, en *eventNotifier, mm metrics.Manager) *aggregator { batchSize := config.GetInt(coreconfig.EventAggregatorBatchSize) ag := &aggregator{ ctx: log.WithLogField(ctx, "role", "aggregator"), diff --git a/internal/events/aggregator_test.go b/internal/events/aggregator_test.go index cdf59bba9..886185c72 100644 --- a/internal/events/aggregator_test.go +++ b/internal/events/aggregator_test.go @@ -49,7 +49,7 @@ func newTestAggregatorCommon(metrics bool) (*aggregator, func()) { mdi := &databasemocks.Plugin{} mdm := &datamocks.Manager{} mpm := &privatemessagingmocks.Manager{} - msh := &definitionsmocks.DefinitionHandler{} + msh := &definitionsmocks.Handler{} mim := &identitymanagermocks.Manager{} mmi := &metricsmocks.Manager{} mbi := &blockchainmocks.Plugin{} @@ -1516,7 +1516,7 @@ func TestDefinitionBroadcastActionRejectCustomCorrelator(t *testing.T) { mim.On("FindIdentityForVerifier", ag.ctx, mock.Anything, mock.Anything).Return(org1, nil) customCorrelator := fftypes.NewUUID() - msh := ag.definitions.(*definitionsmocks.DefinitionHandler) + msh := ag.definitions.(*definitionsmocks.Handler) msh.On("HandleDefinitionBroadcast", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). Return(definitions.HandlerResult{Action: definitions.ActionReject, CustomCorrelator: customCorrelator}, nil) @@ -1733,7 +1733,7 @@ func TestDefinitionBroadcastActionRetry(t *testing.T) { mim := ag.identity.(*identitymanagermocks.Manager) mim.On("FindIdentityForVerifier", ag.ctx, mock.Anything, mock.Anything).Return(org1, nil) - msh := ag.definitions.(*definitionsmocks.DefinitionHandler) + msh := ag.definitions.(*definitionsmocks.Handler) msh.On("HandleDefinitionBroadcast", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(definitions.HandlerResult{Action: definitions.ActionRetry}, fmt.Errorf("pop")) mdm := ag.data.(*datamocks.Manager) @@ -1799,7 +1799,7 @@ func TestDefinitionBroadcastParkUnregisteredSignerIdentityClaim(t *testing.T) { mim := ag.identity.(*identitymanagermocks.Manager) mim.On("FindIdentityForVerifier", ag.ctx, mock.Anything, mock.Anything).Return(nil, nil) - msh := ag.definitions.(*definitionsmocks.DefinitionHandler) + msh := ag.definitions.(*definitionsmocks.Handler) msh.On("HandleDefinitionBroadcast", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(definitions.HandlerResult{Action: definitions.ActionWait}, nil) newState, valid, err := ag.attemptMessageDispatch(ag.ctx, msg1, nil, nil, &batchState{}, &core.Pin{Signer: "0x12345"}) @@ -1836,7 +1836,7 @@ func TestDefinitionBroadcastActionWait(t *testing.T) { mim := ag.identity.(*identitymanagermocks.Manager) mim.On("FindIdentityForVerifier", ag.ctx, mock.Anything, mock.Anything).Return(org1, nil) - msh := ag.definitions.(*definitionsmocks.DefinitionHandler) + msh := ag.definitions.(*definitionsmocks.Handler) msh.On("HandleDefinitionBroadcast", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(definitions.HandlerResult{Action: definitions.ActionWait}, nil) _, _, err := ag.attemptMessageDispatch(ag.ctx, msg1, nil, nil, &batchState{}, &core.Pin{Signer: "0x12345"}) diff --git a/internal/events/event_manager.go b/internal/events/event_manager.go index 46f8c473b..d7fa66e55 100644 --- a/internal/events/event_manager.go +++ b/internal/events/event_manager.go @@ -95,7 +95,7 @@ type eventManager struct { txHelper txcommon.Helper identity identity.Manager defsender definitions.Sender - defhandler definitions.DefinitionHandler + defhandler definitions.Handler data data.Manager subManager *subscriptionManager retry retry.Retry @@ -115,7 +115,7 @@ type eventManager struct { multiparty multiparty.Manager // optional } -func NewEventManager(ctx context.Context, ns string, ni sysmessaging.LocalNodeInfo, di database.Plugin, bi blockchain.Plugin, im identity.Manager, dh definitions.DefinitionHandler, dm data.Manager, ds definitions.Sender, bm broadcast.Manager, pm privatemessaging.Manager, am assets.Manager, sd shareddownload.Manager, mm metrics.Manager, txHelper txcommon.Helper, transports map[string]events.Plugin, mp multiparty.Manager) (EventManager, error) { +func NewEventManager(ctx context.Context, ns string, ni sysmessaging.LocalNodeInfo, di database.Plugin, bi blockchain.Plugin, im identity.Manager, dh definitions.Handler, dm data.Manager, ds definitions.Sender, bm broadcast.Manager, pm privatemessaging.Manager, am assets.Manager, sd shareddownload.Manager, mm metrics.Manager, txHelper txcommon.Helper, transports map[string]events.Plugin, mp multiparty.Manager) (EventManager, error) { if ni == nil || di == nil || bi == nil || im == nil || dh == nil || dm == nil || ds == nil || am == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "EventManager") } diff --git a/internal/events/event_manager_test.go b/internal/events/event_manager_test.go index b04f859bb..190989e8b 100644 --- a/internal/events/event_manager_test.go +++ b/internal/events/event_manager_test.go @@ -73,7 +73,7 @@ func newTestEventManagerCommon(t *testing.T, metrics, dbconcurrency bool) (*even mim := &identitymanagermocks.Manager{} met := &eventsmocks.Plugin{} mdm := &datamocks.Manager{} - msh := &definitionsmocks.DefinitionHandler{} + msh := &definitionsmocks.Handler{} mds := &definitionsmocks.Sender{} mbm := &broadcastmocks.Manager{} mpm := &privatemessagingmocks.Manager{} @@ -142,7 +142,7 @@ func TestStartStopEventListenerFail(t *testing.T) { mbi := &blockchainmocks.Plugin{} mim := &identitymanagermocks.Manager{} mdm := &datamocks.Manager{} - msh := &definitionsmocks.DefinitionHandler{} + msh := &definitionsmocks.Handler{} mds := &definitionsmocks.Sender{} mbm := &broadcastmocks.Manager{} mpm := &privatemessagingmocks.Manager{} diff --git a/internal/orchestrator/orchestrator.go b/internal/orchestrator/orchestrator.go index 46521823d..7186dffed 100644 --- a/internal/orchestrator/orchestrator.go +++ b/internal/orchestrator/orchestrator.go @@ -178,7 +178,7 @@ type orchestrator struct { identity identity.Manager events events.EventManager networkmap networkmap.Manager - defhandler definitions.DefinitionHandler + defhandler definitions.Handler defsender definitions.Sender data data.Manager syncasync syncasync.Bridge diff --git a/internal/orchestrator/orchestrator_test.go b/internal/orchestrator/orchestrator_test.go index 21b9eb498..1004f1861 100644 --- a/internal/orchestrator/orchestrator_test.go +++ b/internal/orchestrator/orchestrator_test.go @@ -75,7 +75,7 @@ type testOrchestrator struct { mth *txcommonmocks.Helper msd *shareddownloadmocks.Manager mae *spieventsmocks.Manager - mdh *definitionsmocks.DefinitionHandler + mdh *definitionsmocks.Handler mmp *multipartymocks.Manager mds *definitionsmocks.Sender } @@ -134,7 +134,7 @@ func newTestOrchestrator() *testOrchestrator { mth: &txcommonmocks.Helper{}, msd: &shareddownloadmocks.Manager{}, mae: &spieventsmocks.Manager{}, - mdh: &definitionsmocks.DefinitionHandler{}, + mdh: &definitionsmocks.Handler{}, mmp: &multipartymocks.Manager{}, mds: &definitionsmocks.Sender{}, } diff --git a/mocks/definitionsmocks/definition_handler.go b/mocks/definitionsmocks/handler.go similarity index 74% rename from mocks/definitionsmocks/definition_handler.go rename to mocks/definitionsmocks/handler.go index f17878456..fcf599ed0 100644 --- a/mocks/definitionsmocks/definition_handler.go +++ b/mocks/definitionsmocks/handler.go @@ -13,13 +13,13 @@ import ( mock "github.com/stretchr/testify/mock" ) -// DefinitionHandler is an autogenerated mock type for the DefinitionHandler type -type DefinitionHandler struct { +// Handler is an autogenerated mock type for the Handler type +type Handler struct { mock.Mock } // HandleDefinition provides a mock function with given fields: ctx, state, msg, data -func (_m *DefinitionHandler) HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error { +func (_m *Handler) HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error { ret := _m.Called(ctx, state, msg, data) var r0 error @@ -33,7 +33,7 @@ func (_m *DefinitionHandler) HandleDefinition(ctx context.Context, state *core.B } // HandleDefinitionBroadcast provides a mock function with given fields: ctx, state, msg, data, tx -func (_m *DefinitionHandler) HandleDefinitionBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (definitions.HandlerResult, error) { +func (_m *Handler) HandleDefinitionBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (definitions.HandlerResult, error) { ret := _m.Called(ctx, state, msg, data, tx) var r0 definitions.HandlerResult diff --git a/mocks/definitionsmocks/sender.go b/mocks/definitionsmocks/sender.go index 68e4c88cc..060c93900 100644 --- a/mocks/definitionsmocks/sender.go +++ b/mocks/definitionsmocks/sender.go @@ -178,7 +178,7 @@ func (_m *Sender) CreateTokenPool(ctx context.Context, pool *core.TokenPoolAnnou } // Init provides a mock function with given fields: handler -func (_m *Sender) Init(handler definitions.DefinitionHandler) { +func (_m *Sender) Init(handler definitions.Handler) { _m.Called(handler) } From 5fbce076712bd2396c5e4b008947674dbd35c990 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Tue, 28 Jun 2022 10:35:16 -0400 Subject: [PATCH 16/27] Handle gateway-mode token pool definitions directly No need to create a message in this case. Signed-off-by: Andrew Richardson --- internal/definitions/handler_tokenpool.go | 3 +++ internal/definitions/sender.go | 18 +++++++++++++--- internal/definitions/sender_tokenpool.go | 21 ++++++++++++------- internal/definitions/sender_tokenpool_test.go | 6 +++--- internal/events/token_pool_created.go | 2 +- internal/events/token_pool_created_test.go | 2 +- mocks/definitionsmocks/sender.go | 21 ++++++------------- 7 files changed, 42 insertions(+), 31 deletions(-) diff --git a/internal/definitions/handler_tokenpool.go b/internal/definitions/handler_tokenpool.go index 5c49cd7bd..9482fa6e8 100644 --- a/internal/definitions/handler_tokenpool.go +++ b/internal/definitions/handler_tokenpool.go @@ -34,7 +34,10 @@ func (dh *definitionHandler) handleTokenPoolBroadcast(ctx context.Context, state pool := announce.Pool pool.Message = msg.Header.ID + return dh.handleTokenPoolDefinition(ctx, state, pool) +} +func (dh *definitionHandler) handleTokenPoolDefinition(ctx context.Context, state *core.BatchState, pool *core.TokenPool) (HandlerResult, error) { // Set an event correlator, so that if we reject then the sync-async bridge action can know // from the event (without downloading and parsing the msg) correlator := pool.ID diff --git a/internal/definitions/sender.go b/internal/definitions/sender.go index 07f5a8c2f..94a45daf9 100644 --- a/internal/definitions/sender.go +++ b/internal/definitions/sender.go @@ -39,7 +39,7 @@ type Sender interface { CreateDefinitionWithIdentity(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (msg *core.Message, err error) CreateIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) - CreateTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (msg *core.Message, err error) + DefineTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) error CreateFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) (output *core.FFI, err error) CreateContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) (output *core.ContractAPI, err error) } @@ -53,7 +53,19 @@ type definitionSender struct { identity identity.Manager data data.Manager contracts contracts.Manager - handler Handler + handler *definitionHandler +} + +// Definitions that get processed immediately will create a temporary batch state and then finalize it inline +func fakeBatch(ctx context.Context, handler func(context.Context, *core.BatchState) (HandlerResult, error)) error { + var state core.BatchState + if _, err := handler(ctx, &state); err != nil { + return err + } + if err := state.RunPreFinalize(ctx); err != nil { + return err + } + return state.RunFinalize(ctx) } func NewDefinitionSender(ctx context.Context, ns string, multiparty bool, di database.Plugin, bm broadcast.Manager, im identity.Manager, dm data.Manager, cm contracts.Manager) (Sender, error) { @@ -77,7 +89,7 @@ func (bm *definitionSender) Name() string { } func (bm *definitionSender) Init(handler Handler) { - bm.handler = handler + bm.handler = handler.(*definitionHandler) } func (bm *definitionSender) CreateDefinition(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) { diff --git a/internal/definitions/sender_tokenpool.go b/internal/definitions/sender_tokenpool.go index b75e5f577..24047568d 100644 --- a/internal/definitions/sender_tokenpool.go +++ b/internal/definitions/sender_tokenpool.go @@ -22,14 +22,19 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (bm *definitionSender) CreateTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (msg *core.Message, err error) { - if err := pool.Pool.Validate(ctx); err != nil { - return nil, err +func (bm *definitionSender) DefineTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) error { + if bm.multiparty { + if err := pool.Pool.Validate(ctx); err != nil { + return err + } + msg, err := bm.CreateDefinition(ctx, pool, core.SystemTagDefinePool, waitConfirm) + if msg != nil { + pool.Pool.Message = msg.Header.ID + } + return err } - msg, err = bm.CreateDefinition(ctx, pool, core.SystemTagDefinePool, waitConfirm) - if msg != nil { - pool.Pool.Message = msg.Header.ID - } - return msg, err + return fakeBatch(ctx, func(ctx context.Context, state *core.BatchState) (HandlerResult, error) { + return bm.handler.handleTokenPoolDefinition(ctx, state, pool.Pool) + }) } diff --git a/internal/definitions/sender_tokenpool_test.go b/internal/definitions/sender_tokenpool_test.go index e091fbbf9..d71b1c71b 100644 --- a/internal/definitions/sender_tokenpool_test.go +++ b/internal/definitions/sender_tokenpool_test.go @@ -46,13 +46,13 @@ func TestBroadcastTokenPoolInvalid(t *testing.T) { }, } - _, err := ds.CreateTokenPool(context.Background(), pool, false) + err := ds.DefineTokenPool(context.Background(), pool, false) assert.Regexp(t, "FF00140", err) mdm.AssertExpectations(t) } -func TestCreateTokenPoolOk(t *testing.T) { +func TestDefineTokenPoolOk(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() ds.multiparty = true @@ -77,7 +77,7 @@ func TestCreateTokenPoolOk(t *testing.T) { mbm.On("NewBroadcast", mock.Anything).Return(mms) mms.On("Send", context.Background()).Return(nil) - _, err := ds.CreateTokenPool(context.Background(), pool, false) + err := ds.DefineTokenPool(context.Background(), pool, false) assert.NoError(t, err) mdm.AssertExpectations(t) diff --git a/internal/events/token_pool_created.go b/internal/events/token_pool_created.go index dfa259d75..ed93ce6f2 100644 --- a/internal/events/token_pool_created.go +++ b/internal/events/token_pool_created.go @@ -195,7 +195,7 @@ func (em *eventManager) TokenPoolCreated(ti tokens.Plugin, pool *tokens.TokenPoo Pool: announcePool, } log.L(em.ctx).Infof("Announcing token pool, id=%s", announcePool.ID) - _, err = em.defsender.CreateTokenPool(em.ctx, broadcast, false) + err = em.defsender.DefineTokenPool(em.ctx, broadcast, false) } } diff --git a/internal/events/token_pool_created_test.go b/internal/events/token_pool_created_test.go index 5c006662a..8205f40c2 100644 --- a/internal/events/token_pool_created_test.go +++ b/internal/events/token_pool_created_test.go @@ -505,7 +505,7 @@ func TestTokenPoolCreatedAnnounce(t *testing.T) { mdi.On("GetTokenPoolByLocator", em.ctx, "ns1", "erc1155", "123").Return(nil, nil).Times(2) mdi.On("GetOperations", em.ctx, "ns1", mock.Anything).Return(nil, nil, fmt.Errorf("pop")).Once() mdi.On("GetOperations", em.ctx, "ns1", mock.Anything).Return(operations, nil, nil).Once() - mds.On("CreateTokenPool", em.ctx, mock.MatchedBy(func(pool *core.TokenPoolAnnouncement) bool { + mds.On("DefineTokenPool", em.ctx, mock.MatchedBy(func(pool *core.TokenPoolAnnouncement) bool { return pool.Pool.Namespace == "ns1" && pool.Pool.Name == "my-pool" && *pool.Pool.ID == *poolID }), false).Return(nil, nil) diff --git a/mocks/definitionsmocks/sender.go b/mocks/definitionsmocks/sender.go index 060c93900..24b477a55 100644 --- a/mocks/definitionsmocks/sender.go +++ b/mocks/definitionsmocks/sender.go @@ -154,27 +154,18 @@ func (_m *Sender) CreateIdentityClaim(ctx context.Context, def *core.IdentityCla return r0, r1 } -// CreateTokenPool provides a mock function with given fields: ctx, pool, waitConfirm -func (_m *Sender) CreateTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) (*core.Message, error) { +// DefineTokenPool provides a mock function with given fields: ctx, pool, waitConfirm +func (_m *Sender) DefineTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) error { ret := _m.Called(ctx, pool, waitConfirm) - var r0 *core.Message - if rf, ok := ret.Get(0).(func(context.Context, *core.TokenPoolAnnouncement, bool) *core.Message); ok { + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *core.TokenPoolAnnouncement, bool) error); ok { r0 = rf(ctx, pool, waitConfirm) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*core.Message) - } + r0 = ret.Error(0) } - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *core.TokenPoolAnnouncement, bool) error); ok { - r1 = rf(ctx, pool, waitConfirm) - } else { - r1 = ret.Error(1) - } - - return r0, r1 + return r0 } // Init provides a mock function with given fields: handler From cc3b5f3a2dd717d120bdcf7da14c872d58c807e5 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Tue, 28 Jun 2022 10:53:12 -0400 Subject: [PATCH 17/27] Handle gateway-mode contract definitions directly Signed-off-by: Andrew Richardson --- .../apiserver/route_post_new_contract_api.go | 4 +- .../route_post_new_contract_api_test.go | 6 +- .../route_post_new_contract_interface.go | 4 +- .../route_post_new_contract_interface_test.go | 6 +- internal/apiserver/route_put_contract_api.go | 5 +- .../apiserver/route_put_contract_api_test.go | 6 +- internal/definitions/handler_contracts.go | 20 +++-- internal/definitions/sender.go | 4 +- internal/definitions/sender_contracts.go | 38 ++++++---- internal/definitions/sender_contracts_test.go | 24 +++--- mocks/definitionsmocks/sender.go | 74 +++++++------------ 11 files changed, 94 insertions(+), 97 deletions(-) diff --git a/internal/apiserver/route_post_new_contract_api.go b/internal/apiserver/route_post_new_contract_api.go index 317a76ea8..5ae7496e2 100644 --- a/internal/apiserver/route_post_new_contract_api.go +++ b/internal/apiserver/route_post_new_contract_api.go @@ -41,7 +41,9 @@ var postNewContractAPI = &ffapi.Route{ CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) - return cr.or.DefinitionSender().CreateContractAPI(cr.ctx, cr.apiBaseURL, r.Input.(*core.ContractAPI), waitConfirm) + api := r.Input.(*core.ContractAPI) + err = cr.or.DefinitionSender().DefineContractAPI(cr.ctx, cr.apiBaseURL, api, waitConfirm) + return api, err }, }, } diff --git a/internal/apiserver/route_post_new_contract_api_test.go b/internal/apiserver/route_post_new_contract_api_test.go index b7fecad6d..e28729174 100644 --- a/internal/apiserver/route_post_new_contract_api_test.go +++ b/internal/apiserver/route_post_new_contract_api_test.go @@ -39,8 +39,7 @@ func TestPostNewContractAPI(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mds.On("CreateContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), false). - Return(&core.ContractAPI{}, nil) + mds.On("DefineContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), false).Return(nil) r.ServeHTTP(res, req) assert.Equal(t, 202, res.Result().StatusCode) @@ -57,8 +56,7 @@ func TestPostNewContractAPISync(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mds.On("CreateContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), true). - Return(&core.ContractAPI{}, nil) + mds.On("DefineContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), true).Return(nil) r.ServeHTTP(res, req) assert.Equal(t, 200, res.Result().StatusCode) diff --git a/internal/apiserver/route_post_new_contract_interface.go b/internal/apiserver/route_post_new_contract_interface.go index 12e3944e9..90f62d7b1 100644 --- a/internal/apiserver/route_post_new_contract_interface.go +++ b/internal/apiserver/route_post_new_contract_interface.go @@ -41,7 +41,9 @@ var postNewContractInterface = &ffapi.Route{ CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) - return cr.or.DefinitionSender().CreateFFI(cr.ctx, r.Input.(*core.FFI), waitConfirm) + ffi := r.Input.(*core.FFI) + err = cr.or.DefinitionSender().DefineFFI(cr.ctx, ffi, waitConfirm) + return ffi, err }, }, } diff --git a/internal/apiserver/route_post_new_contract_interface_test.go b/internal/apiserver/route_post_new_contract_interface_test.go index 9366064f7..3d3d680fc 100644 --- a/internal/apiserver/route_post_new_contract_interface_test.go +++ b/internal/apiserver/route_post_new_contract_interface_test.go @@ -39,8 +39,7 @@ func TestPostNewContractInterface(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mds.On("CreateFFI", mock.Anything, mock.AnythingOfType("*core.FFI"), false). - Return(&core.FFI{}, nil) + mds.On("DefineFFI", mock.Anything, mock.AnythingOfType("*core.FFI"), false).Return(nil) r.ServeHTTP(res, req) assert.Equal(t, 202, res.Result().StatusCode) @@ -57,8 +56,7 @@ func TestPostNewContractInterfaceSync(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mds.On("CreateFFI", mock.Anything, mock.AnythingOfType("*core.FFI"), true). - Return(&core.FFI{}, nil) + mds.On("DefineFFI", mock.Anything, mock.AnythingOfType("*core.FFI"), true).Return(nil) r.ServeHTTP(res, req) assert.Equal(t, 200, res.Result().StatusCode) diff --git a/internal/apiserver/route_put_contract_api.go b/internal/apiserver/route_put_contract_api.go index 7c93d6da5..537571194 100644 --- a/internal/apiserver/route_put_contract_api.go +++ b/internal/apiserver/route_put_contract_api.go @@ -46,11 +46,10 @@ var putContractAPI = &ffapi.Route{ r.SuccessStatus = syncRetcode(waitConfirm) api := r.Input.(*core.ContractAPI) api.ID, err = fftypes.ParseUUID(cr.ctx, r.PP["id"]) - var res interface{} if err == nil { - res, err = cr.or.DefinitionSender().CreateContractAPI(cr.ctx, cr.apiBaseURL, api, waitConfirm) + err = cr.or.DefinitionSender().DefineContractAPI(cr.ctx, cr.apiBaseURL, api, waitConfirm) } - return res, err + return api, err }, }, } diff --git a/internal/apiserver/route_put_contract_api_test.go b/internal/apiserver/route_put_contract_api_test.go index 3df50b305..90754491d 100644 --- a/internal/apiserver/route_put_contract_api_test.go +++ b/internal/apiserver/route_put_contract_api_test.go @@ -39,8 +39,7 @@ func TestPutContractAPI(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mds.On("CreateContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), false). - Return(&core.ContractAPI{}, nil) + mds.On("DefineContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), false).Return(nil) r.ServeHTTP(res, req) assert.Equal(t, 202, res.Result().StatusCode) @@ -57,8 +56,7 @@ func TestPutContractAPISync(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mds.On("CreateContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), true). - Return(&core.ContractAPI{}, nil) + mds.On("DefineContractAPI", mock.Anything, mock.Anything, mock.AnythingOfType("*core.ContractAPI"), true).Return(nil) r.ServeHTTP(res, req) assert.Equal(t, 200, res.Result().StatusCode) diff --git a/internal/definitions/handler_contracts.go b/internal/definitions/handler_contracts.go index 372555ea8..53affe4b6 100644 --- a/internal/definitions/handler_contracts.go +++ b/internal/definitions/handler_contracts.go @@ -76,7 +76,6 @@ func (dh *definitionHandler) persistContractAPI(ctx context.Context, api *core.C } func (dh *definitionHandler) handleFFIBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { - l := log.L(ctx) var ffi core.FFI if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &ffi); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "contract interface", msg.Header.ID) @@ -86,11 +85,16 @@ func (dh *definitionHandler) handleFFIBroadcast(ctx context.Context, state *core } ffi.Message = msg.Header.ID - if err := dh.persistFFI(ctx, &ffi); err != nil { + return dh.handleFFIDefinition(ctx, state, &ffi, tx) +} + +func (dh *definitionHandler) handleFFIDefinition(ctx context.Context, state *core.BatchState, ffi *core.FFI, tx *fftypes.UUID) (HandlerResult, error) { + l := log.L(ctx) + if err := dh.persistFFI(ctx, ffi); err != nil { return HandlerResult{Action: ActionRetry}, err } - l.Infof("Contract interface created id=%s author=%s", ffi.ID, msg.Header.Author) + l.Infof("Contract interface created id=%s", ffi.ID) state.AddFinalize(func(ctx context.Context) error { event := core.NewEvent(core.EventTypeContractInterfaceConfirmed, ffi.Namespace, ffi.ID, tx, ffi.Topic()) return dh.database.InsertEvent(ctx, event) @@ -99,7 +103,6 @@ func (dh *definitionHandler) handleFFIBroadcast(ctx context.Context, state *core } func (dh *definitionHandler) handleContractAPIBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) { - l := log.L(ctx) var api core.ContractAPI if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &api); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "contract API", msg.Header.ID) @@ -109,14 +112,19 @@ func (dh *definitionHandler) handleContractAPIBroadcast(ctx context.Context, sta } api.Message = msg.Header.ID - if retry, err := dh.persistContractAPI(ctx, &api); err != nil { + return dh.handleContractAPIDefinition(ctx, state, &api, tx) +} + +func (dh *definitionHandler) handleContractAPIDefinition(ctx context.Context, state *core.BatchState, api *core.ContractAPI, tx *fftypes.UUID) (HandlerResult, error) { + l := log.L(ctx) + if retry, err := dh.persistContractAPI(ctx, api); err != nil { if retry { return HandlerResult{Action: ActionRetry}, err } return HandlerResult{Action: ActionReject}, err } - l.Infof("Contract API created id=%s author=%s", api.ID, msg.Header.Author) + l.Infof("Contract API created id=%s", api.ID) state.AddFinalize(func(ctx context.Context) error { event := core.NewEvent(core.EventTypeContractAPIConfirmed, api.Namespace, api.ID, tx, core.SystemTopicDefinitions) return dh.database.InsertEvent(ctx, event) diff --git a/internal/definitions/sender.go b/internal/definitions/sender.go index 94a45daf9..f8de96422 100644 --- a/internal/definitions/sender.go +++ b/internal/definitions/sender.go @@ -40,8 +40,8 @@ type Sender interface { CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (msg *core.Message, err error) CreateIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) DefineTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) error - CreateFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) (output *core.FFI, err error) - CreateContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) (output *core.ContractAPI, err error) + DefineFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) error + DefineContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) error } type definitionSender struct { diff --git a/internal/definitions/sender_contracts.go b/internal/definitions/sender_contracts.go index c60132a8e..8f83df19b 100644 --- a/internal/definitions/sender_contracts.go +++ b/internal/definitions/sender_contracts.go @@ -23,7 +23,7 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -func (bm *definitionSender) CreateFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) (output *core.FFI, err error) { +func (bm *definitionSender) DefineFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) error { ffi.ID = fftypes.NewUUID() ffi.Namespace = bm.namespace for _, method := range ffi.Methods { @@ -34,29 +34,39 @@ func (bm *definitionSender) CreateFFI(ctx context.Context, ffi *core.FFI, waitCo } if err := bm.contracts.ResolveFFI(ctx, ffi); err != nil { - return nil, err + return err } - msg, err := bm.CreateDefinition(ctx, ffi, core.SystemTagDefineFFI, waitConfirm) - if err != nil { - return nil, err + if bm.multiparty { + msg, err := bm.CreateDefinition(ctx, ffi, core.SystemTagDefineFFI, waitConfirm) + if msg != nil { + ffi.Message = msg.Header.ID + } + return err } - ffi.Message = msg.Header.ID - return ffi, nil + + return fakeBatch(ctx, func(ctx context.Context, state *core.BatchState) (HandlerResult, error) { + return bm.handler.handleFFIDefinition(ctx, state, ffi, nil) + }) } -func (bm *definitionSender) CreateContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) (output *core.ContractAPI, err error) { +func (bm *definitionSender) DefineContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) error { api.ID = fftypes.NewUUID() api.Namespace = bm.namespace if err := bm.contracts.ResolveContractAPI(ctx, httpServerURL, api); err != nil { - return nil, err + return err } - msg, err := bm.CreateDefinition(ctx, api, core.SystemTagDefineContractAPI, waitConfirm) - if err != nil { - return nil, err + if bm.multiparty { + msg, err := bm.CreateDefinition(ctx, api, core.SystemTagDefineContractAPI, waitConfirm) + if msg != nil { + api.Message = msg.Header.ID + } + return err } - api.Message = msg.Header.ID - return api, nil + + return fakeBatch(ctx, func(ctx context.Context, state *core.BatchState) (HandlerResult, error) { + return bm.handler.handleContractAPIDefinition(ctx, state, api, nil) + }) } diff --git a/internal/definitions/sender_contracts_test.go b/internal/definitions/sender_contracts_test.go index db35e7e8d..474cd4946 100644 --- a/internal/definitions/sender_contracts_test.go +++ b/internal/definitions/sender_contracts_test.go @@ -30,7 +30,7 @@ import ( "github.com/stretchr/testify/mock" ) -func TestCreateFFIResolveFail(t *testing.T) { +func TestDefineFFIResolveFail(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() ds.multiparty = true @@ -43,13 +43,13 @@ func TestCreateFFIResolveFail(t *testing.T) { mcm := ds.contracts.(*contractmocks.Manager) mcm.On("ResolveFFI", context.Background(), ffi).Return(fmt.Errorf("pop")) - _, err := ds.CreateFFI(context.Background(), ffi, false) + err := ds.DefineFFI(context.Background(), ffi, false) assert.EqualError(t, err, "pop") mcm.AssertExpectations(t) } -func TestCreateFFIFail(t *testing.T) { +func TestDefineFFIFail(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() ds.multiparty = true @@ -62,14 +62,14 @@ func TestCreateFFIFail(t *testing.T) { mim := ds.identity.(*identitymanagermocks.Manager) mim.On("ResolveInputSigningIdentity", context.Background(), mock.Anything).Return(fmt.Errorf("pop")) - _, err := ds.CreateFFI(context.Background(), ffi, false) + err := ds.DefineFFI(context.Background(), ffi, false) assert.EqualError(t, err, "pop") mcm.AssertExpectations(t) mim.AssertExpectations(t) } -func TestCreateFFIOk(t *testing.T) { +func TestDefineFFIOk(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() ds.multiparty = true @@ -87,7 +87,7 @@ func TestCreateFFIOk(t *testing.T) { mbm.On("NewBroadcast", mock.Anything).Return(mms) mms.On("Send", context.Background()).Return(nil) - _, err := ds.CreateFFI(context.Background(), ffi, false) + err := ds.DefineFFI(context.Background(), ffi, false) assert.NoError(t, err) mcm.AssertExpectations(t) @@ -96,7 +96,7 @@ func TestCreateFFIOk(t *testing.T) { mms.AssertExpectations(t) } -func TestCreateContractAPIResolveFail(t *testing.T) { +func TestDefineContractAPIResolveFail(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() ds.multiparty = true @@ -107,13 +107,13 @@ func TestCreateContractAPIResolveFail(t *testing.T) { mcm := ds.contracts.(*contractmocks.Manager) mcm.On("ResolveContractAPI", context.Background(), url, api).Return(fmt.Errorf("pop")) - _, err := ds.CreateContractAPI(context.Background(), url, api, false) + err := ds.DefineContractAPI(context.Background(), url, api, false) assert.EqualError(t, err, "pop") mcm.AssertExpectations(t) } -func TestCreateContractAPIFail(t *testing.T) { +func TestDefineContractAPIFail(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() ds.multiparty = true @@ -127,14 +127,14 @@ func TestCreateContractAPIFail(t *testing.T) { mim := ds.identity.(*identitymanagermocks.Manager) mim.On("ResolveInputSigningIdentity", context.Background(), mock.Anything).Return(fmt.Errorf("pop")) - _, err := ds.CreateContractAPI(context.Background(), url, api, false) + err := ds.DefineContractAPI(context.Background(), url, api, false) assert.EqualError(t, err, "pop") mcm.AssertExpectations(t) mim.AssertExpectations(t) } -func TestCreateContractAPIOk(t *testing.T) { +func TestDefineContractAPIOk(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() ds.multiparty = true @@ -153,7 +153,7 @@ func TestCreateContractAPIOk(t *testing.T) { mbm.On("NewBroadcast", mock.Anything).Return(mms) mms.On("Send", context.Background()).Return(nil) - _, err := ds.CreateContractAPI(context.Background(), url, api, false) + err := ds.DefineContractAPI(context.Background(), url, api, false) assert.NoError(t, err) mcm.AssertExpectations(t) diff --git a/mocks/definitionsmocks/sender.go b/mocks/definitionsmocks/sender.go index 24b477a55..41b893fe3 100644 --- a/mocks/definitionsmocks/sender.go +++ b/mocks/definitionsmocks/sender.go @@ -16,29 +16,6 @@ type Sender struct { mock.Mock } -// CreateContractAPI provides a mock function with given fields: ctx, httpServerURL, api, waitConfirm -func (_m *Sender) CreateContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) (*core.ContractAPI, error) { - ret := _m.Called(ctx, httpServerURL, api, waitConfirm) - - var r0 *core.ContractAPI - if rf, ok := ret.Get(0).(func(context.Context, string, *core.ContractAPI, bool) *core.ContractAPI); ok { - r0 = rf(ctx, httpServerURL, api, waitConfirm) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*core.ContractAPI) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, string, *core.ContractAPI, bool) error); ok { - r1 = rf(ctx, httpServerURL, api, waitConfirm) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // CreateDatatype provides a mock function with given fields: ctx, datatype, waitConfirm func (_m *Sender) CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (*core.Message, error) { ret := _m.Called(ctx, datatype, waitConfirm) @@ -108,29 +85,6 @@ func (_m *Sender) CreateDefinitionWithIdentity(ctx context.Context, def core.Def return r0, r1 } -// CreateFFI provides a mock function with given fields: ctx, ffi, waitConfirm -func (_m *Sender) CreateFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) (*core.FFI, error) { - ret := _m.Called(ctx, ffi, waitConfirm) - - var r0 *core.FFI - if rf, ok := ret.Get(0).(func(context.Context, *core.FFI, bool) *core.FFI); ok { - r0 = rf(ctx, ffi, waitConfirm) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*core.FFI) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *core.FFI, bool) error); ok { - r1 = rf(ctx, ffi, waitConfirm) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // CreateIdentityClaim provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm func (_m *Sender) CreateIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { ret := _m.Called(ctx, def, signingIdentity, tag, waitConfirm) @@ -154,6 +108,34 @@ func (_m *Sender) CreateIdentityClaim(ctx context.Context, def *core.IdentityCla return r0, r1 } +// DefineContractAPI provides a mock function with given fields: ctx, httpServerURL, api, waitConfirm +func (_m *Sender) DefineContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) error { + ret := _m.Called(ctx, httpServerURL, api, waitConfirm) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, *core.ContractAPI, bool) error); ok { + r0 = rf(ctx, httpServerURL, api, waitConfirm) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DefineFFI provides a mock function with given fields: ctx, ffi, waitConfirm +func (_m *Sender) DefineFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) error { + ret := _m.Called(ctx, ffi, waitConfirm) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *core.FFI, bool) error); ok { + r0 = rf(ctx, ffi, waitConfirm) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // DefineTokenPool provides a mock function with given fields: ctx, pool, waitConfirm func (_m *Sender) DefineTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) error { ret := _m.Called(ctx, pool, waitConfirm) From 0f22e531fad347dfd2ffb8710dae0cad3cb11f1a Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Tue, 28 Jun 2022 10:56:53 -0400 Subject: [PATCH 18/27] Disable datatype definitions in gateway mode Signed-off-by: Andrew Richardson --- internal/apiserver/route_post_new_datatype.go | 2 +- .../apiserver/route_post_new_datatype_test.go | 6 +-- internal/definitions/sender.go | 2 +- internal/definitions/sender_datatype.go | 22 +++++++---- internal/definitions/sender_datatype_test.go | 12 +++--- mocks/definitionsmocks/sender.go | 37 +++++++------------ 6 files changed, 38 insertions(+), 43 deletions(-) diff --git a/internal/apiserver/route_post_new_datatype.go b/internal/apiserver/route_post_new_datatype.go index 7cd10e04d..8a683ae1e 100644 --- a/internal/apiserver/route_post_new_datatype.go +++ b/internal/apiserver/route_post_new_datatype.go @@ -45,7 +45,7 @@ var postNewDatatype = &ffapi.Route{ CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) - _, err = cr.or.DefinitionSender().CreateDatatype(cr.ctx, r.Input.(*core.Datatype), waitConfirm) + err = cr.or.DefinitionSender().DefineDatatype(cr.ctx, r.Input.(*core.Datatype), waitConfirm) return r.Input, err }, }, diff --git a/internal/apiserver/route_post_new_datatype_test.go b/internal/apiserver/route_post_new_datatype_test.go index 7df163f3c..c8753f2ff 100644 --- a/internal/apiserver/route_post_new_datatype_test.go +++ b/internal/apiserver/route_post_new_datatype_test.go @@ -41,8 +41,7 @@ func TestPostNewDatatypes(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mds.On("CreateDatatype", mock.Anything, mock.AnythingOfType("*core.Datatype"), false). - Return(&core.Message{}, nil) + mds.On("DefineDatatype", mock.Anything, mock.AnythingOfType("*core.Datatype"), false).Return(nil) r.ServeHTTP(res, req) assert.Equal(t, 202, res.Result().StatusCode) @@ -60,8 +59,7 @@ func TestPostNewDatatypesSync(t *testing.T) { req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() - mds.On("CreateDatatype", mock.Anything, mock.AnythingOfType("*core.Datatype"), true). - Return(&core.Message{}, nil) + mds.On("DefineDatatype", mock.Anything, mock.AnythingOfType("*core.Datatype"), true).Return(nil) r.ServeHTTP(res, req) assert.Equal(t, 200, res.Result().StatusCode) diff --git a/internal/definitions/sender.go b/internal/definitions/sender.go index f8de96422..e66a1d9ca 100644 --- a/internal/definitions/sender.go +++ b/internal/definitions/sender.go @@ -37,7 +37,7 @@ type Sender interface { Init(handler Handler) CreateDefinition(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) CreateDefinitionWithIdentity(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) - CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (msg *core.Message, err error) + DefineDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) error CreateIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) DefineTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) error DefineFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) error diff --git a/internal/definitions/sender_datatype.go b/internal/definitions/sender_datatype.go index 79182c69a..9962bdffe 100644 --- a/internal/definitions/sender_datatype.go +++ b/internal/definitions/sender_datatype.go @@ -20,11 +20,12 @@ import ( "context" "github.com/hyperledger/firefly-common/pkg/fftypes" + "github.com/hyperledger/firefly-common/pkg/i18n" + "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/pkg/core" ) -func (bm *definitionSender) CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (*core.Message, error) { - +func (bm *definitionSender) DefineDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) error { // Validate the input data definition data datatype.ID = fftypes.NewUUID() datatype.Created = fftypes.Now() @@ -33,17 +34,22 @@ func (bm *definitionSender) CreateDatatype(ctx context.Context, datatype *core.D datatype.Validator = core.ValidatorTypeJSON } if err := datatype.Validate(ctx, false); err != nil { - return nil, err + return err } datatype.Hash = datatype.Value.Hash() // Verify the data type is now all valid, before we broadcast it if err := bm.data.CheckDatatype(ctx, datatype); err != nil { - return nil, err + return err } - msg, err := bm.CreateDefinition(ctx, datatype, core.SystemTagDefineDatatype, waitConfirm) - if msg != nil { - datatype.Message = msg.Header.ID + + if bm.multiparty { + msg, err := bm.CreateDefinition(ctx, datatype, core.SystemTagDefineDatatype, waitConfirm) + if msg != nil { + datatype.Message = msg.Header.ID + } + return err } - return msg, err + + return i18n.NewError(ctx, coremsgs.MsgActionNotSupported) } diff --git a/internal/definitions/sender_datatype_test.go b/internal/definitions/sender_datatype_test.go index 214aa51d5..5d1393a94 100644 --- a/internal/definitions/sender_datatype_test.go +++ b/internal/definitions/sender_datatype_test.go @@ -31,11 +31,11 @@ import ( "github.com/stretchr/testify/mock" ) -func TestCreateDatatypeBadType(t *testing.T) { +func TestDefineDatatypeBadType(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() ds.multiparty = true - _, err := ds.CreateDatatype(context.Background(), &core.Datatype{ + err := ds.DefineDatatype(context.Background(), &core.Datatype{ Validator: core.ValidatorType("wrong"), }, false) assert.Regexp(t, "FF00111.*validator", err) @@ -49,7 +49,7 @@ func TestBroadcastDatatypeBadValue(t *testing.T) { mdm.On("CheckDatatype", mock.Anything, mock.Anything).Return(nil) mim := ds.identity.(*identitymanagermocks.Manager) mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(nil) - _, err := ds.CreateDatatype(context.Background(), &core.Datatype{ + err := ds.DefineDatatype(context.Background(), &core.Datatype{ Namespace: "ns1", Name: "ent1", Version: "0.0.1", @@ -61,7 +61,7 @@ func TestBroadcastDatatypeBadValue(t *testing.T) { mim.AssertExpectations(t) } -func TestCreateDatatypeInvalid(t *testing.T) { +func TestDefineDatatypeInvalid(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() ds.multiparty = true @@ -71,7 +71,7 @@ func TestCreateDatatypeInvalid(t *testing.T) { mim.On("ResolveInputIdentity", mock.Anything, mock.Anything).Return(nil) mdm.On("CheckDatatype", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - _, err := ds.CreateDatatype(context.Background(), &core.Datatype{ + err := ds.DefineDatatype(context.Background(), &core.Datatype{ Namespace: "ns1", Name: "ent1", Version: "0.0.1", @@ -96,7 +96,7 @@ func TestBroadcastOk(t *testing.T) { mbm.On("NewBroadcast", mock.Anything).Return(mms) mms.On("Send", context.Background()).Return(nil) - _, err := ds.CreateDatatype(context.Background(), &core.Datatype{ + err := ds.DefineDatatype(context.Background(), &core.Datatype{ Namespace: "ns1", Name: "ent1", Version: "0.0.1", diff --git a/mocks/definitionsmocks/sender.go b/mocks/definitionsmocks/sender.go index 41b893fe3..841e3462a 100644 --- a/mocks/definitionsmocks/sender.go +++ b/mocks/definitionsmocks/sender.go @@ -16,29 +16,6 @@ type Sender struct { mock.Mock } -// CreateDatatype provides a mock function with given fields: ctx, datatype, waitConfirm -func (_m *Sender) CreateDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) (*core.Message, error) { - ret := _m.Called(ctx, datatype, waitConfirm) - - var r0 *core.Message - if rf, ok := ret.Get(0).(func(context.Context, *core.Datatype, bool) *core.Message); ok { - r0 = rf(ctx, datatype, waitConfirm) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*core.Message) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *core.Datatype, bool) error); ok { - r1 = rf(ctx, datatype, waitConfirm) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // CreateDefinition provides a mock function with given fields: ctx, def, tag, waitConfirm func (_m *Sender) CreateDefinition(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (*core.Message, error) { ret := _m.Called(ctx, def, tag, waitConfirm) @@ -122,6 +99,20 @@ func (_m *Sender) DefineContractAPI(ctx context.Context, httpServerURL string, a return r0 } +// DefineDatatype provides a mock function with given fields: ctx, datatype, waitConfirm +func (_m *Sender) DefineDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) error { + ret := _m.Called(ctx, datatype, waitConfirm) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *core.Datatype, bool) error); ok { + r0 = rf(ctx, datatype, waitConfirm) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // DefineFFI provides a mock function with given fields: ctx, ffi, waitConfirm func (_m *Sender) DefineFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) error { ret := _m.Called(ctx, ffi, waitConfirm) From 5779bc4167ca8474b8b8021798af7193551a775a Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Tue, 28 Jun 2022 11:07:24 -0400 Subject: [PATCH 19/27] Remove unused CreateDefinition method from public interface Signed-off-by: Andrew Richardson --- internal/definitions/sender.go | 3 +-- internal/definitions/sender_contracts.go | 4 ++-- internal/definitions/sender_datatype.go | 2 +- internal/definitions/sender_test.go | 4 ++-- internal/definitions/sender_tokenpool.go | 2 +- mocks/definitionsmocks/sender.go | 23 ----------------------- 6 files changed, 7 insertions(+), 31 deletions(-) diff --git a/internal/definitions/sender.go b/internal/definitions/sender.go index e66a1d9ca..52312a394 100644 --- a/internal/definitions/sender.go +++ b/internal/definitions/sender.go @@ -35,7 +35,6 @@ type Sender interface { core.Named Init(handler Handler) - CreateDefinition(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) CreateDefinitionWithIdentity(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) DefineDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) error CreateIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) @@ -92,7 +91,7 @@ func (bm *definitionSender) Init(handler Handler) { bm.handler = handler.(*definitionHandler) } -func (bm *definitionSender) CreateDefinition(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) { +func (bm *definitionSender) createDefinitionDefault(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) { return bm.CreateDefinitionWithIdentity(ctx, def, &core.SignerRef{ /* resolve to node default */ }, tag, waitConfirm) } diff --git a/internal/definitions/sender_contracts.go b/internal/definitions/sender_contracts.go index 8f83df19b..8f9b907e8 100644 --- a/internal/definitions/sender_contracts.go +++ b/internal/definitions/sender_contracts.go @@ -38,7 +38,7 @@ func (bm *definitionSender) DefineFFI(ctx context.Context, ffi *core.FFI, waitCo } if bm.multiparty { - msg, err := bm.CreateDefinition(ctx, ffi, core.SystemTagDefineFFI, waitConfirm) + msg, err := bm.createDefinitionDefault(ctx, ffi, core.SystemTagDefineFFI, waitConfirm) if msg != nil { ffi.Message = msg.Header.ID } @@ -59,7 +59,7 @@ func (bm *definitionSender) DefineContractAPI(ctx context.Context, httpServerURL } if bm.multiparty { - msg, err := bm.CreateDefinition(ctx, api, core.SystemTagDefineContractAPI, waitConfirm) + msg, err := bm.createDefinitionDefault(ctx, api, core.SystemTagDefineContractAPI, waitConfirm) if msg != nil { api.Message = msg.Header.ID } diff --git a/internal/definitions/sender_datatype.go b/internal/definitions/sender_datatype.go index 9962bdffe..c198416e6 100644 --- a/internal/definitions/sender_datatype.go +++ b/internal/definitions/sender_datatype.go @@ -44,7 +44,7 @@ func (bm *definitionSender) DefineDatatype(ctx context.Context, datatype *core.D } if bm.multiparty { - msg, err := bm.CreateDefinition(ctx, datatype, core.SystemTagDefineDatatype, waitConfirm) + msg, err := bm.createDefinitionDefault(ctx, datatype, core.SystemTagDefineDatatype, waitConfirm) if msg != nil { datatype.Message = msg.Header.ID } diff --git a/internal/definitions/sender_test.go b/internal/definitions/sender_test.go index 4142689ad..b55395eac 100644 --- a/internal/definitions/sender_test.go +++ b/internal/definitions/sender_test.go @@ -70,7 +70,7 @@ func TestCreateDefinitionConfirm(t *testing.T) { mms.On("SendAndWait", mock.Anything).Return(nil) ds.multiparty = true - _, err := ds.CreateDefinition(ds.ctx, &core.Namespace{}, core.SystemTagDefineNamespace, true) + _, err := ds.createDefinitionDefault(ds.ctx, &core.Namespace{}, core.SystemTagDefineNamespace, true) assert.NoError(t, err) mim.AssertExpectations(t) @@ -136,7 +136,7 @@ func TestCreateDatatypeDefinitionAsNodeConfirm(t *testing.T) { ds.multiparty = true - _, err := ds.CreateDefinition(ds.ctx, &core.Datatype{}, core.SystemTagDefineNamespace, true) + _, err := ds.createDefinitionDefault(ds.ctx, &core.Datatype{}, core.SystemTagDefineNamespace, true) assert.NoError(t, err) mim.AssertExpectations(t) diff --git a/internal/definitions/sender_tokenpool.go b/internal/definitions/sender_tokenpool.go index 24047568d..40041ed52 100644 --- a/internal/definitions/sender_tokenpool.go +++ b/internal/definitions/sender_tokenpool.go @@ -27,7 +27,7 @@ func (bm *definitionSender) DefineTokenPool(ctx context.Context, pool *core.Toke if err := pool.Pool.Validate(ctx); err != nil { return err } - msg, err := bm.CreateDefinition(ctx, pool, core.SystemTagDefinePool, waitConfirm) + msg, err := bm.createDefinitionDefault(ctx, pool, core.SystemTagDefinePool, waitConfirm) if msg != nil { pool.Pool.Message = msg.Header.ID } diff --git a/mocks/definitionsmocks/sender.go b/mocks/definitionsmocks/sender.go index 841e3462a..25a5b66de 100644 --- a/mocks/definitionsmocks/sender.go +++ b/mocks/definitionsmocks/sender.go @@ -16,29 +16,6 @@ type Sender struct { mock.Mock } -// CreateDefinition provides a mock function with given fields: ctx, def, tag, waitConfirm -func (_m *Sender) CreateDefinition(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (*core.Message, error) { - ret := _m.Called(ctx, def, tag, waitConfirm) - - var r0 *core.Message - if rf, ok := ret.Get(0).(func(context.Context, core.Definition, string, bool) *core.Message); ok { - r0 = rf(ctx, def, tag, waitConfirm) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*core.Message) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, core.Definition, string, bool) error); ok { - r1 = rf(ctx, def, tag, waitConfirm) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // CreateDefinitionWithIdentity provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm func (_m *Sender) CreateDefinitionWithIdentity(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { ret := _m.Called(ctx, def, signingIdentity, tag, waitConfirm) From 3f77c04faad0c9a8bac5eeaa0bf619ba7145dc5d Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Tue, 28 Jun 2022 12:02:46 -0400 Subject: [PATCH 20/27] Handle gateway-mode identity definitions directly Signed-off-by: Andrew Richardson --- .../definitions/handler_identity_claim.go | 62 ++++++++---- .../handler_identity_verification.go | 3 +- internal/definitions/handler_network_node.go | 2 +- internal/definitions/handler_network_org.go | 2 +- internal/definitions/sender.go | 22 +---- internal/definitions/sender_identity.go | 63 ++++++++++++ internal/definitions/sender_test.go | 12 ++- internal/identity/identitymanager.go | 3 - internal/identity/identitymanager_test.go | 17 ---- internal/networkmap/register_identity.go | 69 +++++-------- internal/networkmap/register_identity_test.go | 97 +------------------ internal/networkmap/register_node_test.go | 8 +- internal/networkmap/register_org_test.go | 8 +- internal/networkmap/update_identity.go | 14 ++- internal/networkmap/update_identity_test.go | 4 +- mocks/definitionsmocks/sender.go | 41 +++----- 16 files changed, 183 insertions(+), 244 deletions(-) create mode 100644 internal/definitions/sender_identity.go diff --git a/internal/definitions/handler_identity_claim.go b/internal/definitions/handler_identity_claim.go index 4940850c7..458439c1b 100644 --- a/internal/definitions/handler_identity_claim.go +++ b/internal/definitions/handler_identity_claim.go @@ -28,18 +28,38 @@ import ( "github.com/hyperledger/firefly/pkg/database" ) -func (dh *definitionHandler) handleIdentityClaimBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, verificationID *fftypes.UUID) (HandlerResult, error) { +type identityMsgInfo struct { + core.SignerRef + claimMsg struct { + ID *fftypes.UUID + Hash *fftypes.Bytes32 + } + verifyMsg struct { + ID *fftypes.UUID + } +} + +func buildIdentityMsgInfo(msg *core.Message, verifyMsgID *fftypes.UUID) *identityMsgInfo { + info := &identityMsgInfo{} + info.claimMsg.ID = msg.Header.ID + info.claimMsg.Hash = msg.Hash + info.verifyMsg.ID = verifyMsgID + info.SignerRef = msg.Header.SignerRef + return info +} + +func (dh *definitionHandler) handleIdentityClaimBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, verifyMsgID *fftypes.UUID) (HandlerResult, error) { var claim core.IdentityClaim if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &claim); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "identity claim", msg.Header.ID) } - return dh.handleIdentityClaim(ctx, state, msg, &claim, verificationID) + return dh.handleIdentityClaim(ctx, state, buildIdentityMsgInfo(msg, verifyMsgID), &claim) } -func (dh *definitionHandler) verifyClaimSignature(ctx context.Context, msg *core.Message, identity *core.Identity, parent *core.Identity) error { - author := msg.Header.Author +func (dh *definitionHandler) verifyClaimSignature(ctx context.Context, msg *identityMsgInfo, identity *core.Identity, parent *core.Identity) error { + author := msg.Author if author == "" { - return i18n.NewError(ctx, coremsgs.MsgDefRejectedAuthorBlank, "identity claim", msg.Header.ID) + return i18n.NewError(ctx, coremsgs.MsgDefRejectedAuthorBlank, "identity claim", msg.claimMsg.ID) } var expectedSigner *core.Identity @@ -54,13 +74,13 @@ func (dh *definitionHandler) verifyClaimSignature(ctx context.Context, msg *core valid := author == expectedSigner.DID || (expectedSigner.Type == core.IdentityTypeOrg && author == fmt.Sprintf("%s%s", core.FireFlyOrgDIDPrefix, expectedSigner.ID)) if !valid { - log.L(ctx).Errorf("unable to process identity claim %s - signature mismatch type=%s author=%s expected=%s", msg.Header.ID, identity.Type, author, expectedSigner.DID) - return i18n.NewError(ctx, coremsgs.MsgDefRejectedSignatureMismatch, "identity claim", msg.Header.ID) + log.L(ctx).Errorf("unable to process identity claim %s - signature mismatch type=%s author=%s expected=%s", msg.claimMsg.ID, identity.Type, author, expectedSigner.DID) + return i18n.NewError(ctx, coremsgs.MsgDefRejectedSignatureMismatch, "identity claim", msg.claimMsg.ID) } return nil } -func (dh *definitionHandler) getClaimVerifier(msg *core.Message, identity *core.Identity) *core.Verifier { +func (dh *definitionHandler) getClaimVerifier(msg *identityMsgInfo, identity *core.Identity) *core.Verifier { verifier := &core.Verifier{ Identity: identity.ID, Namespace: identity.Namespace, @@ -71,13 +91,13 @@ func (dh *definitionHandler) getClaimVerifier(msg *core.Message, identity *core. verifier.VerifierRef.Value = identity.Profile.GetString("id") default: verifier.VerifierRef.Type = dh.blockchain.VerifierType() - verifier.VerifierRef.Value = msg.Header.Key + verifier.VerifierRef.Value = msg.Key } verifier.Seal() return verifier } -func (dh *definitionHandler) confirmVerificationForClaim(ctx context.Context, state *core.BatchState, msg *core.Message, identity, parent *core.Identity) (*fftypes.UUID, error) { +func (dh *definitionHandler) confirmVerificationForClaim(ctx context.Context, state *core.BatchState, msg *identityMsgInfo, identity, parent *core.Identity) (*fftypes.UUID, error) { // Query for messages on the topic for this DID, signed by the right identity idTopic := identity.Topic() fb := database.MessageQueryFactory.NewFilter(ctx) @@ -111,22 +131,22 @@ func (dh *definitionHandler) confirmVerificationForClaim(ctx context.Context, st var verificationHash *fftypes.Bytes32 if foundAll { var verification core.IdentityVerification - if !dh.getSystemBroadcastPayload(ctx, msg, data, &verification) { + if !dh.getSystemBroadcastPayload(ctx, candidate, data, &verification) { return nil, nil } identityMatches = verification.Identity.Equals(ctx, &identity.IdentityBase) verificationID = verification.Claim.ID verificationHash = verification.Claim.Hash - if identityMatches && msg.Header.ID.Equals(verificationID) && msg.Hash.Equals(verificationHash) { + if identityMatches && msg.claimMsg.ID.Equals(verificationID) && msg.claimMsg.Hash.Equals(verificationHash) { return candidate.Header.ID, nil } } - log.L(ctx).Warnf("Skipping invalid potential verification '%s' for identity claimID='%s' claimHash=%s: foundData=%t identityMatch=%t id=%s hash=%s", candidate.Header.ID, msg.Header.ID, msg.Hash, foundAll, identityMatches, verificationID, verificationHash) + log.L(ctx).Warnf("Skipping invalid potential verification '%s' for identity claimID='%s' claimHash=%s: foundData=%t identityMatch=%t id=%s hash=%s", candidate.Header.ID, msg.claimMsg.ID, msg.claimMsg.Hash, foundAll, identityMatches, verificationID, verificationHash) } return nil, nil } -func (dh *definitionHandler) handleIdentityClaim(ctx context.Context, state *core.BatchState, msg *core.Message, identityClaim *core.IdentityClaim, verificationID *fftypes.UUID) (HandlerResult, error) { +func (dh *definitionHandler) handleIdentityClaim(ctx context.Context, state *core.BatchState, msg *identityMsgInfo, identityClaim *core.IdentityClaim) (HandlerResult, error) { l := log.L(ctx) identity := identityClaim.Identity @@ -138,7 +158,7 @@ func (dh *definitionHandler) handleIdentityClaim(ctx context.Context, state *cor // We treat this as a park - because we don't know if the parent identity // will be processed after this message and generate a rewind. // They are on separate topics, so there is not ordering assurance between the two messages. - l.Infof("Unable to process identity claim (parked) %s: %s", msg.Header.ID, err) + l.Infof("Unable to process identity claim (parked) %s: %s", msg.claimMsg.ID, err) return HandlerResult{Action: ActionWait}, nil } @@ -177,21 +197,21 @@ func (dh *definitionHandler) handleIdentityClaim(ctx context.Context, state *cor if dh.multiparty && parent != nil && identity.Type != core.IdentityTypeNode { // The verification might be passed into this function, if we confirm the verification second, // or we might have to hunt for it, if we confirm the verification first. - if verificationID == nil { + if msg.verifyMsg.ID == nil { // Search for a corresponding verification message on the same topic - verificationID, err = dh.confirmVerificationForClaim(ctx, state, msg, identity, parent) + msg.verifyMsg.ID, err = dh.confirmVerificationForClaim(ctx, state, msg, identity, parent) if err != nil { return HandlerResult{Action: ActionRetry}, err // retry database errors } } - if verificationID == nil { + if msg.verifyMsg.ID == nil { // Ok, we still confirm the message as it's valid, and we do not want to block the context. // But we do NOT go on to create the identity - we will be called back - log.L(ctx).Infof("Identity %s (%s) awaiting verification claim='%s'", identity.DID, identity.ID, msg.Header.ID) + log.L(ctx).Infof("Identity %s (%s) awaiting verification claim='%s'", identity.DID, identity.ID, msg.claimMsg.ID) return HandlerResult{Action: ActionConfirm}, nil } - log.L(ctx).Infof("Identity %s (%s) verified claim='%s' verification='%s'", identity.DID, identity.ID, msg.Header.ID, verificationID) - identity.Messages.Verification = verificationID + log.L(ctx).Infof("Identity %s (%s) verified claim='%s' verification='%s'", identity.DID, identity.ID, msg.claimMsg.ID, msg.verifyMsg.ID) + identity.Messages.Verification = msg.verifyMsg.ID } if existingVerifier == nil { diff --git a/internal/definitions/handler_identity_verification.go b/internal/definitions/handler_identity_verification.go index 013ebd935..14b5e6549 100644 --- a/internal/definitions/handler_identity_verification.go +++ b/internal/definitions/handler_identity_verification.go @@ -48,13 +48,12 @@ func (dh *definitionHandler) handleIdentityVerificationBroadcast(ctx context.Con } // At this point, this is a valid verification, but we don't know if the claim has arrived. - // It might be being processed in the same pin batch as us - so we can't - // See if the message has already arrived, if so we need to queue a rewind to it claimMsg, err := dh.database.GetMessageByID(ctx, dh.namespace, verification.Claim.ID) if err != nil { return HandlerResult{Action: ActionRetry}, err } + // See if the message was processed earlier in this same batch if claimMsg == nil || claimMsg.State != core.MessageStateConfirmed { claimMsg = state.PendingConfirms[*verification.Claim.ID] } diff --git a/internal/definitions/handler_network_node.go b/internal/definitions/handler_network_node.go index eb73bc377..d204d6421 100644 --- a/internal/definitions/handler_network_node.go +++ b/internal/definitions/handler_network_node.go @@ -41,6 +41,6 @@ func (dh *definitionHandler) handleDeprecatedNodeBroadcast(ctx context.Context, return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedIdentityNotFound, "node", nodeOld.ID, nodeOld.Owner) } - return dh.handleIdentityClaim(ctx, state, msg, nodeOld.AddMigratedParent(owner.ID), nil) + return dh.handleIdentityClaim(ctx, state, buildIdentityMsgInfo(msg, nil), nodeOld.AddMigratedParent(owner.ID)) } diff --git a/internal/definitions/handler_network_org.go b/internal/definitions/handler_network_org.go index 20bcfd396..ecfcc2b2e 100644 --- a/internal/definitions/handler_network_org.go +++ b/internal/definitions/handler_network_org.go @@ -32,6 +32,6 @@ func (dh *definitionHandler) handleDeprecatedOrganizationBroadcast(ctx context.C return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "org", msg.Header.ID) } - return dh.handleIdentityClaim(ctx, state, msg, orgOld.Migrated(), nil) + return dh.handleIdentityClaim(ctx, state, buildIdentityMsgInfo(msg, nil), orgOld.Migrated()) } diff --git a/internal/definitions/sender.go b/internal/definitions/sender.go index 52312a394..59545b8b1 100644 --- a/internal/definitions/sender.go +++ b/internal/definitions/sender.go @@ -35,9 +35,9 @@ type Sender interface { core.Named Init(handler Handler) - CreateDefinitionWithIdentity(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) + CreateDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) DefineDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) error - CreateIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) + DefineIdentity(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, parentSigner *core.SignerRef, tag string, waitConfirm bool) error DefineTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) error DefineFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) error DefineContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) error @@ -92,10 +92,10 @@ func (bm *definitionSender) Init(handler Handler) { } func (bm *definitionSender) createDefinitionDefault(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) { - return bm.CreateDefinitionWithIdentity(ctx, def, &core.SignerRef{ /* resolve to node default */ }, tag, waitConfirm) + return bm.CreateDefinition(ctx, def, &core.SignerRef{ /* resolve to node default */ }, tag, waitConfirm) } -func (bm *definitionSender) CreateDefinitionWithIdentity(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { +func (bm *definitionSender) CreateDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { if bm.multiparty { err = bm.identity.ResolveInputSigningIdentity(ctx, signingIdentity) @@ -107,20 +107,6 @@ func (bm *definitionSender) CreateDefinitionWithIdentity(ctx context.Context, de return bm.createDefinitionCommon(ctx, def, signingIdentity, tag, waitConfirm) } -// CreateIdentityClaim is a special form of CreateDefinition where the signing identity does not need to have been pre-registered -// The blockchain "key" will be normalized, but the "author" will pass through unchecked -func (bm *definitionSender) CreateIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { - - if signingIdentity != nil { - signingIdentity.Key, err = bm.identity.NormalizeSigningKey(ctx, signingIdentity.Key, identity.KeyNormalizationBlockchainPlugin) - if err != nil { - return nil, err - } - } - - return bm.createDefinitionCommon(ctx, def, signingIdentity, tag, waitConfirm) -} - func (bm *definitionSender) createDefinitionCommon(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { b, err := json.Marshal(&def) diff --git a/internal/definitions/sender_identity.go b/internal/definitions/sender_identity.go new file mode 100644 index 000000000..e2657ea56 --- /dev/null +++ b/internal/definitions/sender_identity.go @@ -0,0 +1,63 @@ +// 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 definitions + +import ( + "context" + + "github.com/hyperledger/firefly/internal/identity" + "github.com/hyperledger/firefly/pkg/core" +) + +// DefineIdentity is a special form of CreateDefinition where the signing identity does not need to have been pre-registered +// The blockchain "key" will be normalized, but the "author" will pass through unchecked +func (bm *definitionSender) DefineIdentity(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, parentSigner *core.SignerRef, tag string, waitConfirm bool) error { + if bm.multiparty { + var err error + signingIdentity.Key, err = bm.identity.NormalizeSigningKey(ctx, signingIdentity.Key, identity.KeyNormalizationBlockchainPlugin) + if err != nil { + return err + } + + claimMsg, err := bm.createDefinitionCommon(ctx, def, signingIdentity, tag, waitConfirm) + if err != nil { + return err + } + def.Identity.Messages.Claim = claimMsg.Header.ID + + // Send the verification if one is required. + if parentSigner != nil { + verifyMsg, err := bm.CreateDefinition(ctx, &core.IdentityVerification{ + Claim: core.MessageRef{ + ID: claimMsg.Header.ID, + Hash: claimMsg.Hash, + }, + Identity: def.Identity.IdentityBase, + }, parentSigner, core.SystemTagIdentityVerification, false) + if err != nil { + return err + } + def.Identity.Messages.Verification = verifyMsg.Header.ID + } + + return nil + } + + return fakeBatch(ctx, func(ctx context.Context, state *core.BatchState) (HandlerResult, error) { + return bm.handler.handleIdentityClaim(ctx, state, &identityMsgInfo{SignerRef: *signingIdentity}, def) + }) +} diff --git a/internal/definitions/sender_test.go b/internal/definitions/sender_test.go index b55395eac..9f949041f 100644 --- a/internal/definitions/sender_test.go +++ b/internal/definitions/sender_test.go @@ -92,11 +92,11 @@ func TestCreateIdentityClaim(t *testing.T) { ds.multiparty = true - _, err := ds.CreateIdentityClaim(ds.ctx, &core.IdentityClaim{ + err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ Identity: &core.Identity{}, }, &core.SignerRef{ Key: "0x1234", - }, core.SystemTagDefineNamespace, true) + }, nil, core.SystemTagDefineNamespace, true) assert.NoError(t, err) mim.AssertExpectations(t) @@ -112,11 +112,13 @@ func TestCreateIdentityClaimFail(t *testing.T) { mim.On("NormalizeSigningKey", mock.Anything, "0x1234", identity.KeyNormalizationBlockchainPlugin).Return("", fmt.Errorf("pop")) - _, err := ds.CreateIdentityClaim(ds.ctx, &core.IdentityClaim{ + ds.multiparty = true + + err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ Identity: &core.Identity{}, }, &core.SignerRef{ Key: "0x1234", - }, core.SystemTagDefineNamespace, true) + }, nil, core.SystemTagDefineNamespace, true) assert.EqualError(t, err, "pop") mim.AssertExpectations(t) @@ -152,7 +154,7 @@ func TestCreateDefinitionBadIdentity(t *testing.T) { mim := ds.identity.(*identitymanagermocks.Manager) mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - _, err := ds.CreateDefinitionWithIdentity(ds.ctx, &core.Namespace{}, &core.SignerRef{ + _, err := ds.CreateDefinition(ds.ctx, &core.Namespace{}, &core.SignerRef{ Author: "wrong", Key: "wrong", }, core.SystemTagDefineNamespace, false) diff --git a/internal/identity/identitymanager.go b/internal/identity/identitymanager.go index fc7ba0d45..7d1ff8b1a 100644 --- a/internal/identity/identitymanager.go +++ b/internal/identity/identitymanager.go @@ -344,9 +344,6 @@ func (im *identityManager) VerifyIdentityChain(ctx context.Context, checkIdentit } func (im *identityManager) ResolveIdentitySigner(ctx context.Context, identity *core.Identity) (signer *core.SignerRef, err error) { - if im.multiparty == nil { - return nil, nil - } // Find the message that registered the identity msg, err := im.database.GetMessageByID(ctx, im.namespace, identity.Messages.Claim) diff --git a/internal/identity/identitymanager_test.go b/internal/identity/identitymanager_test.go index 103740683..7bfe9c0ab 100644 --- a/internal/identity/identitymanager_test.go +++ b/internal/identity/identitymanager_test.go @@ -1341,23 +1341,6 @@ func TestResolveIdentitySignerNotFound(t *testing.T) { mdi.AssertExpectations(t) } -func TestResolveIdentitySignerGateway(t *testing.T) { - ctx, im := newTestIdentityManager(t) - im.multiparty = nil - - signer, err := im.ResolveIdentitySigner(ctx, &core.Identity{ - IdentityBase: core.IdentityBase{ - ID: fftypes.NewUUID(), - DID: "did:firefly:org/org1", - Namespace: "ns1", - Name: "org1", - Type: core.IdentityTypeOrg, - }, - }) - assert.NoError(t, err) - assert.Nil(t, signer) -} - func TestParseKeyNormalizationConfig(t *testing.T) { assert.Equal(t, KeyNormalizationBlockchainPlugin, ParseKeyNormalizationConfig("blockchain_Plugin")) assert.Equal(t, KeyNormalizationNone, ParseKeyNormalizationConfig("none")) diff --git a/internal/networkmap/register_identity.go b/internal/networkmap/register_identity.go index e7e4496c3..1605d7a8b 100644 --- a/internal/networkmap/register_identity.go +++ b/internal/networkmap/register_identity.go @@ -68,25 +68,33 @@ func (nm *networkMap) RegisterIdentity(ctx context.Context, dto *core.IdentityCr return nil, err } - // Resolve if we need to perform a validation + var claimSigner *core.SignerRef var parentSigner *core.SignerRef - if immediateParent != nil { - parentSigner, err = nm.identity.ResolveIdentitySigner(ctx, immediateParent) - if err != nil { - return nil, err + + if nm.multiparty != nil { + // Resolve if we need to perform a validation + if immediateParent != nil { + parentSigner, err = nm.identity.ResolveIdentitySigner(ctx, immediateParent) + if err != nil { + return nil, err + } } - } - // Determine claim signer - var claimSigner *core.SignerRef - if dto.Type == core.IdentityTypeNode { - // Nodes are special - as they need the claim to be signed directly by the parent - claimSigner = parentSigner - parentSigner = nil - } else { - if dto.Key == "" { - return nil, i18n.NewError(ctx, coremsgs.MsgBlockchainKeyNotSet) + // Determine claim signer + if dto.Type == core.IdentityTypeNode { + // Nodes are special - as they need the claim to be signed directly by the parent + claimSigner = parentSigner + parentSigner = nil + } else { + if dto.Key == "" { + return nil, i18n.NewError(ctx, coremsgs.MsgBlockchainKeyNotSet) + } + claimSigner = &core.SignerRef{ + Key: dto.Key, + Author: identity.DID, + } } + } else { claimSigner = &core.SignerRef{ Key: dto.Key, Author: identity.DID, @@ -99,36 +107,9 @@ func (nm *networkMap) RegisterIdentity(ctx context.Context, dto *core.IdentityCr }) } err = nm.sendIdentityRequest(ctx, identity, claimSigner, parentSigner) - if err != nil { - return nil, err - } - return identity, nil + return identity, err } func (nm *networkMap) sendIdentityRequest(ctx context.Context, identity *core.Identity, claimSigner *core.SignerRef, parentSigner *core.SignerRef) error { - - // Send the claim - we disable the check on the DID author here, as we are registering the identity so it will not exist - claimMsg, err := nm.defsender.CreateIdentityClaim(ctx, &core.IdentityClaim{ - Identity: identity, - }, claimSigner, core.SystemTagIdentityClaim, false) - if err != nil { - return err - } - identity.Messages.Claim = claimMsg.Header.ID - - // Send the verification if one is required. - if parentSigner != nil { - verifyMsg, err := nm.defsender.CreateDefinitionWithIdentity(ctx, &core.IdentityVerification{ - Claim: core.MessageRef{ - ID: claimMsg.Header.ID, - Hash: claimMsg.Hash, - }, - Identity: identity.IdentityBase, - }, parentSigner, core.SystemTagIdentityVerification, false) - if err != nil { - return err - } - identity.Messages.Verification = verifyMsg.Header.ID - } - return nil + return nm.defsender.DefineIdentity(ctx, &core.IdentityClaim{Identity: identity}, claimSigner, parentSigner, core.SystemTagIdentityClaim, false) } diff --git a/internal/networkmap/register_identity_test.go b/internal/networkmap/register_identity_test.go index 6a8d79bf5..cb85c37d8 100644 --- a/internal/networkmap/register_identity_test.go +++ b/internal/networkmap/register_identity_test.go @@ -44,23 +44,17 @@ func TestRegisterIdentityOrgWithParentOk(t *testing.T) { Key: "0x23456", }, nil) - mockMsg1 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mockMsg2 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("CreateIdentityClaim", nm.ctx, + mds.On("DefineIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" }), - core.SystemTagIdentityClaim, false).Return(mockMsg1, nil) - - mds.On("CreateDefinitionWithIdentity", nm.ctx, - mock.AnythingOfType("*core.IdentityVerification"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x23456" }), - core.SystemTagIdentityVerification, false).Return(mockMsg2, nil) + core.SystemTagIdentityClaim, false).Return(nil) org, err := nm.RegisterIdentity(nm.ctx, &core.IdentityCreateDTO{ Name: "child1", @@ -68,8 +62,7 @@ func TestRegisterIdentityOrgWithParentOk(t *testing.T) { Parent: fftypes.NewUUID().String(), }, false) assert.NoError(t, err) - assert.Equal(t, *mockMsg1.Header.ID, *org.Messages.Claim) - assert.Equal(t, *mockMsg2.Header.ID, *org.Messages.Verification) + assert.NotNil(t, org) mim.AssertExpectations(t) mds.AssertExpectations(t) @@ -98,23 +91,17 @@ func TestRegisterIdentityOrgWithParentWaitConfirmOk(t *testing.T) { assert.NoError(t, err) }).Return(nil, nil) - mockMsg1 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mockMsg2 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("CreateIdentityClaim", nm.ctx, + mds.On("DefineIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" }), - core.SystemTagIdentityClaim, false).Return(mockMsg1, nil) - - mds.On("CreateDefinitionWithIdentity", nm.ctx, - mock.AnythingOfType("*core.IdentityVerification"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x23456" }), - core.SystemTagIdentityVerification, false).Return(mockMsg2, nil) + core.SystemTagIdentityClaim, false).Return(nil) _, err := nm.RegisterIdentity(nm.ctx, &core.IdentityCreateDTO{ Name: "child1", @@ -128,53 +115,6 @@ func TestRegisterIdentityOrgWithParentWaitConfirmOk(t *testing.T) { msa.AssertExpectations(t) } -func TestRegisterIdentityCustomWithParentFail(t *testing.T) { - - nm, cancel := newTestNetworkmap(t) - defer cancel() - - parentIdentity := testOrg("parent1") - - mim := nm.identity.(*identitymanagermocks.Manager) - mim.On("VerifyIdentityChain", nm.ctx, mock.AnythingOfType("*core.Identity")).Return(parentIdentity, false, nil) - mim.On("CachedIdentityLookupMustExist", nm.ctx, "did:firefly:org/parent1").Return(&core.Identity{ - IdentityBase: core.IdentityBase{ - ID: fftypes.NewUUID(), - DID: "did:firefly:org/parent1", - }, - }, false, nil) - mim.On("ResolveIdentitySigner", nm.ctx, parentIdentity).Return(&core.SignerRef{ - Key: "0x23456", - }, nil) - - mockMsg := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} - mds := nm.defsender.(*definitionsmocks.Sender) - - mds.On("CreateIdentityClaim", nm.ctx, - mock.AnythingOfType("*core.IdentityClaim"), - mock.MatchedBy(func(sr *core.SignerRef) bool { - return sr.Key == "0x12345" - }), - core.SystemTagIdentityClaim, false).Return(mockMsg, nil) - - mds.On("CreateDefinitionWithIdentity", nm.ctx, - mock.AnythingOfType("*core.IdentityVerification"), - mock.MatchedBy(func(sr *core.SignerRef) bool { - return sr.Key == "0x23456" - }), - core.SystemTagIdentityVerification, false).Return(nil, fmt.Errorf("pop")) - - _, err := nm.RegisterIdentity(nm.ctx, &core.IdentityCreateDTO{ - Name: "custom1", - Key: "0x12345", - Parent: "did:firefly:org/parent1", - }, false) - assert.Regexp(t, "pop", err) - - mim.AssertExpectations(t) - mds.AssertExpectations(t) -} - func TestRegisterIdentityGetParentMsgFail(t *testing.T) { nm, cancel := newTestNetworkmap(t) @@ -196,33 +136,6 @@ func TestRegisterIdentityGetParentMsgFail(t *testing.T) { mim.AssertExpectations(t) } -func TestRegisterIdentityRootBroadcastFail(t *testing.T) { - - nm, cancel := newTestNetworkmap(t) - defer cancel() - - mim := nm.identity.(*identitymanagermocks.Manager) - mim.On("VerifyIdentityChain", nm.ctx, mock.AnythingOfType("*core.Identity")).Return(nil, false, nil) - - mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("CreateIdentityClaim", nm.ctx, - mock.AnythingOfType("*core.IdentityClaim"), - mock.MatchedBy(func(sr *core.SignerRef) bool { - return sr.Key == "0x12345" - }), - core.SystemTagIdentityClaim, false).Return(nil, fmt.Errorf("pop")) - - _, err := nm.RegisterIdentity(nm.ctx, &core.IdentityCreateDTO{ - Name: "custom1", - Key: "0x12345", - Parent: fftypes.NewUUID().String(), - }, false) - assert.Regexp(t, "pop", err) - - mim.AssertExpectations(t) - mds.AssertExpectations(t) -} - func TestRegisterIdentityMissingKey(t *testing.T) { nm, cancel := newTestNetworkmap(t) diff --git a/internal/networkmap/register_node_test.go b/internal/networkmap/register_node_test.go index b9c51dbd4..c7e6f8e27 100644 --- a/internal/networkmap/register_node_test.go +++ b/internal/networkmap/register_node_test.go @@ -54,16 +54,16 @@ func TestRegisterNodeOk(t *testing.T) { "endpoint": "details", }, nil) - mockMsg := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("CreateIdentityClaim", nm.ctx, + mds.On("DefineIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), signerRef, - core.SystemTagIdentityClaim, false).Return(mockMsg, nil) + (*core.SignerRef)(nil), + core.SystemTagIdentityClaim, false).Return(nil) node, err := nm.RegisterNode(nm.ctx, false) assert.NoError(t, err) - assert.Equal(t, *mockMsg.Header.ID, *node.Messages.Claim) + assert.NotNil(t, node) mim.AssertExpectations(t) mdx.AssertExpectations(t) diff --git a/internal/networkmap/register_org_test.go b/internal/networkmap/register_org_test.go index d617167c7..8935dee02 100644 --- a/internal/networkmap/register_org_test.go +++ b/internal/networkmap/register_org_test.go @@ -67,18 +67,18 @@ func TestRegisterNodeOrgOk(t *testing.T) { mmp := nm.multiparty.(*multipartymocks.Manager) mmp.On("RootOrg").Return(multiparty.RootOrg{Name: "org0"}) - mockMsg := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("CreateIdentityClaim", nm.ctx, + mds.On("DefineIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" }), - core.SystemTagIdentityClaim, false).Return(mockMsg, nil) + (*core.SignerRef)(nil), + core.SystemTagIdentityClaim, false).Return(nil) org, err := nm.RegisterNodeOrganization(nm.ctx, false) assert.NoError(t, err) - assert.Equal(t, *mockMsg.Header.ID, *org.Messages.Claim) + assert.NotNil(t, org) mim.AssertExpectations(t) mds.AssertExpectations(t) diff --git a/internal/networkmap/update_identity.go b/internal/networkmap/update_identity.go index fe0d2d28a..244b5e80a 100644 --- a/internal/networkmap/update_identity.go +++ b/internal/networkmap/update_identity.go @@ -44,10 +44,14 @@ func (nm *networkMap) updateIdentityID(ctx context.Context, id *fftypes.UUID, dt return nil, i18n.NewError(ctx, coremsgs.Msg404NoResult) } - // Resolve the signer of the original claim - updateSigner, err := nm.identity.ResolveIdentitySigner(ctx, identity) - if err != nil { - return nil, err + var updateSigner *core.SignerRef + + if nm.multiparty != nil { + // Resolve the signer of the original claim + updateSigner, err = nm.identity.ResolveIdentitySigner(ctx, identity) + if err != nil { + return nil, err + } } identity.IdentityProfile = dto.IdentityProfile @@ -56,7 +60,7 @@ func (nm *networkMap) updateIdentityID(ctx context.Context, id *fftypes.UUID, dt } // Send the update - updateMsg, err := nm.defsender.CreateDefinitionWithIdentity(ctx, &core.IdentityUpdate{ + updateMsg, err := nm.defsender.CreateDefinition(ctx, &core.IdentityUpdate{ Identity: identity.IdentityBase, Updates: dto.IdentityProfile, }, updateSigner, core.SystemTagIdentityUpdate, waitConfirm) diff --git a/internal/networkmap/update_identity_test.go b/internal/networkmap/update_identity_test.go index 5a9072a29..dae28e9f4 100644 --- a/internal/networkmap/update_identity_test.go +++ b/internal/networkmap/update_identity_test.go @@ -43,7 +43,7 @@ func TestUpdateIdentityProfileOk(t *testing.T) { mockMsg1 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("CreateDefinitionWithIdentity", nm.ctx, + mds.On("CreateDefinition", nm.ctx, mock.AnythingOfType("*core.IdentityUpdate"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" @@ -76,7 +76,7 @@ func TestUpdateIdentityProfileBroadcastFail(t *testing.T) { mim.On("ResolveIdentitySigner", nm.ctx, identity).Return(signerRef, nil) mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("CreateDefinitionWithIdentity", nm.ctx, + mds.On("CreateDefinition", nm.ctx, mock.AnythingOfType("*core.IdentityUpdate"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" diff --git a/mocks/definitionsmocks/sender.go b/mocks/definitionsmocks/sender.go index 25a5b66de..d2ce92ee5 100644 --- a/mocks/definitionsmocks/sender.go +++ b/mocks/definitionsmocks/sender.go @@ -16,8 +16,8 @@ type Sender struct { mock.Mock } -// CreateDefinitionWithIdentity provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm -func (_m *Sender) CreateDefinitionWithIdentity(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { +// CreateDefinition provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm +func (_m *Sender) CreateDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { ret := _m.Called(ctx, def, signingIdentity, tag, waitConfirm) var r0 *core.Message @@ -39,29 +39,6 @@ func (_m *Sender) CreateDefinitionWithIdentity(ctx context.Context, def core.Def return r0, r1 } -// CreateIdentityClaim provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm -func (_m *Sender) CreateIdentityClaim(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { - ret := _m.Called(ctx, def, signingIdentity, tag, waitConfirm) - - var r0 *core.Message - if rf, ok := ret.Get(0).(func(context.Context, *core.IdentityClaim, *core.SignerRef, string, bool) *core.Message); ok { - r0 = rf(ctx, def, signingIdentity, tag, waitConfirm) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*core.Message) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *core.IdentityClaim, *core.SignerRef, string, bool) error); ok { - r1 = rf(ctx, def, signingIdentity, tag, waitConfirm) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // DefineContractAPI provides a mock function with given fields: ctx, httpServerURL, api, waitConfirm func (_m *Sender) DefineContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) error { ret := _m.Called(ctx, httpServerURL, api, waitConfirm) @@ -104,6 +81,20 @@ func (_m *Sender) DefineFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool return r0 } +// DefineIdentity provides a mock function with given fields: ctx, def, signingIdentity, parentSigner, tag, waitConfirm +func (_m *Sender) DefineIdentity(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, parentSigner *core.SignerRef, tag string, waitConfirm bool) error { + ret := _m.Called(ctx, def, signingIdentity, parentSigner, tag, waitConfirm) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *core.IdentityClaim, *core.SignerRef, *core.SignerRef, string, bool) error); ok { + r0 = rf(ctx, def, signingIdentity, parentSigner, tag, waitConfirm) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // DefineTokenPool provides a mock function with given fields: ctx, pool, waitConfirm func (_m *Sender) DefineTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) error { ret := _m.Called(ctx, pool, waitConfirm) From 1f60a549575ebb8b5214f8eb9ae7cc53afb98f1e Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Tue, 28 Jun 2022 12:20:12 -0400 Subject: [PATCH 21/27] Move plugin start calls to namespace manager Avoid starting plugins more than once. Signed-off-by: Andrew Richardson --- internal/namespace/manager.go | 15 +++++ internal/namespace/manager_test.go | 66 ++++++++++++++++++- internal/orchestrator/orchestrator.go | 13 ---- internal/orchestrator/orchestrator_test.go | 38 ----------- internal/privatemessaging/privatemessaging.go | 5 -- .../privatemessaging/privatemessaging_test.go | 11 ---- 6 files changed, 80 insertions(+), 68 deletions(-) diff --git a/internal/namespace/manager.go b/internal/namespace/manager.go index 9bc79b4be..45981c876 100644 --- a/internal/namespace/manager.go +++ b/internal/namespace/manager.go @@ -220,6 +220,21 @@ func (nm *namespaceManager) Start() error { metrics.Registry() } for _, ns := range nm.namespaces { + if ns.plugins.Blockchain.Plugin != nil { + if err := ns.plugins.Blockchain.Plugin.Start(); err != nil { + return err + } + } + if ns.plugins.DataExchange.Plugin != nil { + if err := ns.plugins.DataExchange.Plugin.Start(); err != nil { + return err + } + } + for _, plugin := range ns.plugins.Tokens { + if err := plugin.Plugin.Start(); err != nil { + return err + } + } if err := ns.orchestrator.Start(); err != nil { return err } diff --git a/internal/namespace/manager_test.go b/internal/namespace/manager_test.go index 9ce16f359..83ee6f662 100644 --- a/internal/namespace/manager_test.go +++ b/internal/namespace/manager_test.go @@ -29,6 +29,7 @@ import ( "github.com/hyperledger/firefly/internal/database/difactory" "github.com/hyperledger/firefly/internal/dataexchange/dxfactory" "github.com/hyperledger/firefly/internal/identity/iifactory" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/internal/sharedstorage/ssfactory" "github.com/hyperledger/firefly/internal/tokens/tifactory" "github.com/hyperledger/firefly/mocks/blockchainmocks" @@ -1126,7 +1127,70 @@ func TestStart(t *testing.T) { mo.AssertExpectations(t) } -func TestStartFail(t *testing.T) { +func TestStartBlockchainFail(t *testing.T) { + nm := newTestNamespaceManager(true) + defer nm.cleanup(t) + + nm.namespaces = map[string]*namespace{ + "ns": { + plugins: orchestrator.Plugins{ + Blockchain: orchestrator.BlockchainPlugin{ + Plugin: nm.mbi, + }, + }, + }, + } + + nm.mbi.On("Start").Return(fmt.Errorf("pop")) + + err := nm.Start() + assert.EqualError(t, err, "pop") + +} + +func TestStartDataExchangeFail(t *testing.T) { + nm := newTestNamespaceManager(true) + defer nm.cleanup(t) + + nm.namespaces = map[string]*namespace{ + "ns": { + plugins: orchestrator.Plugins{ + DataExchange: orchestrator.DataExchangePlugin{ + Plugin: nm.mdx, + }, + }, + }, + } + + nm.mdx.On("Start").Return(fmt.Errorf("pop")) + + err := nm.Start() + assert.EqualError(t, err, "pop") + +} + +func TestStartTokensFail(t *testing.T) { + nm := newTestNamespaceManager(true) + defer nm.cleanup(t) + + nm.namespaces = map[string]*namespace{ + "ns": { + plugins: orchestrator.Plugins{ + Tokens: []orchestrator.TokensPlugin{{ + Plugin: nm.mti, + }}, + }, + }, + } + + nm.mti.On("Start").Return(fmt.Errorf("pop")) + + err := nm.Start() + assert.EqualError(t, err, "pop") + +} + +func TestStartOrchestratorFail(t *testing.T) { nm := newTestNamespaceManager(true) defer nm.cleanup(t) diff --git a/internal/orchestrator/orchestrator.go b/internal/orchestrator/orchestrator.go index 7186dffed..5ef492663 100644 --- a/internal/orchestrator/orchestrator.go +++ b/internal/orchestrator/orchestrator.go @@ -262,29 +262,16 @@ func (or *orchestrator) Start() (err error) { if err == nil { err = or.broadcast.Start() } - if err == nil { - err = or.messaging.Start() - } if err == nil { err = or.sharedDownload.Start() } } - if err == nil { - err = or.blockchain().Start() - } if err == nil { err = or.events.Start() } if err == nil { err = or.operations.Start() } - if err == nil { - for _, el := range or.tokens() { - if err = el.Start(); err != nil { - break - } - } - } or.started = true return err } diff --git a/internal/orchestrator/orchestrator_test.go b/internal/orchestrator/orchestrator_test.go index 1004f1861..c17a58912 100644 --- a/internal/orchestrator/orchestrator_test.go +++ b/internal/orchestrator/orchestrator_test.go @@ -379,41 +379,6 @@ func TestStartBatchFail(t *testing.T) { assert.EqualError(t, err, "pop") } -func TestStartTokensFail(t *testing.T) { - coreconfig.Reset() - or := newTestOrchestrator() - defer or.cleanup(t) - or.mdi.On("GetNamespace", mock.Anything, "ns").Return(nil, nil) - or.mdi.On("UpsertNamespace", mock.Anything, mock.Anything, true).Return(nil) - or.mmp.On("ConfigureContract", mock.Anything, &core.FireFlyContracts{}).Return(nil) - or.mbi.On("Start").Return(nil) - or.mba.On("Start").Return(nil) - or.mem.On("Start").Return(nil) - or.mbm.On("Start").Return(nil) - or.mpm.On("Start").Return(nil) - or.msd.On("Start").Return(nil) - or.mom.On("Start").Return(nil) - or.mti.On("Start").Return(fmt.Errorf("pop")) - err := or.Start() - assert.EqualError(t, err, "pop") -} - -func TestStartBlockchainsFail(t *testing.T) { - coreconfig.Reset() - or := newTestOrchestrator() - defer or.cleanup(t) - or.mdi.On("GetNamespace", mock.Anything, "ns").Return(nil, nil) - or.mdi.On("UpsertNamespace", mock.Anything, mock.Anything, true).Return(nil) - or.mmp.On("ConfigureContract", mock.Anything, &core.FireFlyContracts{}).Return(nil) - or.mbm.On("Start").Return(nil) - or.mpm.On("Start").Return(nil) - or.mba.On("Start").Return(nil) - or.msd.On("Start").Return(nil) - or.mbi.On("Start").Return(fmt.Errorf("pop")) - err := or.Start() - assert.EqualError(t, err, "pop") -} - func TestStartBlockchainsConfigureFail(t *testing.T) { coreconfig.Reset() or := newTestOrchestrator() @@ -431,12 +396,9 @@ func TestStartStopOk(t *testing.T) { or.mdi.On("GetNamespace", mock.Anything, "ns").Return(nil, nil) or.mdi.On("UpsertNamespace", mock.Anything, mock.Anything, true).Return(nil) or.mmp.On("ConfigureContract", mock.Anything, &core.FireFlyContracts{}).Return(nil) - or.mbi.On("Start").Return(nil) or.mba.On("Start").Return(nil) or.mem.On("Start").Return(nil) or.mbm.On("Start").Return(nil) - or.mpm.On("Start").Return(nil) - or.mti.On("Start").Return(nil) or.msd.On("Start").Return(nil) or.mom.On("Start").Return(nil) or.mba.On("WaitStop").Return(nil) diff --git a/internal/privatemessaging/privatemessaging.go b/internal/privatemessaging/privatemessaging.go index 8aa8b675f..75a1914d7 100644 --- a/internal/privatemessaging/privatemessaging.go +++ b/internal/privatemessaging/privatemessaging.go @@ -49,7 +49,6 @@ type Manager interface { core.Named GroupManager - Start() error NewMessage(msg *core.MessageInOut) sysmessaging.MessageSender SendMessage(ctx context.Context, in *core.MessageInOut, waitConfirm bool) (out *core.Message, err error) RequestReply(ctx context.Context, request *core.MessageInOut) (reply *core.MessageInOut, err error) @@ -161,10 +160,6 @@ func (pm *privateMessaging) Name() string { return "PrivateMessaging" } -func (pm *privateMessaging) Start() error { - return pm.exchange.Start() -} - func (pm *privateMessaging) dispatchPinnedBatch(ctx context.Context, state *batch.DispatchState) error { err := pm.dispatchBatchCommon(ctx, state) if err != nil { diff --git a/internal/privatemessaging/privatemessaging_test.go b/internal/privatemessaging/privatemessaging_test.go index 86ff52fe9..6546ccc6e 100644 --- a/internal/privatemessaging/privatemessaging_test.go +++ b/internal/privatemessaging/privatemessaging_test.go @@ -535,14 +535,3 @@ func TestTransferBlobsOpInsertFail(t *testing.T) { mdi.AssertExpectations(t) } - -func TestStart(t *testing.T) { - pm, cancel := newTestPrivateMessaging(t) - defer cancel() - - mdx := pm.exchange.(*dataexchangemocks.Plugin) - mdx.On("Start").Return(nil) - - err := pm.Start() - assert.NoError(t, err) -} From 2a02feec8c77a3f5b5d4cd170147342723ec3efb Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Tue, 28 Jun 2022 15:14:41 -0400 Subject: [PATCH 22/27] Complete test coverage and remove dead branches Signed-off-by: Andrew Richardson --- internal/contracts/manager.go | 4 +- internal/definitions/handler.go | 9 - internal/definitions/handler_contracts.go | 46 ++--- .../definitions/handler_contracts_test.go | 133 ++++++------ .../handler_identity_claim_test.go | 40 ---- internal/definitions/handler_test.go | 11 - internal/definitions/sender.go | 45 ++--- internal/definitions/sender_contracts.go | 18 +- internal/definitions/sender_contracts_test.go | 37 ++++ internal/definitions/sender_datatype.go | 16 +- internal/definitions/sender_datatype_test.go | 14 ++ internal/definitions/sender_identity_test.go | 191 ++++++++++++++++++ internal/definitions/sender_test.go | 47 ----- internal/definitions/sender_tokenpool.go | 1 + internal/definitions/sender_tokenpool_test.go | 26 +++ internal/networkmap/register_identity_test.go | 74 +++++++ 16 files changed, 463 insertions(+), 249 deletions(-) create mode 100644 internal/definitions/sender_identity_test.go diff --git a/internal/contracts/manager.go b/internal/contracts/manager.go index 461a2d13d..394774cc6 100644 --- a/internal/contracts/manager.go +++ b/internal/contracts/manager.go @@ -308,7 +308,9 @@ func (cm *contractManager) ResolveContractAPI(ctx context.Context, httpServerURL return err } - cm.addContractURLs(httpServerURL, api) + if httpServerURL != "" { + cm.addContractURLs(httpServerURL, api) + } return nil } diff --git a/internal/definitions/handler.go b/internal/definitions/handler.go index 97698ff4e..042e3211b 100644 --- a/internal/definitions/handler.go +++ b/internal/definitions/handler.go @@ -37,7 +37,6 @@ import ( type Handler interface { HandleDefinitionBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (HandlerResult, error) - HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error } type HandlerResult struct { @@ -149,11 +148,3 @@ func (dh *definitionHandler) getSystemBroadcastPayload(ctx context.Context, msg res.SetBroadcastMessage(msg.Header.ID) return true } - -func (dh *definitionHandler) HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error { - result, err := dh.HandleDefinitionBroadcast(ctx, state, msg, core.DataArray{data}, nil) - if result.Action == ActionReject { - return i18n.WrapError(ctx, err, coremsgs.MsgDefinitionRejected) - } - return err -} diff --git a/internal/definitions/handler_contracts.go b/internal/definitions/handler_contracts.go index 53affe4b6..d00de0483 100644 --- a/internal/definitions/handler_contracts.go +++ b/internal/definitions/handler_contracts.go @@ -27,44 +27,35 @@ import ( "github.com/hyperledger/firefly/pkg/database" ) -func (dh *definitionHandler) persistFFI(ctx context.Context, ffi *core.FFI) (err error) { +func (dh *definitionHandler) persistFFI(ctx context.Context, ffi *core.FFI) (retry bool, err error) { if err = dh.contracts.ResolveFFI(ctx, ffi); err != nil { - log.L(ctx).Warnf("Unable to process FFI %s - validate failed: %s", ffi.ID, err) - return nil + return false, i18n.NewError(ctx, coremsgs.MsgDefRejectedValidateFail, "contract interface", ffi.ID, err) } err = dh.database.UpsertFFI(ctx, ffi) if err != nil { - return err + return true, err } for _, method := range ffi.Methods { - err := dh.database.UpsertFFIMethod(ctx, method) - if err != nil { - return err + if err := dh.database.UpsertFFIMethod(ctx, method); err != nil { + return true, err } } - for _, event := range ffi.Events { - err := dh.database.UpsertFFIEvent(ctx, event) - if err != nil { - return err + if err := dh.database.UpsertFFIEvent(ctx, event); err != nil { + return true, err } } - return nil + return false, nil } -func (dh *definitionHandler) persistContractAPI(ctx context.Context, api *core.ContractAPI) (retry bool, err error) { - existing, err := dh.database.GetContractAPIByName(ctx, api.Namespace, api.Name) - if err != nil { - return true, err - } - if existing != nil { - if !api.LocationAndLedgerEquals(existing) { - return false, i18n.NewError(ctx, coremsgs.MsgDefRejectedLocationMismatch, "contract API", api.ID) - } +func (dh *definitionHandler) persistContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI) (retry bool, err error) { + if err := dh.contracts.ResolveContractAPI(ctx, httpServerURL, api); err != nil { + return false, i18n.NewError(ctx, coremsgs.MsgDefRejectedValidateFail, "contract API", api.ID, err) } + err = dh.database.UpsertContractAPI(ctx, api) if err != nil { if err == database.IDMismatch { @@ -90,8 +81,11 @@ func (dh *definitionHandler) handleFFIBroadcast(ctx context.Context, state *core func (dh *definitionHandler) handleFFIDefinition(ctx context.Context, state *core.BatchState, ffi *core.FFI, tx *fftypes.UUID) (HandlerResult, error) { l := log.L(ctx) - if err := dh.persistFFI(ctx, ffi); err != nil { - return HandlerResult{Action: ActionRetry}, err + if retry, err := dh.persistFFI(ctx, ffi); err != nil { + if retry { + return HandlerResult{Action: ActionRetry}, err + } + return HandlerResult{Action: ActionReject}, err } l.Infof("Contract interface created id=%s", ffi.ID) @@ -112,12 +106,12 @@ func (dh *definitionHandler) handleContractAPIBroadcast(ctx context.Context, sta } api.Message = msg.Header.ID - return dh.handleContractAPIDefinition(ctx, state, &api, tx) + return dh.handleContractAPIDefinition(ctx, state, "", &api, tx) } -func (dh *definitionHandler) handleContractAPIDefinition(ctx context.Context, state *core.BatchState, api *core.ContractAPI, tx *fftypes.UUID) (HandlerResult, error) { +func (dh *definitionHandler) handleContractAPIDefinition(ctx context.Context, state *core.BatchState, httpServerURL string, api *core.ContractAPI, tx *fftypes.UUID) (HandlerResult, error) { l := log.L(ctx) - if retry, err := dh.persistContractAPI(ctx, api); err != nil { + if retry, err := dh.persistContractAPI(ctx, httpServerURL, api); err != nil { if retry { return HandlerResult{Action: ActionRetry}, err } diff --git a/internal/definitions/handler_contracts_test.go b/internal/definitions/handler_contracts_test.go index 750a6bc97..e72d655dd 100644 --- a/internal/definitions/handler_contracts_test.go +++ b/internal/definitions/handler_contracts_test.go @@ -96,11 +96,11 @@ func TestHandleFFIBroadcastOk(t *testing.T) { Value: fftypes.JSONAnyPtrBytes(b), } - mbi := dh.database.(*databasemocks.Plugin) - mbi.On("UpsertFFI", mock.Anything, mock.Anything).Return(nil) - mbi.On("UpsertFFIMethod", mock.Anything, mock.Anything).Return(nil) - mbi.On("UpsertFFIEvent", mock.Anything, mock.Anything).Return(nil) - mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) + mdi := dh.database.(*databasemocks.Plugin) + mdi.On("UpsertFFI", mock.Anything, mock.Anything).Return(nil) + mdi.On("UpsertFFIMethod", mock.Anything, mock.Anything).Return(nil) + mdi.On("UpsertFFIEvent", mock.Anything, mock.Anything).Return(nil) + mdi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) mcm := dh.contracts.(*contractmocks.Manager) mcm.On("ResolveFFI", mock.Anything, mock.Anything).Return(nil) @@ -113,23 +113,24 @@ func TestHandleFFIBroadcastOk(t *testing.T) { assert.NoError(t, err) err = bs.RunFinalize(context.Background()) assert.NoError(t, err) - mbi.AssertExpectations(t) + mdi.AssertExpectations(t) } func TestPersistFFIValidateFFIFail(t *testing.T) { dh, _ := newTestDefinitionHandler(t) mcm := dh.contracts.(*contractmocks.Manager) mcm.On("ResolveFFI", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - err := dh.persistFFI(context.Background(), testFFI()) - assert.NoError(t, err) + retry, err := dh.persistFFI(context.Background(), testFFI()) + assert.Regexp(t, "FF10403", err) + assert.False(t, retry) mcm.AssertExpectations(t) } func TestHandleFFIBroadcastReject(t *testing.T) { dh, bs := newTestDefinitionHandler(t) - mbi := dh.database.(*databasemocks.Plugin) + mdi := dh.database.(*databasemocks.Plugin) mcm := dh.contracts.(*contractmocks.Manager) - mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) + mdi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) mcm.On("ResolveFFI", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) action, err := dh.handleFFIBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ @@ -143,40 +144,43 @@ func TestHandleFFIBroadcastReject(t *testing.T) { func TestPersistFFIUpsertFFIFail(t *testing.T) { dh, _ := newTestDefinitionHandler(t) - mbi := dh.database.(*databasemocks.Plugin) - mbi.On("UpsertFFI", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) + mdi := dh.database.(*databasemocks.Plugin) + mdi.On("UpsertFFI", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) mcm := dh.contracts.(*contractmocks.Manager) mcm.On("ResolveFFI", mock.Anything, mock.Anything).Return(nil) - err := dh.persistFFI(context.Background(), testFFI()) + retry, err := dh.persistFFI(context.Background(), testFFI()) assert.Regexp(t, "pop", err) - mbi.AssertExpectations(t) + assert.True(t, retry) + mdi.AssertExpectations(t) mcm.AssertExpectations(t) } func TestPersistFFIUpsertFFIMethodFail(t *testing.T) { dh, _ := newTestDefinitionHandler(t) - mbi := dh.database.(*databasemocks.Plugin) - mbi.On("UpsertFFI", mock.Anything, mock.Anything).Return(nil) - mbi.On("UpsertFFIMethod", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) + mdi := dh.database.(*databasemocks.Plugin) + mdi.On("UpsertFFI", mock.Anything, mock.Anything).Return(nil) + mdi.On("UpsertFFIMethod", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) mcm := dh.contracts.(*contractmocks.Manager) mcm.On("ResolveFFI", mock.Anything, mock.Anything).Return(nil) - err := dh.persistFFI(context.Background(), testFFI()) + retry, err := dh.persistFFI(context.Background(), testFFI()) assert.Regexp(t, "pop", err) - mbi.AssertExpectations(t) + assert.True(t, retry) + mdi.AssertExpectations(t) mcm.AssertExpectations(t) } func TestPersistFFIUpsertFFIEventFail(t *testing.T) { dh, _ := newTestDefinitionHandler(t) - mbi := dh.database.(*databasemocks.Plugin) - mbi.On("UpsertFFI", mock.Anything, mock.Anything).Return(nil) - mbi.On("UpsertFFIMethod", mock.Anything, mock.Anything).Return(nil) - mbi.On("UpsertFFIEvent", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) + mdi := dh.database.(*databasemocks.Plugin) + mdi.On("UpsertFFI", mock.Anything, mock.Anything).Return(nil) + mdi.On("UpsertFFIMethod", mock.Anything, mock.Anything).Return(nil) + mdi.On("UpsertFFIEvent", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) mcm := dh.contracts.(*contractmocks.Manager) mcm.On("ResolveFFI", mock.Anything, mock.Anything).Return(nil) - err := dh.persistFFI(context.Background(), testFFI()) + retry, err := dh.persistFFI(context.Background(), testFFI()) assert.Regexp(t, "pop", err) - mbi.AssertExpectations(t) + assert.True(t, retry) + mdi.AssertExpectations(t) mcm.AssertExpectations(t) } @@ -189,8 +193,8 @@ func TestHandleFFIBroadcastValidateFail(t *testing.T) { data := &core.Data{ Value: fftypes.JSONAnyPtrBytes(b), } - mbi := dh.database.(*databasemocks.Plugin) - mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) + mdi := dh.database.(*databasemocks.Plugin) + mdi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineFFI, @@ -233,10 +237,12 @@ func TestHandleContractAPIBroadcastOk(t *testing.T) { Value: fftypes.JSONAnyPtrBytes(b), } - mbi := dh.database.(*databasemocks.Plugin) - mbi.On("UpsertContractAPI", mock.Anything, mock.Anything, mock.Anything).Return(nil) - mbi.On("GetContractAPIByName", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) - mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) + mdi := dh.database.(*databasemocks.Plugin) + mdi.On("UpsertContractAPI", mock.Anything, mock.Anything, mock.Anything).Return(nil) + mdi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) + mcm := dh.contracts.(*contractmocks.Manager) + mcm.On("ResolveContractAPI", context.Background(), "", mock.Anything).Return(nil) + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineContractAPI, @@ -246,7 +252,9 @@ func TestHandleContractAPIBroadcastOk(t *testing.T) { assert.NoError(t, err) err = bs.RunFinalize(context.Background()) assert.NoError(t, err) - mbi.AssertExpectations(t) + + mdi.AssertExpectations(t) + mcm.AssertExpectations(t) } func TestHandleContractAPIBadPayload(t *testing.T) { @@ -273,9 +281,10 @@ func TestHandleContractAPIIDMismatch(t *testing.T) { Value: fftypes.JSONAnyPtrBytes(b), } - mbi := dh.database.(*databasemocks.Plugin) - mbi.On("GetContractAPIByName", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) - mbi.On("UpsertContractAPI", mock.Anything, mock.Anything, mock.Anything).Return(database.IDMismatch) + mdi := dh.database.(*databasemocks.Plugin) + mdi.On("UpsertContractAPI", mock.Anything, mock.Anything, mock.Anything).Return(database.IDMismatch) + mcm := dh.contracts.(*contractmocks.Manager) + mcm.On("ResolveContractAPI", context.Background(), "", mock.Anything).Return(nil) action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ @@ -284,38 +293,23 @@ func TestHandleContractAPIIDMismatch(t *testing.T) { }, core.DataArray{data}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionReject}, action) assert.Regexp(t, "FF10404", err) - mbi.AssertExpectations(t) -} -func TestPersistContractAPIGetFail(t *testing.T) { - dh, _ := newTestDefinitionHandler(t) - mbi := dh.database.(*databasemocks.Plugin) - mbi.On("GetContractAPIByName", mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("pop")) - _, err := dh.persistContractAPI(context.Background(), testContractAPI()) - assert.Regexp(t, "pop", err) - mbi.AssertExpectations(t) -} - -func TestPersistContractAPIDifferentLocation(t *testing.T) { - existing := testContractAPI() - existing.Location = fftypes.JSONAnyPtr(`{"existing": true}`) - dh, _ := newTestDefinitionHandler(t) - mbi := dh.database.(*databasemocks.Plugin) - mbi.On("GetContractAPIByName", mock.Anything, mock.Anything, mock.Anything).Return(existing, nil) - retry, err := dh.persistContractAPI(context.Background(), testContractAPI()) - assert.False(t, retry) - assert.Regexp(t, "FF10405", err) - mbi.AssertExpectations(t) + mdi.AssertExpectations(t) + mcm.AssertExpectations(t) } func TestPersistContractAPIUpsertFail(t *testing.T) { dh, _ := newTestDefinitionHandler(t) - mbi := dh.database.(*databasemocks.Plugin) - mbi.On("GetContractAPIByName", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) - mbi.On("UpsertContractAPI", mock.Anything, mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - _, err := dh.persistContractAPI(context.Background(), testContractAPI()) + mdi := dh.database.(*databasemocks.Plugin) + mdi.On("UpsertContractAPI", mock.Anything, mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) + mcm := dh.contracts.(*contractmocks.Manager) + mcm.On("ResolveContractAPI", context.Background(), "http://test", mock.Anything).Return(nil) + + _, err := dh.persistContractAPI(context.Background(), "http://test", testContractAPI()) assert.Regexp(t, "pop", err) - mbi.AssertExpectations(t) + + mdi.AssertExpectations(t) + mcm.AssertExpectations(t) } func TestHandleContractAPIBroadcastValidateFail(t *testing.T) { @@ -327,8 +321,8 @@ func TestHandleContractAPIBroadcastValidateFail(t *testing.T) { data := &core.Data{ Value: fftypes.JSONAnyPtrBytes(b), } - mbi := dh.database.(*databasemocks.Plugin) - mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) + mdi := dh.database.(*databasemocks.Plugin) + mdi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineContractAPI, @@ -347,10 +341,11 @@ func TestHandleContractAPIBroadcastPersistFail(t *testing.T) { data := &core.Data{ Value: fftypes.JSONAnyPtrBytes(b), } - mbi := dh.database.(*databasemocks.Plugin) - mbi.On("GetContractAPIByName", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) - mbi.On("UpsertContractAPI", mock.Anything, mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - mbi.On("InsertEvent", mock.Anything, mock.Anything).Return(nil) + mdi := dh.database.(*databasemocks.Plugin) + mdi.On("UpsertContractAPI", mock.Anything, mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) + mcm := dh.contracts.(*contractmocks.Manager) + mcm.On("ResolveContractAPI", context.Background(), "", mock.Anything).Return(nil) + action, err := dh.HandleDefinitionBroadcast(context.Background(), &bs.BatchState, &core.Message{ Header: core.MessageHeader{ Tag: core.SystemTagDefineContractAPI, @@ -358,5 +353,9 @@ func TestHandleContractAPIBroadcastPersistFail(t *testing.T) { }, core.DataArray{data}, fftypes.NewUUID()) assert.Equal(t, HandlerResult{Action: ActionRetry}, action) assert.Regexp(t, "pop", err) + bs.assertNoFinalizers() + + mdi.AssertExpectations(t) + mcm.AssertExpectations(t) } diff --git a/internal/definitions/handler_identity_claim_test.go b/internal/definitions/handler_identity_claim_test.go index ae4961020..0ce6db8ad 100644 --- a/internal/definitions/handler_identity_claim_test.go +++ b/internal/definitions/handler_identity_claim_test.go @@ -614,43 +614,3 @@ func TestHandleDefinitionIdentityClaimBadData(t *testing.T) { bs.assertNoFinalizers() } - -func TestHandleDefinitionIdentityClaimGateway(t *testing.T) { - dh, bs := newTestDefinitionHandler(t) - ctx := context.Background() - - custom1, org1, claimMsg, claimData, _, _ := testCustomClaimAndVerification(t) - - mim := dh.identity.(*identitymanagermocks.Manager) - mim.On("VerifyIdentityChain", ctx, custom1).Return(org1, false, nil) - - mdi := dh.database.(*databasemocks.Plugin) - mdi.On("GetIdentityByName", ctx, custom1.Type, custom1.Namespace, custom1.Name).Return(nil, nil) - mdi.On("GetIdentityByID", ctx, "ns1", custom1.ID).Return(nil, nil) - mdi.On("GetVerifierByValue", ctx, core.VerifierTypeEthAddress, "ns1", "0x12345").Return(nil, nil) - mdi.On("UpsertIdentity", ctx, mock.MatchedBy(func(identity *core.Identity) bool { - assert.Equal(t, *claimMsg.Header.ID, *identity.Messages.Claim) - assert.Nil(t, identity.Messages.Verification) - return true - }), database.UpsertOptimizationNew).Return(nil) - mdi.On("UpsertVerifier", ctx, mock.MatchedBy(func(verifier *core.Verifier) bool { - assert.Equal(t, core.VerifierTypeEthAddress, verifier.Type) - assert.Equal(t, "0x12345", verifier.Value) - assert.Equal(t, *custom1.ID, *verifier.Identity) - return true - }), database.UpsertOptimizationNew).Return(nil) - mdi.On("InsertEvent", mock.Anything, mock.MatchedBy(func(event *core.Event) bool { - return event.Type == core.EventTypeIdentityConfirmed - })).Return(nil) - - err := dh.HandleDefinition(ctx, &bs.BatchState, claimMsg, claimData) - assert.NoError(t, err) - assert.Equal(t, bs.ConfirmedDIDClaims, []string{custom1.DID}) - - err = bs.RunFinalize(ctx) - assert.NoError(t, err) - - mdi.AssertExpectations(t) - mim.AssertExpectations(t) - -} diff --git a/internal/definitions/handler_test.go b/internal/definitions/handler_test.go index f859dd426..fb7fe6067 100644 --- a/internal/definitions/handler_test.go +++ b/internal/definitions/handler_test.go @@ -111,14 +111,3 @@ func TestActionEnum(t *testing.T) { assert.Equal(t, "wait", fmt.Sprintf("%s", ActionWait)) assert.Equal(t, "unknown", fmt.Sprintf("%s", DefinitionMessageAction(999))) } - -func TestHandleDefinitionReject(t *testing.T) { - dh, bs := newTestDefinitionHandler(t) - err := dh.HandleDefinition(context.Background(), &bs.BatchState, &core.Message{ - Header: core.MessageHeader{ - Tag: "unknown", - }, - }, &core.Data{}) - assert.Error(t, err) - bs.assertNoFinalizers() -} diff --git a/internal/definitions/sender.go b/internal/definitions/sender.go index 59545b8b1..ff69e87b9 100644 --- a/internal/definitions/sender.go +++ b/internal/definitions/sender.go @@ -56,15 +56,16 @@ type definitionSender struct { } // Definitions that get processed immediately will create a temporary batch state and then finalize it inline -func fakeBatch(ctx context.Context, handler func(context.Context, *core.BatchState) (HandlerResult, error)) error { +func fakeBatch(ctx context.Context, handler func(context.Context, *core.BatchState) (HandlerResult, error)) (err error) { var state core.BatchState - if _, err := handler(ctx, &state); err != nil { - return err + _, err = handler(ctx, &state) + if err == nil { + err = state.RunPreFinalize(ctx) } - if err := state.RunPreFinalize(ctx); err != nil { - return err + if err == nil { + err = state.RunFinalize(ctx) } - return state.RunFinalize(ctx) + return err } func NewDefinitionSender(ctx context.Context, ns string, multiparty bool, di database.Plugin, bm broadcast.Manager, im identity.Manager, dm data.Manager, cm contracts.Manager) (Sender, error) { @@ -129,32 +130,14 @@ func (bm *definitionSender) createDefinitionCommon(ctx context.Context, def core message.Header.SignerRef = *signingIdentity } - if bm.multiparty { - message.InlineData = core.InlineData{ - &core.DataRefOrValue{Value: dataValue}, - } - sender := bm.broadcast.NewBroadcast(message) - if waitConfirm { - err = sender.SendAndWait(ctx) - } else { - err = sender.Send(ctx) - } + message.InlineData = core.InlineData{ + &core.DataRefOrValue{Value: dataValue}, + } + sender := bm.broadcast.NewBroadcast(message) + if waitConfirm { + err = sender.SendAndWait(ctx) } else { - data := &core.Data{Value: dataValue} - err = bm.createDefinitionLocal(ctx, &message.Message, data) + err = sender.Send(ctx) } - return &message.Message, err } - -func (bm *definitionSender) createDefinitionLocal(ctx context.Context, msg *core.Message, data *core.Data) (err error) { - state := &core.BatchState{ - PendingConfirms: make(map[fftypes.UUID]*core.Message), - } - if err = bm.handler.HandleDefinition(ctx, state, msg, data); err == nil { - if err = state.RunPreFinalize(ctx); err == nil { - err = state.RunFinalize(ctx) - } - } - return err -} diff --git a/internal/definitions/sender_contracts.go b/internal/definitions/sender_contracts.go index 8f9b907e8..cf9640d96 100644 --- a/internal/definitions/sender_contracts.go +++ b/internal/definitions/sender_contracts.go @@ -33,11 +33,11 @@ func (bm *definitionSender) DefineFFI(ctx context.Context, ffi *core.FFI, waitCo event.ID = fftypes.NewUUID() } - if err := bm.contracts.ResolveFFI(ctx, ffi); err != nil { - return err - } - if bm.multiparty { + if err := bm.contracts.ResolveFFI(ctx, ffi); err != nil { + return err + } + msg, err := bm.createDefinitionDefault(ctx, ffi, core.SystemTagDefineFFI, waitConfirm) if msg != nil { ffi.Message = msg.Header.ID @@ -54,11 +54,11 @@ func (bm *definitionSender) DefineContractAPI(ctx context.Context, httpServerURL api.ID = fftypes.NewUUID() api.Namespace = bm.namespace - if err := bm.contracts.ResolveContractAPI(ctx, httpServerURL, api); err != nil { - return err - } - if bm.multiparty { + if err := bm.contracts.ResolveContractAPI(ctx, httpServerURL, api); err != nil { + return err + } + msg, err := bm.createDefinitionDefault(ctx, api, core.SystemTagDefineContractAPI, waitConfirm) if msg != nil { api.Message = msg.Header.ID @@ -67,6 +67,6 @@ func (bm *definitionSender) DefineContractAPI(ctx context.Context, httpServerURL } return fakeBatch(ctx, func(ctx context.Context, state *core.BatchState) (HandlerResult, error) { - return bm.handler.handleContractAPIDefinition(ctx, state, api, nil) + return bm.handler.handleContractAPIDefinition(ctx, state, httpServerURL, api, nil) }) } diff --git a/internal/definitions/sender_contracts_test.go b/internal/definitions/sender_contracts_test.go index 474cd4946..e01038ada 100644 --- a/internal/definitions/sender_contracts_test.go +++ b/internal/definitions/sender_contracts_test.go @@ -96,6 +96,24 @@ func TestDefineFFIOk(t *testing.T) { mms.AssertExpectations(t) } +func TestDefineFFINonMultiparty(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + dh, _ := newTestDefinitionHandler(t) + ds.Init(dh) + ds.multiparty = false + + ffi := &core.FFI{} + + mcm := dh.contracts.(*contractmocks.Manager) + mcm.On("ResolveFFI", context.Background(), ffi).Return(fmt.Errorf("pop")) + + err := ds.DefineFFI(context.Background(), ffi, false) + assert.Regexp(t, "FF10403", err) + + mcm.AssertExpectations(t) +} + func TestDefineContractAPIResolveFail(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() @@ -161,3 +179,22 @@ func TestDefineContractAPIOk(t *testing.T) { mbm.AssertExpectations(t) mms.AssertExpectations(t) } + +func TestDefineContractAPINonMultiparty(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + dh, _ := newTestDefinitionHandler(t) + ds.Init(dh) + ds.multiparty = false + + url := "http://firefly" + api := &core.ContractAPI{} + + mcm := dh.contracts.(*contractmocks.Manager) + mcm.On("ResolveContractAPI", context.Background(), url, api).Return(fmt.Errorf("pop")) + + err := ds.DefineContractAPI(context.Background(), url, api, false) + assert.Regexp(t, "FF10403", err) + + mcm.AssertExpectations(t) +} diff --git a/internal/definitions/sender_datatype.go b/internal/definitions/sender_datatype.go index c198416e6..7f35fe1c2 100644 --- a/internal/definitions/sender_datatype.go +++ b/internal/definitions/sender_datatype.go @@ -33,17 +33,17 @@ func (bm *definitionSender) DefineDatatype(ctx context.Context, datatype *core.D if datatype.Validator == "" { datatype.Validator = core.ValidatorTypeJSON } - if err := datatype.Validate(ctx, false); err != nil { - return err - } datatype.Hash = datatype.Value.Hash() - // Verify the data type is now all valid, before we broadcast it - if err := bm.data.CheckDatatype(ctx, datatype); err != nil { - return err - } - if bm.multiparty { + if err := datatype.Validate(ctx, false); err != nil { + return err + } + // Verify the data type is now all valid, before we broadcast it + if err := bm.data.CheckDatatype(ctx, datatype); err != nil { + return err + } + msg, err := bm.createDefinitionDefault(ctx, datatype, core.SystemTagDefineDatatype, waitConfirm) if msg != nil { datatype.Message = msg.Header.ID diff --git a/internal/definitions/sender_datatype_test.go b/internal/definitions/sender_datatype_test.go index 5d1393a94..bca20dfa6 100644 --- a/internal/definitions/sender_datatype_test.go +++ b/internal/definitions/sender_datatype_test.go @@ -109,3 +109,17 @@ func TestBroadcastOk(t *testing.T) { mbm.AssertExpectations(t) mms.AssertExpectations(t) } + +func TestDefineDatatypeNonMultiparty(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + ds.multiparty = false + + err := ds.DefineDatatype(context.Background(), &core.Datatype{ + Namespace: "ns1", + Name: "ent1", + Version: "0.0.1", + Value: fftypes.JSONAnyPtr(`{"some": "data"}`), + }, false) + assert.Regexp(t, "FF10414", err) +} diff --git a/internal/definitions/sender_identity_test.go b/internal/definitions/sender_identity_test.go new file mode 100644 index 000000000..02119eeed --- /dev/null +++ b/internal/definitions/sender_identity_test.go @@ -0,0 +1,191 @@ +// Copyright © 2021 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 definitions + +import ( + "fmt" + "testing" + + "github.com/hyperledger/firefly/internal/identity" + "github.com/hyperledger/firefly/mocks/broadcastmocks" + "github.com/hyperledger/firefly/mocks/identitymanagermocks" + "github.com/hyperledger/firefly/mocks/sysmessagingmocks" + "github.com/hyperledger/firefly/pkg/core" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestDefineIdentity(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + + mim := ds.identity.(*identitymanagermocks.Manager) + mbm := ds.broadcast.(*broadcastmocks.Manager) + mms := &sysmessagingmocks.MessageSender{} + + mim.On("NormalizeSigningKey", mock.Anything, "0x1234", identity.KeyNormalizationBlockchainPlugin).Return("", nil) + mbm.On("NewBroadcast", mock.Anything).Return(mms) + mms.On("SendAndWait", mock.Anything).Return(nil) + + ds.multiparty = true + + err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ + Identity: &core.Identity{}, + }, &core.SignerRef{ + Key: "0x1234", + }, nil, core.SystemTagDefineNamespace, true) + assert.NoError(t, err) + + mim.AssertExpectations(t) + mbm.AssertExpectations(t) + mms.AssertExpectations(t) +} + +func TestDefineIdentityFail(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + + mim := ds.identity.(*identitymanagermocks.Manager) + mbm := ds.broadcast.(*broadcastmocks.Manager) + mms := &sysmessagingmocks.MessageSender{} + + mim.On("NormalizeSigningKey", mock.Anything, "0x1234", identity.KeyNormalizationBlockchainPlugin).Return("", nil) + mbm.On("NewBroadcast", mock.Anything).Return(mms) + mms.On("SendAndWait", mock.Anything).Return(fmt.Errorf("pop")) + + ds.multiparty = true + + err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ + Identity: &core.Identity{}, + }, &core.SignerRef{ + Key: "0x1234", + }, nil, core.SystemTagDefineNamespace, true) + assert.EqualError(t, err, "pop") + + mim.AssertExpectations(t) + mbm.AssertExpectations(t) + mms.AssertExpectations(t) +} + +func TestDefineIdentityFailKey(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + + mim := ds.identity.(*identitymanagermocks.Manager) + + mim.On("NormalizeSigningKey", mock.Anything, "0x1234", identity.KeyNormalizationBlockchainPlugin).Return("", fmt.Errorf("pop")) + + ds.multiparty = true + + err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ + Identity: &core.Identity{}, + }, &core.SignerRef{ + Key: "0x1234", + }, nil, core.SystemTagDefineNamespace, true) + assert.EqualError(t, err, "pop") + + mim.AssertExpectations(t) +} + +func TestDefineIdentityChild(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + + mim := ds.identity.(*identitymanagermocks.Manager) + mbm := ds.broadcast.(*broadcastmocks.Manager) + mms1 := &sysmessagingmocks.MessageSender{} + mms2 := &sysmessagingmocks.MessageSender{} + + mim.On("NormalizeSigningKey", mock.Anything, "0x1234", identity.KeyNormalizationBlockchainPlugin).Return("", nil) + mbm.On("NewBroadcast", mock.Anything).Return(mms1).Once() + mbm.On("NewBroadcast", mock.Anything).Return(mms2).Once() + mms1.On("SendAndWait", mock.Anything).Return(nil) + mms2.On("Send", mock.Anything).Return(nil) + mim.On("ResolveInputSigningIdentity", mock.Anything, mock.MatchedBy(func(signer *core.SignerRef) bool { + return signer.Key == "0x2345" + })).Return(nil) + + ds.multiparty = true + + err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ + Identity: &core.Identity{}, + }, &core.SignerRef{ + Key: "0x1234", + }, &core.SignerRef{ + Key: "0x2345", + }, core.SystemTagDefineNamespace, true) + assert.NoError(t, err) + + mim.AssertExpectations(t) + mbm.AssertExpectations(t) + mms1.AssertExpectations(t) +} + +func TestDefineIdentityChildFail(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + + mim := ds.identity.(*identitymanagermocks.Manager) + mbm := ds.broadcast.(*broadcastmocks.Manager) + mms1 := &sysmessagingmocks.MessageSender{} + mms2 := &sysmessagingmocks.MessageSender{} + + mim.On("NormalizeSigningKey", mock.Anything, "0x1234", identity.KeyNormalizationBlockchainPlugin).Return("", nil) + mbm.On("NewBroadcast", mock.Anything).Return(mms1).Once() + mbm.On("NewBroadcast", mock.Anything).Return(mms2).Once() + mms1.On("SendAndWait", mock.Anything).Return(nil) + mms2.On("Send", mock.Anything).Return(fmt.Errorf("pop")) + mim.On("ResolveInputSigningIdentity", mock.Anything, mock.MatchedBy(func(signer *core.SignerRef) bool { + return signer.Key == "0x2345" + })).Return(nil) + + ds.multiparty = true + + err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ + Identity: &core.Identity{}, + }, &core.SignerRef{ + Key: "0x1234", + }, &core.SignerRef{ + Key: "0x2345", + }, core.SystemTagDefineNamespace, true) + assert.EqualError(t, err, "pop") + + mim.AssertExpectations(t) + mbm.AssertExpectations(t) + mms1.AssertExpectations(t) +} + +func TestDefineIdentityNonMultiparty(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + dh, _ := newTestDefinitionHandler(t) + ds.Init(dh) + + mim := dh.identity.(*identitymanagermocks.Manager) + mim.On("VerifyIdentityChain", mock.Anything, mock.AnythingOfType("*core.Identity")).Return(nil, false, fmt.Errorf("pop")) + + ds.multiparty = false + + err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ + Identity: &core.Identity{}, + }, &core.SignerRef{ + Key: "0x1234", + }, nil, core.SystemTagDefineNamespace, true) + assert.NoError(t, err) + + mim.AssertExpectations(t) +} diff --git a/internal/definitions/sender_test.go b/internal/definitions/sender_test.go index 9f949041f..cd952de0f 100644 --- a/internal/definitions/sender_test.go +++ b/internal/definitions/sender_test.go @@ -21,7 +21,6 @@ import ( "fmt" "testing" - "github.com/hyperledger/firefly/internal/identity" "github.com/hyperledger/firefly/mocks/broadcastmocks" "github.com/hyperledger/firefly/mocks/contractmocks" "github.com/hyperledger/firefly/mocks/databasemocks" @@ -78,52 +77,6 @@ func TestCreateDefinitionConfirm(t *testing.T) { mms.AssertExpectations(t) } -func TestCreateIdentityClaim(t *testing.T) { - ds, cancel := newTestDefinitionSender(t) - defer cancel() - - mim := ds.identity.(*identitymanagermocks.Manager) - mbm := ds.broadcast.(*broadcastmocks.Manager) - mms := &sysmessagingmocks.MessageSender{} - - mim.On("NormalizeSigningKey", mock.Anything, "0x1234", identity.KeyNormalizationBlockchainPlugin).Return("", nil) - mbm.On("NewBroadcast", mock.Anything).Return(mms) - mms.On("SendAndWait", mock.Anything).Return(nil) - - ds.multiparty = true - - err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ - Identity: &core.Identity{}, - }, &core.SignerRef{ - Key: "0x1234", - }, nil, core.SystemTagDefineNamespace, true) - assert.NoError(t, err) - - mim.AssertExpectations(t) - mbm.AssertExpectations(t) - mms.AssertExpectations(t) -} - -func TestCreateIdentityClaimFail(t *testing.T) { - ds, cancel := newTestDefinitionSender(t) - defer cancel() - - mim := ds.identity.(*identitymanagermocks.Manager) - - mim.On("NormalizeSigningKey", mock.Anything, "0x1234", identity.KeyNormalizationBlockchainPlugin).Return("", fmt.Errorf("pop")) - - ds.multiparty = true - - err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ - Identity: &core.Identity{}, - }, &core.SignerRef{ - Key: "0x1234", - }, nil, core.SystemTagDefineNamespace, true) - assert.EqualError(t, err, "pop") - - mim.AssertExpectations(t) -} - func TestCreateDatatypeDefinitionAsNodeConfirm(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() diff --git a/internal/definitions/sender_tokenpool.go b/internal/definitions/sender_tokenpool.go index 40041ed52..c0618598d 100644 --- a/internal/definitions/sender_tokenpool.go +++ b/internal/definitions/sender_tokenpool.go @@ -27,6 +27,7 @@ func (bm *definitionSender) DefineTokenPool(ctx context.Context, pool *core.Toke if err := pool.Pool.Validate(ctx); err != nil { return err } + msg, err := bm.createDefinitionDefault(ctx, pool, core.SystemTagDefinePool, waitConfirm) if msg != nil { pool.Pool.Message = msg.Header.ID diff --git a/internal/definitions/sender_tokenpool_test.go b/internal/definitions/sender_tokenpool_test.go index d71b1c71b..4e7ab01a1 100644 --- a/internal/definitions/sender_tokenpool_test.go +++ b/internal/definitions/sender_tokenpool_test.go @@ -33,6 +33,32 @@ import ( func TestBroadcastTokenPoolInvalid(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() + ds.multiparty = true + + mdm := ds.data.(*datamocks.Manager) + + pool := &core.TokenPoolAnnouncement{ + Pool: &core.TokenPool{ + ID: fftypes.NewUUID(), + Namespace: "", + Name: "", + Type: core.TokenTypeNonFungible, + Locator: "N1", + Symbol: "COIN", + }, + } + + err := ds.DefineTokenPool(context.Background(), pool, false) + assert.Regexp(t, "FF00140", err) + + mdm.AssertExpectations(t) +} + +func TestBroadcastTokenPoolInvalidNonMultiparty(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + ds.multiparty = false + mdm := ds.data.(*datamocks.Manager) pool := &core.TokenPoolAnnouncement{ diff --git a/internal/networkmap/register_identity_test.go b/internal/networkmap/register_identity_test.go index cb85c37d8..4daa174c4 100644 --- a/internal/networkmap/register_identity_test.go +++ b/internal/networkmap/register_identity_test.go @@ -115,6 +115,80 @@ func TestRegisterIdentityOrgWithParentWaitConfirmOk(t *testing.T) { msa.AssertExpectations(t) } +func TestRegisterIdentityOrgNonMultiparty(t *testing.T) { + + nm, cancel := newTestNetworkmap(t) + defer cancel() + nm.multiparty = nil + + parentIdentity := testOrg("parent1") + + mim := nm.identity.(*identitymanagermocks.Manager) + mim.On("VerifyIdentityChain", nm.ctx, mock.AnythingOfType("*core.Identity")).Return(parentIdentity, false, nil) + mim.On("CachedIdentityLookupMustExist", nm.ctx, "did:firefly:org/parent1").Return(&core.Identity{ + IdentityBase: core.IdentityBase{ + ID: fftypes.NewUUID(), + DID: "did:firefly:org/parent1", + }, + }, false, nil) + + mds := nm.defsender.(*definitionsmocks.Sender) + mds.On("DefineIdentity", nm.ctx, + mock.AnythingOfType("*core.IdentityClaim"), + mock.MatchedBy(func(sr *core.SignerRef) bool { + return sr.Key == "0x12345" + }), + (*core.SignerRef)(nil), + core.SystemTagIdentityClaim, false).Return(fmt.Errorf("pop")) + + _, err := nm.RegisterIdentity(nm.ctx, &core.IdentityCreateDTO{ + Name: "custom1", + Key: "0x12345", + Parent: "did:firefly:org/parent1", + }, false) + assert.Regexp(t, "pop", err) + + mim.AssertExpectations(t) + mds.AssertExpectations(t) +} + +func TestRegisterIdentityCustomWithParentFail(t *testing.T) { + + nm, cancel := newTestNetworkmap(t) + defer cancel() + + parentIdentity := testOrg("parent1") + + mim := nm.identity.(*identitymanagermocks.Manager) + mim.On("VerifyIdentityChain", nm.ctx, mock.AnythingOfType("*core.Identity")).Return(parentIdentity, false, nil) + mim.On("ResolveIdentitySigner", nm.ctx, parentIdentity).Return(&core.SignerRef{ + Key: "0x23456", + }, nil) + + mds := nm.defsender.(*definitionsmocks.Sender) + + mds.On("DefineIdentity", nm.ctx, + mock.AnythingOfType("*core.IdentityClaim"), + mock.MatchedBy(func(sr *core.SignerRef) bool { + return sr.Key == "0x12345" + }), + mock.MatchedBy(func(sr *core.SignerRef) bool { + return sr.Key == "0x23456" + }), + core.SystemTagIdentityClaim, false).Return(nil) + + org, err := nm.RegisterIdentity(nm.ctx, &core.IdentityCreateDTO{ + Name: "child1", + Key: "0x12345", + Parent: fftypes.NewUUID().String(), + }, false) + assert.NoError(t, err) + assert.NotNil(t, org) + + mim.AssertExpectations(t) + mds.AssertExpectations(t) +} + func TestRegisterIdentityGetParentMsgFail(t *testing.T) { nm, cancel := newTestNetworkmap(t) From 007f8a8e14950e6a1d50a2b0c7e98e896473fbb5 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Tue, 28 Jun 2022 15:47:31 -0400 Subject: [PATCH 23/27] Combine init of definition sender/handler Signed-off-by: Andrew Richardson --- internal/definitions/handler.go | 2 +- internal/definitions/handler_test.go | 6 ++-- internal/definitions/sender.go | 19 +++++++------ internal/definitions/sender_contracts_test.go | 8 ++---- internal/definitions/sender_identity_test.go | 3 +- internal/definitions/sender_test.go | 12 ++++++-- internal/orchestrator/orchestrator.go | 28 ++++--------------- internal/orchestrator/orchestrator_test.go | 9 ------ mocks/definitionsmocks/handler.go | 14 ---------- mocks/definitionsmocks/sender.go | 6 ---- mocks/privatemessagingmocks/manager.go | 14 ---------- 11 files changed, 32 insertions(+), 89 deletions(-) diff --git a/internal/definitions/handler.go b/internal/definitions/handler.go index 042e3211b..6c2f150bb 100644 --- a/internal/definitions/handler.go +++ b/internal/definitions/handler.go @@ -88,7 +88,7 @@ type definitionHandler struct { contracts contracts.Manager } -func NewDefinitionHandler(ctx context.Context, ns string, multiparty bool, di database.Plugin, bi blockchain.Plugin, dx dataexchange.Plugin, dm data.Manager, im identity.Manager, am assets.Manager, cm contracts.Manager) (Handler, error) { +func newDefinitionHandler(ctx context.Context, ns string, multiparty bool, di database.Plugin, bi blockchain.Plugin, dx dataexchange.Plugin, dm data.Manager, im identity.Manager, am assets.Manager, cm contracts.Manager) (*definitionHandler, error) { if di == nil || bi == nil || dm == nil || im == nil || am == nil || cm == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "DefinitionHandler") } diff --git a/internal/definitions/handler_test.go b/internal/definitions/handler_test.go index fb7fe6067..9a8c96805 100644 --- a/internal/definitions/handler_test.go +++ b/internal/definitions/handler_test.go @@ -42,8 +42,8 @@ func newTestDefinitionHandler(t *testing.T) (*definitionHandler, *testDefinition mam := &assetmocks.Manager{} mcm := &contractmocks.Manager{} mbi.On("VerifierType").Return(core.VerifierTypeEthAddress).Maybe() - dh, _ := NewDefinitionHandler(context.Background(), "ns1", false, mdi, mbi, mdx, mdm, mim, mam, mcm) - return dh.(*definitionHandler), newTestDefinitionBatchState(t) + dh, _ := newDefinitionHandler(context.Background(), "ns1", false, mdi, mbi, mdx, mdm, mim, mam, mcm) + return dh, newTestDefinitionBatchState(t) } type testDefinitionBatchState struct { @@ -68,7 +68,7 @@ func (bs *testDefinitionBatchState) assertNoFinalizers() { } func TestInitFail(t *testing.T) { - _, err := NewDefinitionHandler(context.Background(), "", false, nil, nil, nil, nil, nil, nil, nil) + _, err := newDefinitionHandler(context.Background(), "", false, nil, nil, nil, nil, nil, nil, nil) assert.Regexp(t, "FF10128", err) } diff --git a/internal/definitions/sender.go b/internal/definitions/sender.go index ff69e87b9..a7a415a39 100644 --- a/internal/definitions/sender.go +++ b/internal/definitions/sender.go @@ -22,19 +22,21 @@ import ( "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly-common/pkg/i18n" + "github.com/hyperledger/firefly/internal/assets" "github.com/hyperledger/firefly/internal/broadcast" "github.com/hyperledger/firefly/internal/contracts" "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/internal/data" "github.com/hyperledger/firefly/internal/identity" + "github.com/hyperledger/firefly/pkg/blockchain" "github.com/hyperledger/firefly/pkg/core" "github.com/hyperledger/firefly/pkg/database" + "github.com/hyperledger/firefly/pkg/dataexchange" ) type Sender interface { core.Named - Init(handler Handler) CreateDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) DefineDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) error DefineIdentity(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, parentSigner *core.SignerRef, tag string, waitConfirm bool) error @@ -68,11 +70,11 @@ func fakeBatch(ctx context.Context, handler func(context.Context, *core.BatchSta return err } -func NewDefinitionSender(ctx context.Context, ns string, multiparty bool, di database.Plugin, bm broadcast.Manager, im identity.Manager, dm data.Manager, cm contracts.Manager) (Sender, error) { +func NewDefinitionSender(ctx context.Context, ns string, multiparty bool, di database.Plugin, bi blockchain.Plugin, dx dataexchange.Plugin, bm broadcast.Manager, im identity.Manager, dm data.Manager, am assets.Manager, cm contracts.Manager) (Sender, Handler, error) { if di == nil || im == nil || dm == nil || cm == nil { - return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError) + return nil, nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError) } - return &definitionSender{ + ds := &definitionSender{ ctx: ctx, namespace: ns, multiparty: multiparty, @@ -81,17 +83,16 @@ func NewDefinitionSender(ctx context.Context, ns string, multiparty bool, di dat identity: im, data: dm, contracts: cm, - }, nil + } + dh, err := newDefinitionHandler(ctx, ns, multiparty, di, bi, dx, dm, im, am, cm) + ds.handler = dh + return ds, dh, err } func (bm *definitionSender) Name() string { return "DefinitionSender" } -func (bm *definitionSender) Init(handler Handler) { - bm.handler = handler.(*definitionHandler) -} - func (bm *definitionSender) createDefinitionDefault(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) { return bm.CreateDefinition(ctx, def, &core.SignerRef{ /* resolve to node default */ }, tag, waitConfirm) } diff --git a/internal/definitions/sender_contracts_test.go b/internal/definitions/sender_contracts_test.go index e01038ada..1cb017b42 100644 --- a/internal/definitions/sender_contracts_test.go +++ b/internal/definitions/sender_contracts_test.go @@ -99,9 +99,7 @@ func TestDefineFFIOk(t *testing.T) { func TestDefineFFINonMultiparty(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() - dh, _ := newTestDefinitionHandler(t) - ds.Init(dh) - ds.multiparty = false + dh := ds.handler ffi := &core.FFI{} @@ -183,9 +181,7 @@ func TestDefineContractAPIOk(t *testing.T) { func TestDefineContractAPINonMultiparty(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() - dh, _ := newTestDefinitionHandler(t) - ds.Init(dh) - ds.multiparty = false + dh := ds.handler url := "http://firefly" api := &core.ContractAPI{} diff --git a/internal/definitions/sender_identity_test.go b/internal/definitions/sender_identity_test.go index 02119eeed..14e8a9200 100644 --- a/internal/definitions/sender_identity_test.go +++ b/internal/definitions/sender_identity_test.go @@ -172,8 +172,7 @@ func TestDefineIdentityChildFail(t *testing.T) { func TestDefineIdentityNonMultiparty(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() - dh, _ := newTestDefinitionHandler(t) - ds.Init(dh) + dh := ds.handler mim := dh.identity.(*identitymanagermocks.Manager) mim.On("VerifyIdentityChain", mock.Anything, mock.AnythingOfType("*core.Identity")).Return(nil, false, fmt.Errorf("pop")) diff --git a/internal/definitions/sender_test.go b/internal/definitions/sender_test.go index cd952de0f..6b0767352 100644 --- a/internal/definitions/sender_test.go +++ b/internal/definitions/sender_test.go @@ -21,9 +21,12 @@ import ( "fmt" "testing" + "github.com/hyperledger/firefly/mocks/assetmocks" + "github.com/hyperledger/firefly/mocks/blockchainmocks" "github.com/hyperledger/firefly/mocks/broadcastmocks" "github.com/hyperledger/firefly/mocks/contractmocks" "github.com/hyperledger/firefly/mocks/databasemocks" + "github.com/hyperledger/firefly/mocks/dataexchangemocks" "github.com/hyperledger/firefly/mocks/datamocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/mocks/sysmessagingmocks" @@ -34,19 +37,22 @@ import ( func newTestDefinitionSender(t *testing.T) (*definitionSender, func()) { mdi := &databasemocks.Plugin{} + mbi := &blockchainmocks.Plugin{} + mdx := &dataexchangemocks.Plugin{} mbm := &broadcastmocks.Manager{} mim := &identitymanagermocks.Manager{} mdm := &datamocks.Manager{} + mam := &assetmocks.Manager{} mcm := &contractmocks.Manager{} ctx, cancel := context.WithCancel(context.Background()) - b, err := NewDefinitionSender(ctx, "ns1", false, mdi, mbm, mim, mdm, mcm) + ds, _, err := NewDefinitionSender(ctx, "ns1", false, mdi, mbi, mdx, mbm, mim, mdm, mam, mcm) assert.NoError(t, err) - return b.(*definitionSender), cancel + return ds.(*definitionSender), cancel } func TestInitSenderFail(t *testing.T) { - _, err := NewDefinitionSender(context.Background(), "", false, nil, nil, nil, nil, nil) + _, _, err := NewDefinitionSender(context.Background(), "", false, nil, nil, nil, nil, nil, nil, nil, nil) assert.Regexp(t, "FF10128", err) } diff --git a/internal/orchestrator/orchestrator.go b/internal/orchestrator/orchestrator.go index 5ef492663..35d47e703 100644 --- a/internal/orchestrator/orchestrator.go +++ b/internal/orchestrator/orchestrator.go @@ -456,7 +456,7 @@ func (or *orchestrator) initManagers(ctx context.Context) (err error) { } if or.defsender == nil { - or.defsender, err = definitions.NewDefinitionSender(ctx, or.namespace, or.config.Multiparty.Enabled, or.database(), or.broadcast, or.identity, or.data, or.contracts) + or.defsender, or.defhandler, err = definitions.NewDefinitionSender(ctx, or.namespace, or.config.Multiparty.Enabled, or.database(), or.blockchain(), or.dataexchange(), or.broadcast, or.identity, or.data, or.assets, or.contracts) if err != nil { return err } @@ -472,24 +472,6 @@ func (or *orchestrator) initManagers(ctx context.Context) (err error) { return nil } -func (or *orchestrator) initHandlers(ctx context.Context) (err error) { - if or.defhandler == nil { - or.defhandler, err = definitions.NewDefinitionHandler(ctx, or.namespace, or.config.Multiparty.Enabled, or.database(), or.blockchain(), or.dataexchange(), or.data, or.identity, or.assets, or.contracts) - if err != nil { - return err - } - } - - if or.events == nil { - or.events, err = events.NewEventManager(ctx, or.namespace, or, or.database(), or.blockchain(), or.identity, or.defhandler, or.data, or.defsender, or.broadcast, or.messaging, or.assets, or.sharedDownload, or.metrics, or.txHelper, or.plugins.Events, or.multiparty) - if err != nil { - return err - } - } - - return nil -} - func (or *orchestrator) initComponents(ctx context.Context) (err error) { if or.data == nil { or.data, err = data.NewDataManager(ctx, or.namespace, or.database(), or.dataexchange()) @@ -502,12 +484,14 @@ func (or *orchestrator) initComponents(ctx context.Context) (err error) { return err } - if err := or.initHandlers(ctx); err != nil { - return err + if or.events == nil { + or.events, err = events.NewEventManager(ctx, or.namespace, or, or.database(), or.blockchain(), or.identity, or.defhandler, or.data, or.defsender, or.broadcast, or.messaging, or.assets, or.sharedDownload, or.metrics, or.txHelper, or.plugins.Events, or.multiparty) + if err != nil { + return err + } } or.syncasync.Init(or.events) - or.defsender.Init(or.defhandler) return nil } diff --git a/internal/orchestrator/orchestrator_test.go b/internal/orchestrator/orchestrator_test.go index c17a58912..3851a6a2b 100644 --- a/internal/orchestrator/orchestrator_test.go +++ b/internal/orchestrator/orchestrator_test.go @@ -348,15 +348,6 @@ func TestInitContractsComponentFail(t *testing.T) { assert.Regexp(t, "FF10128", err) } -func TestInitDefinitionsComponentFail(t *testing.T) { - or := newTestOrchestrator() - defer or.cleanup(t) - or.plugins.Database.Plugin = nil - or.defhandler = nil - err := or.initComponents(context.Background()) - assert.Regexp(t, "FF10128", err) -} - func TestInitOperationsComponentFail(t *testing.T) { or := newTestOrchestrator() defer or.cleanup(t) diff --git a/mocks/definitionsmocks/handler.go b/mocks/definitionsmocks/handler.go index fcf599ed0..acd7e4667 100644 --- a/mocks/definitionsmocks/handler.go +++ b/mocks/definitionsmocks/handler.go @@ -18,20 +18,6 @@ type Handler struct { mock.Mock } -// HandleDefinition provides a mock function with given fields: ctx, state, msg, data -func (_m *Handler) HandleDefinition(ctx context.Context, state *core.BatchState, msg *core.Message, data *core.Data) error { - ret := _m.Called(ctx, state, msg, data) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *core.BatchState, *core.Message, *core.Data) error); ok { - r0 = rf(ctx, state, msg, data) - } else { - r0 = ret.Error(0) - } - - return r0 -} - // HandleDefinitionBroadcast provides a mock function with given fields: ctx, state, msg, data, tx func (_m *Handler) HandleDefinitionBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray, tx *fftypes.UUID) (definitions.HandlerResult, error) { ret := _m.Called(ctx, state, msg, data, tx) diff --git a/mocks/definitionsmocks/sender.go b/mocks/definitionsmocks/sender.go index d2ce92ee5..8332d04fa 100644 --- a/mocks/definitionsmocks/sender.go +++ b/mocks/definitionsmocks/sender.go @@ -5,7 +5,6 @@ package definitionsmocks import ( context "context" - definitions "github.com/hyperledger/firefly/internal/definitions" core "github.com/hyperledger/firefly/pkg/core" mock "github.com/stretchr/testify/mock" @@ -109,11 +108,6 @@ func (_m *Sender) DefineTokenPool(ctx context.Context, pool *core.TokenPoolAnnou return r0 } -// Init provides a mock function with given fields: handler -func (_m *Sender) Init(handler definitions.Handler) { - _m.Called(handler) -} - // Name provides a mock function with given fields: func (_m *Sender) Name() string { ret := _m.Called() diff --git a/mocks/privatemessagingmocks/manager.go b/mocks/privatemessagingmocks/manager.go index dc6ae416f..15eba3c57 100644 --- a/mocks/privatemessagingmocks/manager.go +++ b/mocks/privatemessagingmocks/manager.go @@ -247,17 +247,3 @@ func (_m *Manager) SendMessage(ctx context.Context, in *core.MessageInOut, waitC return r0, r1 } - -// Start provides a mock function with given fields: -func (_m *Manager) Start() error { - ret := _m.Called() - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} From 03989ebbbea2254174e407052c625dfef65b5488 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Tue, 28 Jun 2022 16:25:19 -0400 Subject: [PATCH 24/27] Fix up identity update path Signed-off-by: Andrew Richardson --- .../definitions/handler_identity_claim.go | 8 +- .../definitions/handler_identity_update.go | 23 ++++-- .../handler_identity_update_test.go | 1 + internal/definitions/sender.go | 32 ++++---- internal/definitions/sender_contracts.go | 4 +- internal/definitions/sender_datatype.go | 2 +- internal/definitions/sender_identity.go | 20 ++++- internal/definitions/sender_identity_test.go | 80 ++++++++++++++----- internal/definitions/sender_test.go | 6 +- internal/definitions/sender_tokenpool.go | 2 +- internal/networkmap/register_identity.go | 2 +- internal/networkmap/register_identity_test.go | 16 ++-- internal/networkmap/register_node_test.go | 4 +- internal/networkmap/register_org_test.go | 4 +- internal/networkmap/update_identity.go | 9 +-- internal/networkmap/update_identity_test.go | 13 +-- mocks/definitionsmocks/sender.go | 53 +++++------- 17 files changed, 167 insertions(+), 112 deletions(-) diff --git a/internal/definitions/handler_identity_claim.go b/internal/definitions/handler_identity_claim.go index 458439c1b..442f021c1 100644 --- a/internal/definitions/handler_identity_claim.go +++ b/internal/definitions/handler_identity_claim.go @@ -53,6 +53,7 @@ func (dh *definitionHandler) handleIdentityClaimBroadcast(ctx context.Context, s if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &claim); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "identity claim", msg.Header.ID) } + claim.Identity.Messages.Claim = msg.Header.ID return dh.handleIdentityClaim(ctx, state, buildIdentityMsgInfo(msg, verifyMsgID), &claim) } @@ -151,9 +152,10 @@ func (dh *definitionHandler) handleIdentityClaim(ctx context.Context, state *cor identity := identityClaim.Identity parent, retryable, err := dh.identity.VerifyIdentityChain(ctx, identity) - if err != nil && retryable { - return HandlerResult{Action: ActionRetry}, err - } else if err != nil { + if err != nil { + if retryable { + return HandlerResult{Action: ActionRetry}, err + } // This cannot be processed as something in the identity chain is invalid. // We treat this as a park - because we don't know if the parent identity // will be processed after this message and generate a rewind. diff --git a/internal/definitions/handler_identity_update.go b/internal/definitions/handler_identity_update.go index 72dc10615..d6d9f32eb 100644 --- a/internal/definitions/handler_identity_update.go +++ b/internal/definitions/handler_identity_update.go @@ -19,19 +19,32 @@ package definitions import ( "context" + "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly/internal/coremsgs" "github.com/hyperledger/firefly/pkg/core" "github.com/hyperledger/firefly/pkg/database" ) +type identityUpdateMsgInfo struct { + ID *fftypes.UUID + Author string +} + func (dh *definitionHandler) handleIdentityUpdateBroadcast(ctx context.Context, state *core.BatchState, msg *core.Message, data core.DataArray) (HandlerResult, error) { var update core.IdentityUpdate if valid := dh.getSystemBroadcastPayload(ctx, msg, data, &update); !valid { return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedBadPayload, "identity update", msg.Header.ID) } + return dh.handleIdentityUpdate(ctx, state, &identityUpdateMsgInfo{ + ID: msg.Header.ID, + Author: msg.Header.Author, + }, &update) +} + +func (dh *definitionHandler) handleIdentityUpdate(ctx context.Context, state *core.BatchState, msg *identityUpdateMsgInfo, update *core.IdentityUpdate) (HandlerResult, error) { if err := update.Identity.Validate(ctx); err != nil { - return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedValidateFail, "identity update", msg.Header.ID, err) + return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedValidateFail, "identity update", update.Identity.ID, err) } // Get the existing identity (must be a confirmed identity at the point an update is issued) @@ -40,17 +53,17 @@ func (dh *definitionHandler) handleIdentityUpdateBroadcast(ctx context.Context, return HandlerResult{Action: ActionRetry}, err } if identity == nil { - return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedIdentityNotFound, "identity update", msg.Header.ID, update.Identity.ID) + return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedIdentityNotFound, "identity update", update.Identity.ID, update.Identity.ID) } // Check the author matches - if identity.DID != msg.Header.Author { - return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedWrongAuthor, "identity update", msg.Header.ID, msg.Header.Author) + if dh.multiparty && identity.DID != msg.Author { + return HandlerResult{Action: ActionReject}, i18n.NewError(ctx, coremsgs.MsgDefRejectedWrongAuthor, "identity update", update.Identity.ID, msg.Author) } // Update the profile identity.IdentityProfile = update.Updates - identity.Messages.Update = msg.Header.ID + identity.Messages.Update = msg.ID err = dh.database.UpsertIdentity(ctx, identity, database.UpsertOptimizationExisting) if err != nil { return HandlerResult{Action: ActionRetry}, err diff --git a/internal/definitions/handler_identity_update_test.go b/internal/definitions/handler_identity_update_test.go index 4772497aa..ccabbe31f 100644 --- a/internal/definitions/handler_identity_update_test.go +++ b/internal/definitions/handler_identity_update_test.go @@ -122,6 +122,7 @@ func TestHandleDefinitionIdentityUpdateUpsertFail(t *testing.T) { func TestHandleDefinitionIdentityInvalidIdentity(t *testing.T) { dh, bs := newTestDefinitionHandler(t) ctx := context.Background() + dh.multiparty = true org1, updateMsg, updateData, _ := testIdentityUpdate(t) updateMsg.Header.Author = "wrong" diff --git a/internal/definitions/sender.go b/internal/definitions/sender.go index a7a415a39..fe85cb0c3 100644 --- a/internal/definitions/sender.go +++ b/internal/definitions/sender.go @@ -37,9 +37,9 @@ import ( type Sender interface { core.Named - CreateDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) + ClaimIdentity(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, parentSigner *core.SignerRef, waitConfirm bool) error + UpdateIdentity(ctx context.Context, identity *core.Identity, def *core.IdentityUpdate, signingIdentity *core.SignerRef, waitConfirm bool) error DefineDatatype(ctx context.Context, datatype *core.Datatype, waitConfirm bool) error - DefineIdentity(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, parentSigner *core.SignerRef, tag string, waitConfirm bool) error DefineTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) error DefineFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool) error DefineContractAPI(ctx context.Context, httpServerURL string, api *core.ContractAPI, waitConfirm bool) error @@ -93,23 +93,21 @@ func (bm *definitionSender) Name() string { return "DefinitionSender" } -func (bm *definitionSender) createDefinitionDefault(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) { - return bm.CreateDefinition(ctx, def, &core.SignerRef{ /* resolve to node default */ }, tag, waitConfirm) +func (bm *definitionSender) sendDefinitionDefault(ctx context.Context, def core.Definition, tag string, waitConfirm bool) (msg *core.Message, err error) { + return bm.sendDefinition(ctx, def, &core.SignerRef{ /* resolve to node default */ }, tag, waitConfirm) } -func (bm *definitionSender) CreateDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { +func (bm *definitionSender) sendDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (msg *core.Message, err error) { - if bm.multiparty { - err = bm.identity.ResolveInputSigningIdentity(ctx, signingIdentity) - if err != nil { - return nil, err - } + err = bm.identity.ResolveInputSigningIdentity(ctx, signingIdentity) + if err != nil { + return nil, err } - return bm.createDefinitionCommon(ctx, def, signingIdentity, tag, waitConfirm) + return bm.sendDefinitionCommon(ctx, def, signingIdentity, tag, waitConfirm) } -func (bm *definitionSender) createDefinitionCommon(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { +func (bm *definitionSender) sendDefinitionCommon(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { b, err := json.Marshal(&def) if err != nil { @@ -124,16 +122,14 @@ func (bm *definitionSender) createDefinitionCommon(ctx context.Context, def core Topics: core.FFStringArray{def.Topic()}, Tag: tag, TxType: core.TransactionTypeBatchPin, + SignerRef: *signingIdentity, }, }, - } - if signingIdentity != nil { - message.Header.SignerRef = *signingIdentity + InlineData: core.InlineData{ + &core.DataRefOrValue{Value: dataValue}, + }, } - message.InlineData = core.InlineData{ - &core.DataRefOrValue{Value: dataValue}, - } sender := bm.broadcast.NewBroadcast(message) if waitConfirm { err = sender.SendAndWait(ctx) diff --git a/internal/definitions/sender_contracts.go b/internal/definitions/sender_contracts.go index cf9640d96..59026521b 100644 --- a/internal/definitions/sender_contracts.go +++ b/internal/definitions/sender_contracts.go @@ -38,7 +38,7 @@ func (bm *definitionSender) DefineFFI(ctx context.Context, ffi *core.FFI, waitCo return err } - msg, err := bm.createDefinitionDefault(ctx, ffi, core.SystemTagDefineFFI, waitConfirm) + msg, err := bm.sendDefinitionDefault(ctx, ffi, core.SystemTagDefineFFI, waitConfirm) if msg != nil { ffi.Message = msg.Header.ID } @@ -59,7 +59,7 @@ func (bm *definitionSender) DefineContractAPI(ctx context.Context, httpServerURL return err } - msg, err := bm.createDefinitionDefault(ctx, api, core.SystemTagDefineContractAPI, waitConfirm) + msg, err := bm.sendDefinitionDefault(ctx, api, core.SystemTagDefineContractAPI, waitConfirm) if msg != nil { api.Message = msg.Header.ID } diff --git a/internal/definitions/sender_datatype.go b/internal/definitions/sender_datatype.go index 7f35fe1c2..4d26cd397 100644 --- a/internal/definitions/sender_datatype.go +++ b/internal/definitions/sender_datatype.go @@ -44,7 +44,7 @@ func (bm *definitionSender) DefineDatatype(ctx context.Context, datatype *core.D return err } - msg, err := bm.createDefinitionDefault(ctx, datatype, core.SystemTagDefineDatatype, waitConfirm) + msg, err := bm.sendDefinitionDefault(ctx, datatype, core.SystemTagDefineDatatype, waitConfirm) if msg != nil { datatype.Message = msg.Header.ID } diff --git a/internal/definitions/sender_identity.go b/internal/definitions/sender_identity.go index e2657ea56..757f07b1e 100644 --- a/internal/definitions/sender_identity.go +++ b/internal/definitions/sender_identity.go @@ -23,9 +23,9 @@ import ( "github.com/hyperledger/firefly/pkg/core" ) -// DefineIdentity is a special form of CreateDefinition where the signing identity does not need to have been pre-registered +// ClaimIdentity is a special form of CreateDefinition where the signing identity does not need to have been pre-registered // The blockchain "key" will be normalized, but the "author" will pass through unchecked -func (bm *definitionSender) DefineIdentity(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, parentSigner *core.SignerRef, tag string, waitConfirm bool) error { +func (bm *definitionSender) ClaimIdentity(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, parentSigner *core.SignerRef, waitConfirm bool) error { if bm.multiparty { var err error signingIdentity.Key, err = bm.identity.NormalizeSigningKey(ctx, signingIdentity.Key, identity.KeyNormalizationBlockchainPlugin) @@ -33,7 +33,7 @@ func (bm *definitionSender) DefineIdentity(ctx context.Context, def *core.Identi return err } - claimMsg, err := bm.createDefinitionCommon(ctx, def, signingIdentity, tag, waitConfirm) + claimMsg, err := bm.sendDefinitionCommon(ctx, def, signingIdentity, core.SystemTagIdentityClaim, waitConfirm) if err != nil { return err } @@ -41,7 +41,7 @@ func (bm *definitionSender) DefineIdentity(ctx context.Context, def *core.Identi // Send the verification if one is required. if parentSigner != nil { - verifyMsg, err := bm.CreateDefinition(ctx, &core.IdentityVerification{ + verifyMsg, err := bm.sendDefinition(ctx, &core.IdentityVerification{ Claim: core.MessageRef{ ID: claimMsg.Header.ID, Hash: claimMsg.Hash, @@ -61,3 +61,15 @@ func (bm *definitionSender) DefineIdentity(ctx context.Context, def *core.Identi return bm.handler.handleIdentityClaim(ctx, state, &identityMsgInfo{SignerRef: *signingIdentity}, def) }) } + +func (bm *definitionSender) UpdateIdentity(ctx context.Context, identity *core.Identity, def *core.IdentityUpdate, signingIdentity *core.SignerRef, waitConfirm bool) error { + if bm.multiparty { + updateMsg, err := bm.sendDefinition(ctx, def, signingIdentity, core.SystemTagIdentityUpdate, waitConfirm) + identity.Messages.Update = updateMsg.Header.ID + return err + } + + return fakeBatch(ctx, func(ctx context.Context, state *core.BatchState) (HandlerResult, error) { + return bm.handler.handleIdentityUpdate(ctx, state, &identityUpdateMsgInfo{}, def) + }) +} diff --git a/internal/definitions/sender_identity_test.go b/internal/definitions/sender_identity_test.go index 14e8a9200..a239a2c9b 100644 --- a/internal/definitions/sender_identity_test.go +++ b/internal/definitions/sender_identity_test.go @@ -29,7 +29,7 @@ import ( "github.com/stretchr/testify/mock" ) -func TestDefineIdentity(t *testing.T) { +func TestClaimIdentity(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() @@ -43,11 +43,11 @@ func TestDefineIdentity(t *testing.T) { ds.multiparty = true - err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ + err := ds.ClaimIdentity(ds.ctx, &core.IdentityClaim{ Identity: &core.Identity{}, }, &core.SignerRef{ Key: "0x1234", - }, nil, core.SystemTagDefineNamespace, true) + }, nil, true) assert.NoError(t, err) mim.AssertExpectations(t) @@ -55,7 +55,7 @@ func TestDefineIdentity(t *testing.T) { mms.AssertExpectations(t) } -func TestDefineIdentityFail(t *testing.T) { +func TestClaimIdentityFail(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() @@ -69,11 +69,11 @@ func TestDefineIdentityFail(t *testing.T) { ds.multiparty = true - err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ + err := ds.ClaimIdentity(ds.ctx, &core.IdentityClaim{ Identity: &core.Identity{}, }, &core.SignerRef{ Key: "0x1234", - }, nil, core.SystemTagDefineNamespace, true) + }, nil, true) assert.EqualError(t, err, "pop") mim.AssertExpectations(t) @@ -81,7 +81,7 @@ func TestDefineIdentityFail(t *testing.T) { mms.AssertExpectations(t) } -func TestDefineIdentityFailKey(t *testing.T) { +func TestClaimIdentityFailKey(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() @@ -91,17 +91,17 @@ func TestDefineIdentityFailKey(t *testing.T) { ds.multiparty = true - err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ + err := ds.ClaimIdentity(ds.ctx, &core.IdentityClaim{ Identity: &core.Identity{}, }, &core.SignerRef{ Key: "0x1234", - }, nil, core.SystemTagDefineNamespace, true) + }, nil, true) assert.EqualError(t, err, "pop") mim.AssertExpectations(t) } -func TestDefineIdentityChild(t *testing.T) { +func TestClaimIdentityChild(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() @@ -121,13 +121,13 @@ func TestDefineIdentityChild(t *testing.T) { ds.multiparty = true - err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ + err := ds.ClaimIdentity(ds.ctx, &core.IdentityClaim{ Identity: &core.Identity{}, }, &core.SignerRef{ Key: "0x1234", }, &core.SignerRef{ Key: "0x2345", - }, core.SystemTagDefineNamespace, true) + }, true) assert.NoError(t, err) mim.AssertExpectations(t) @@ -135,7 +135,7 @@ func TestDefineIdentityChild(t *testing.T) { mms1.AssertExpectations(t) } -func TestDefineIdentityChildFail(t *testing.T) { +func TestClaimIdentityChildFail(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() @@ -155,13 +155,13 @@ func TestDefineIdentityChildFail(t *testing.T) { ds.multiparty = true - err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ + err := ds.ClaimIdentity(ds.ctx, &core.IdentityClaim{ Identity: &core.Identity{}, }, &core.SignerRef{ Key: "0x1234", }, &core.SignerRef{ Key: "0x2345", - }, core.SystemTagDefineNamespace, true) + }, true) assert.EqualError(t, err, "pop") mim.AssertExpectations(t) @@ -169,7 +169,7 @@ func TestDefineIdentityChildFail(t *testing.T) { mms1.AssertExpectations(t) } -func TestDefineIdentityNonMultiparty(t *testing.T) { +func TestClaimIdentityNonMultiparty(t *testing.T) { ds, cancel := newTestDefinitionSender(t) defer cancel() dh := ds.handler @@ -179,12 +179,56 @@ func TestDefineIdentityNonMultiparty(t *testing.T) { ds.multiparty = false - err := ds.DefineIdentity(ds.ctx, &core.IdentityClaim{ + err := ds.ClaimIdentity(ds.ctx, &core.IdentityClaim{ Identity: &core.Identity{}, }, &core.SignerRef{ Key: "0x1234", - }, nil, core.SystemTagDefineNamespace, true) + }, nil, true) assert.NoError(t, err) mim.AssertExpectations(t) } + +func TestUpdateIdentity(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + + mim := ds.identity.(*identitymanagermocks.Manager) + mbm := ds.broadcast.(*broadcastmocks.Manager) + mms := &sysmessagingmocks.MessageSender{} + + mbm.On("NewBroadcast", mock.Anything).Return(mms) + mms.On("Send", mock.Anything).Return(nil) + mim.On("ResolveInputSigningIdentity", mock.Anything, mock.MatchedBy(func(signer *core.SignerRef) bool { + return signer.Key == "0x1234" + })).Return(nil) + + ds.multiparty = true + + err := ds.UpdateIdentity(ds.ctx, &core.Identity{}, &core.IdentityUpdate{ + Identity: core.IdentityBase{}, + Updates: core.IdentityProfile{}, + }, &core.SignerRef{ + Key: "0x1234", + }, false) + assert.NoError(t, err) + + mim.AssertExpectations(t) + mbm.AssertExpectations(t) + mms.AssertExpectations(t) +} + +func TestUpdateIdentityNonMultiparty(t *testing.T) { + ds, cancel := newTestDefinitionSender(t) + defer cancel() + + ds.multiparty = false + + err := ds.UpdateIdentity(ds.ctx, &core.Identity{}, &core.IdentityUpdate{ + Identity: core.IdentityBase{}, + Updates: core.IdentityProfile{}, + }, &core.SignerRef{ + Key: "0x1234", + }, false) + assert.Regexp(t, "FF10403", err) +} diff --git a/internal/definitions/sender_test.go b/internal/definitions/sender_test.go index 6b0767352..a53a4e617 100644 --- a/internal/definitions/sender_test.go +++ b/internal/definitions/sender_test.go @@ -75,7 +75,7 @@ func TestCreateDefinitionConfirm(t *testing.T) { mms.On("SendAndWait", mock.Anything).Return(nil) ds.multiparty = true - _, err := ds.createDefinitionDefault(ds.ctx, &core.Namespace{}, core.SystemTagDefineNamespace, true) + _, err := ds.sendDefinitionDefault(ds.ctx, &core.Namespace{}, core.SystemTagDefineNamespace, true) assert.NoError(t, err) mim.AssertExpectations(t) @@ -97,7 +97,7 @@ func TestCreateDatatypeDefinitionAsNodeConfirm(t *testing.T) { ds.multiparty = true - _, err := ds.createDefinitionDefault(ds.ctx, &core.Datatype{}, core.SystemTagDefineNamespace, true) + _, err := ds.sendDefinitionDefault(ds.ctx, &core.Datatype{}, core.SystemTagDefineNamespace, true) assert.NoError(t, err) mim.AssertExpectations(t) @@ -113,7 +113,7 @@ func TestCreateDefinitionBadIdentity(t *testing.T) { mim := ds.identity.(*identitymanagermocks.Manager) mim.On("ResolveInputSigningIdentity", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) - _, err := ds.CreateDefinition(ds.ctx, &core.Namespace{}, &core.SignerRef{ + _, err := ds.sendDefinition(ds.ctx, &core.Namespace{}, &core.SignerRef{ Author: "wrong", Key: "wrong", }, core.SystemTagDefineNamespace, false) diff --git a/internal/definitions/sender_tokenpool.go b/internal/definitions/sender_tokenpool.go index c0618598d..0889002a3 100644 --- a/internal/definitions/sender_tokenpool.go +++ b/internal/definitions/sender_tokenpool.go @@ -28,7 +28,7 @@ func (bm *definitionSender) DefineTokenPool(ctx context.Context, pool *core.Toke return err } - msg, err := bm.createDefinitionDefault(ctx, pool, core.SystemTagDefinePool, waitConfirm) + msg, err := bm.sendDefinitionDefault(ctx, pool, core.SystemTagDefinePool, waitConfirm) if msg != nil { pool.Pool.Message = msg.Header.ID } diff --git a/internal/networkmap/register_identity.go b/internal/networkmap/register_identity.go index 1605d7a8b..43a4c218b 100644 --- a/internal/networkmap/register_identity.go +++ b/internal/networkmap/register_identity.go @@ -111,5 +111,5 @@ func (nm *networkMap) RegisterIdentity(ctx context.Context, dto *core.IdentityCr } func (nm *networkMap) sendIdentityRequest(ctx context.Context, identity *core.Identity, claimSigner *core.SignerRef, parentSigner *core.SignerRef) error { - return nm.defsender.DefineIdentity(ctx, &core.IdentityClaim{Identity: identity}, claimSigner, parentSigner, core.SystemTagIdentityClaim, false) + return nm.defsender.ClaimIdentity(ctx, &core.IdentityClaim{Identity: identity}, claimSigner, parentSigner, false) } diff --git a/internal/networkmap/register_identity_test.go b/internal/networkmap/register_identity_test.go index 4daa174c4..b026bfbf9 100644 --- a/internal/networkmap/register_identity_test.go +++ b/internal/networkmap/register_identity_test.go @@ -46,7 +46,7 @@ func TestRegisterIdentityOrgWithParentOk(t *testing.T) { mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("DefineIdentity", nm.ctx, + mds.On("ClaimIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" @@ -54,7 +54,7 @@ func TestRegisterIdentityOrgWithParentOk(t *testing.T) { mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x23456" }), - core.SystemTagIdentityClaim, false).Return(nil) + false).Return(nil) org, err := nm.RegisterIdentity(nm.ctx, &core.IdentityCreateDTO{ Name: "child1", @@ -93,7 +93,7 @@ func TestRegisterIdentityOrgWithParentWaitConfirmOk(t *testing.T) { mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("DefineIdentity", nm.ctx, + mds.On("ClaimIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" @@ -101,7 +101,7 @@ func TestRegisterIdentityOrgWithParentWaitConfirmOk(t *testing.T) { mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x23456" }), - core.SystemTagIdentityClaim, false).Return(nil) + false).Return(nil) _, err := nm.RegisterIdentity(nm.ctx, &core.IdentityCreateDTO{ Name: "child1", @@ -133,13 +133,13 @@ func TestRegisterIdentityOrgNonMultiparty(t *testing.T) { }, false, nil) mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("DefineIdentity", nm.ctx, + mds.On("ClaimIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" }), (*core.SignerRef)(nil), - core.SystemTagIdentityClaim, false).Return(fmt.Errorf("pop")) + false).Return(fmt.Errorf("pop")) _, err := nm.RegisterIdentity(nm.ctx, &core.IdentityCreateDTO{ Name: "custom1", @@ -167,7 +167,7 @@ func TestRegisterIdentityCustomWithParentFail(t *testing.T) { mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("DefineIdentity", nm.ctx, + mds.On("ClaimIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" @@ -175,7 +175,7 @@ func TestRegisterIdentityCustomWithParentFail(t *testing.T) { mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x23456" }), - core.SystemTagIdentityClaim, false).Return(nil) + false).Return(nil) org, err := nm.RegisterIdentity(nm.ctx, &core.IdentityCreateDTO{ Name: "child1", diff --git a/internal/networkmap/register_node_test.go b/internal/networkmap/register_node_test.go index c7e6f8e27..092ee0f49 100644 --- a/internal/networkmap/register_node_test.go +++ b/internal/networkmap/register_node_test.go @@ -55,11 +55,11 @@ func TestRegisterNodeOk(t *testing.T) { }, nil) mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("DefineIdentity", nm.ctx, + mds.On("ClaimIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), signerRef, (*core.SignerRef)(nil), - core.SystemTagIdentityClaim, false).Return(nil) + false).Return(nil) node, err := nm.RegisterNode(nm.ctx, false) assert.NoError(t, err) diff --git a/internal/networkmap/register_org_test.go b/internal/networkmap/register_org_test.go index 8935dee02..ae4ed84c5 100644 --- a/internal/networkmap/register_org_test.go +++ b/internal/networkmap/register_org_test.go @@ -68,13 +68,13 @@ func TestRegisterNodeOrgOk(t *testing.T) { mmp.On("RootOrg").Return(multiparty.RootOrg{Name: "org0"}) mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("DefineIdentity", nm.ctx, + mds.On("ClaimIdentity", nm.ctx, mock.AnythingOfType("*core.IdentityClaim"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" }), (*core.SignerRef)(nil), - core.SystemTagIdentityClaim, false).Return(nil) + false).Return(nil) org, err := nm.RegisterNodeOrganization(nm.ctx, false) assert.NoError(t, err) diff --git a/internal/networkmap/update_identity.go b/internal/networkmap/update_identity.go index 244b5e80a..a7435182e 100644 --- a/internal/networkmap/update_identity.go +++ b/internal/networkmap/update_identity.go @@ -60,14 +60,9 @@ func (nm *networkMap) updateIdentityID(ctx context.Context, id *fftypes.UUID, dt } // Send the update - updateMsg, err := nm.defsender.CreateDefinition(ctx, &core.IdentityUpdate{ + err = nm.defsender.UpdateIdentity(ctx, identity, &core.IdentityUpdate{ Identity: identity.IdentityBase, Updates: dto.IdentityProfile, - }, updateSigner, core.SystemTagIdentityUpdate, waitConfirm) - if err != nil { - return nil, err - } - identity.Messages.Update = updateMsg.Header.ID - + }, updateSigner, waitConfirm) return identity, err } diff --git a/internal/networkmap/update_identity_test.go b/internal/networkmap/update_identity_test.go index dae28e9f4..20f0ce921 100644 --- a/internal/networkmap/update_identity_test.go +++ b/internal/networkmap/update_identity_test.go @@ -40,15 +40,15 @@ func TestUpdateIdentityProfileOk(t *testing.T) { signerRef := &core.SignerRef{Key: "0x12345"} mim.On("ResolveIdentitySigner", nm.ctx, identity).Return(signerRef, nil) - mockMsg1 := &core.Message{Header: core.MessageHeader{ID: fftypes.NewUUID()}} mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("CreateDefinition", nm.ctx, + mds.On("UpdateIdentity", nm.ctx, + mock.AnythingOfType("*core.Identity"), mock.AnythingOfType("*core.IdentityUpdate"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" }), - core.SystemTagIdentityUpdate, true).Return(mockMsg1, nil) + true).Return(nil) org, err := nm.UpdateIdentity(nm.ctx, identity.ID.String(), &core.IdentityUpdateDTO{ IdentityProfile: core.IdentityProfile{ @@ -57,7 +57,7 @@ func TestUpdateIdentityProfileOk(t *testing.T) { }, }, true) assert.NoError(t, err) - assert.Equal(t, *mockMsg1.Header.ID, *org.Messages.Update) + assert.NotNil(t, org) mim.AssertExpectations(t) mds.AssertExpectations(t) @@ -76,12 +76,13 @@ func TestUpdateIdentityProfileBroadcastFail(t *testing.T) { mim.On("ResolveIdentitySigner", nm.ctx, identity).Return(signerRef, nil) mds := nm.defsender.(*definitionsmocks.Sender) - mds.On("CreateDefinition", nm.ctx, + mds.On("UpdateIdentity", nm.ctx, + mock.AnythingOfType("*core.Identity"), mock.AnythingOfType("*core.IdentityUpdate"), mock.MatchedBy(func(sr *core.SignerRef) bool { return sr.Key == "0x12345" }), - core.SystemTagIdentityUpdate, true).Return(nil, fmt.Errorf("pop")) + true).Return(fmt.Errorf("pop")) _, err := nm.UpdateIdentity(nm.ctx, identity.ID.String(), &core.IdentityUpdateDTO{ IdentityProfile: core.IdentityProfile{ diff --git a/mocks/definitionsmocks/sender.go b/mocks/definitionsmocks/sender.go index 8332d04fa..102ecbfa2 100644 --- a/mocks/definitionsmocks/sender.go +++ b/mocks/definitionsmocks/sender.go @@ -15,27 +15,18 @@ type Sender struct { mock.Mock } -// CreateDefinition provides a mock function with given fields: ctx, def, signingIdentity, tag, waitConfirm -func (_m *Sender) CreateDefinition(ctx context.Context, def core.Definition, signingIdentity *core.SignerRef, tag string, waitConfirm bool) (*core.Message, error) { - ret := _m.Called(ctx, def, signingIdentity, tag, waitConfirm) +// ClaimIdentity provides a mock function with given fields: ctx, def, signingIdentity, parentSigner, waitConfirm +func (_m *Sender) ClaimIdentity(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, parentSigner *core.SignerRef, waitConfirm bool) error { + ret := _m.Called(ctx, def, signingIdentity, parentSigner, waitConfirm) - var r0 *core.Message - if rf, ok := ret.Get(0).(func(context.Context, core.Definition, *core.SignerRef, string, bool) *core.Message); ok { - r0 = rf(ctx, def, signingIdentity, tag, waitConfirm) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*core.Message) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, core.Definition, *core.SignerRef, string, bool) error); ok { - r1 = rf(ctx, def, signingIdentity, tag, waitConfirm) + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *core.IdentityClaim, *core.SignerRef, *core.SignerRef, bool) error); ok { + r0 = rf(ctx, def, signingIdentity, parentSigner, waitConfirm) } else { - r1 = ret.Error(1) + r0 = ret.Error(0) } - return r0, r1 + return r0 } // DefineContractAPI provides a mock function with given fields: ctx, httpServerURL, api, waitConfirm @@ -80,20 +71,6 @@ func (_m *Sender) DefineFFI(ctx context.Context, ffi *core.FFI, waitConfirm bool return r0 } -// DefineIdentity provides a mock function with given fields: ctx, def, signingIdentity, parentSigner, tag, waitConfirm -func (_m *Sender) DefineIdentity(ctx context.Context, def *core.IdentityClaim, signingIdentity *core.SignerRef, parentSigner *core.SignerRef, tag string, waitConfirm bool) error { - ret := _m.Called(ctx, def, signingIdentity, parentSigner, tag, waitConfirm) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *core.IdentityClaim, *core.SignerRef, *core.SignerRef, string, bool) error); ok { - r0 = rf(ctx, def, signingIdentity, parentSigner, tag, waitConfirm) - } else { - r0 = ret.Error(0) - } - - return r0 -} - // DefineTokenPool provides a mock function with given fields: ctx, pool, waitConfirm func (_m *Sender) DefineTokenPool(ctx context.Context, pool *core.TokenPoolAnnouncement, waitConfirm bool) error { ret := _m.Called(ctx, pool, waitConfirm) @@ -121,3 +98,17 @@ func (_m *Sender) Name() string { return r0 } + +// UpdateIdentity provides a mock function with given fields: ctx, identity, def, signingIdentity, waitConfirm +func (_m *Sender) UpdateIdentity(ctx context.Context, identity *core.Identity, def *core.IdentityUpdate, signingIdentity *core.SignerRef, waitConfirm bool) error { + ret := _m.Called(ctx, identity, def, signingIdentity, waitConfirm) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *core.Identity, *core.IdentityUpdate, *core.SignerRef, bool) error); ok { + r0 = rf(ctx, identity, def, signingIdentity, waitConfirm) + } else { + r0 = ret.Error(0) + } + + return r0 +} From fb5c9a32bc26d13889db3a4aeac31f1d742fcc07 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Tue, 28 Jun 2022 16:32:14 -0400 Subject: [PATCH 25/27] Remove references to "gateway mode" Signed-off-by: Andrew Richardson --- internal/coremsgs/en_error_messages.go | 8 ++++---- internal/namespace/manager.go | 24 ++++++++++++------------ internal/namespace/manager_test.go | 14 +++++++------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/internal/coremsgs/en_error_messages.go b/internal/coremsgs/en_error_messages.go index f109a6320..313846a16 100644 --- a/internal/coremsgs/en_error_messages.go +++ b/internal/coremsgs/en_error_messages.go @@ -230,10 +230,10 @@ var ( MsgFFSystemReservedName = ffe("FF10388", "Invalid namespace configuration - %s is a reserved name") MsgInvalidNamespaceMode = ffe("FF10389", "Invalid %s namespace configuration - unknown mode") MsgNamespaceUnknownPlugin = ffe("FF10390", "Invalid %s namespace configuration - unknown plugin %s") - MsgNamespaceMultipartyConfiguration = ffe("FF10391", "Invalid %s multiparty namespace configuration - database, blockchain, shared storage, and data exchange plugins are required") - MsgNamespaceGatewayNoDB = ffe("FF10392", "Invalid %s gateway namespace configuration - a database plugin is required") - MsgNamespaceGatewayInvalidPlugins = ffe("FF10393", "Invalid %s gateway namespace configuration - cannot specify dataexchange or shared storage plugins") - MsgNamespaceGatewayMultiplePluginType = ffe("FF10394", "Invalid %s namespace configuration - multiple %s plugins provided") + MsgNamespaceWrongPluginsMultiparty = ffe("FF10391", "Invalid %s namespace configuration - multiparty mode requires database, blockchain, shared storage, and data exchange plugins") + MsgNamespaceNoDatabase = ffe("FF10392", "Invalid %s namespace configuration - a database plugin is required") + MsgNamespaceWrongPluginsNonMultiparty = ffe("FF10393", "Invalid %s namespace configuration - cannot specify data exchange or shared storage plugins when multiparty mode is disabled") + MsgNamespaceMultiplePluginType = ffe("FF10394", "Invalid %s namespace configuration - multiple %s plugins provided") MsgDuplicatePluginName = ffe("FF10395", "Invalid plugin configuration - plugin with name %s already exists") MsgInvalidFireFlyContractIndex = ffe("FF10396", "No configuration found for FireFly contract at %s") MsgUnrecognizedNetworkAction = ffe("FF10397", "Unrecognized network action: %s", 400) diff --git a/internal/namespace/manager.go b/internal/namespace/manager.go index 45981c876..4fea92bf1 100644 --- a/internal/namespace/manager.go +++ b/internal/namespace/manager.go @@ -730,7 +730,7 @@ func (nm *namespaceManager) loadNamespace(ctx context.Context, name string, inde config.Multiparty.Contracts = contracts p, err = nm.validateMultiPartyConfig(ctx, name, plugins) } else { - p, err = nm.validateGatewayConfig(ctx, name, plugins) + p, err = nm.validateNonMultipartyConfig(ctx, name, plugins) } if err != nil { return nil, err @@ -753,7 +753,7 @@ func (nm *namespaceManager) validateMultiPartyConfig(ctx context.Context, name s for _, pluginName := range plugins { if instance, ok := nm.plugins.blockchain[pluginName]; ok { if result.Blockchain.Plugin != nil { - return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceGatewayMultiplePluginType, name, "blockchain") + return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceMultiplePluginType, name, "blockchain") } result.Blockchain = orchestrator.BlockchainPlugin{ Name: pluginName, @@ -763,7 +763,7 @@ func (nm *namespaceManager) validateMultiPartyConfig(ctx context.Context, name s } if instance, ok := nm.plugins.dataexchange[pluginName]; ok { if result.DataExchange.Plugin != nil { - return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceGatewayMultiplePluginType, name, "dataexchange") + return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceMultiplePluginType, name, "dataexchange") } result.DataExchange = orchestrator.DataExchangePlugin{ Name: pluginName, @@ -773,7 +773,7 @@ func (nm *namespaceManager) validateMultiPartyConfig(ctx context.Context, name s } if instance, ok := nm.plugins.sharedstorage[pluginName]; ok { if result.SharedStorage.Plugin != nil { - return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceGatewayMultiplePluginType, name, "sharedstorage") + return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceMultiplePluginType, name, "sharedstorage") } result.SharedStorage = orchestrator.SharedStoragePlugin{ Name: pluginName, @@ -783,7 +783,7 @@ func (nm *namespaceManager) validateMultiPartyConfig(ctx context.Context, name s } if instance, ok := nm.plugins.database[pluginName]; ok { if result.Database.Plugin != nil { - return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceGatewayMultiplePluginType, name, "database") + return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceMultiplePluginType, name, "database") } result.Database = orchestrator.DatabasePlugin{ Name: pluginName, @@ -813,18 +813,18 @@ func (nm *namespaceManager) validateMultiPartyConfig(ctx context.Context, name s result.SharedStorage.Plugin == nil || result.DataExchange.Plugin == nil || result.Blockchain.Plugin == nil { - return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceMultipartyConfiguration, name) + return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceWrongPluginsMultiparty, name) } return &result, nil } -func (nm *namespaceManager) validateGatewayConfig(ctx context.Context, name string, plugins []string) (*orchestrator.Plugins, error) { +func (nm *namespaceManager) validateNonMultipartyConfig(ctx context.Context, name string, plugins []string) (*orchestrator.Plugins, error) { var result orchestrator.Plugins for _, pluginName := range plugins { if instance, ok := nm.plugins.blockchain[pluginName]; ok { if result.Blockchain.Plugin != nil { - return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceGatewayMultiplePluginType, name, "blockchain") + return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceMultiplePluginType, name, "blockchain") } result.Blockchain = orchestrator.BlockchainPlugin{ Name: pluginName, @@ -833,14 +833,14 @@ func (nm *namespaceManager) validateGatewayConfig(ctx context.Context, name stri continue } if _, ok := nm.plugins.dataexchange[pluginName]; ok { - return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceGatewayInvalidPlugins, name) + return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceWrongPluginsNonMultiparty, name) } if _, ok := nm.plugins.sharedstorage[pluginName]; ok { - return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceGatewayInvalidPlugins, name) + return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceWrongPluginsNonMultiparty, name) } if instance, ok := nm.plugins.database[pluginName]; ok { if result.Database.Plugin != nil { - return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceGatewayMultiplePluginType, name, "database") + return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceMultiplePluginType, name, "database") } result.Database = orchestrator.DatabasePlugin{ Name: pluginName, @@ -860,7 +860,7 @@ func (nm *namespaceManager) validateGatewayConfig(ctx context.Context, name stri } if result.Database.Plugin == nil { - return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceGatewayNoDB, name) + return nil, i18n.NewError(ctx, coremsgs.MsgNamespaceNoDatabase, name) } return &result, nil diff --git a/internal/namespace/manager_test.go b/internal/namespace/manager_test.go index 83ee6f662..1ca924212 100644 --- a/internal/namespace/manager_test.go +++ b/internal/namespace/manager_test.go @@ -829,7 +829,7 @@ func TestLoadNamespacesUseDefaults(t *testing.T) { assert.Len(t, nm.namespaces, 1) } -func TestLoadNamespacesGatewayNoDatabase(t *testing.T) { +func TestLoadNamespacesNonMultipartyNoDatabase(t *testing.T) { nm := newTestNamespaceManager(true) defer nm.cleanup(t) @@ -981,7 +981,7 @@ func TestLoadNamespacesMultipartyContractBadLocation(t *testing.T) { assert.Regexp(t, "json:", err) } -func TestLoadNamespacesGatewayMultipleDB(t *testing.T) { +func TestLoadNamespacesNonMultipartyMultipleDB(t *testing.T) { nm := newTestNamespaceManager(true) defer nm.cleanup(t) @@ -999,7 +999,7 @@ func TestLoadNamespacesGatewayMultipleDB(t *testing.T) { assert.Regexp(t, "FF10394.*database", err) } -func TestLoadNamespacesGatewayMultipleBlockchains(t *testing.T) { +func TestLoadNamespacesNonMultipartyMultipleBlockchains(t *testing.T) { nm := newTestNamespaceManager(true) defer nm.cleanup(t) @@ -1037,7 +1037,7 @@ func TestLoadNamespacesMultipartyMissingPlugins(t *testing.T) { assert.Regexp(t, "FF10391", err) } -func TestLoadNamespacesGatewayWithDX(t *testing.T) { +func TestLoadNamespacesNonMultipartyWithDX(t *testing.T) { nm := newTestNamespaceManager(true) defer nm.cleanup(t) @@ -1055,7 +1055,7 @@ func TestLoadNamespacesGatewayWithDX(t *testing.T) { assert.Regexp(t, "FF10393", err) } -func TestLoadNamespacesGatewayWithSharedStorage(t *testing.T) { +func TestLoadNamespacesNonMultipartyWithSharedStorage(t *testing.T) { nm := newTestNamespaceManager(true) defer nm.cleanup(t) @@ -1073,7 +1073,7 @@ func TestLoadNamespacesGatewayWithSharedStorage(t *testing.T) { assert.Regexp(t, "FF10393", err) } -func TestLoadNamespacesGatewayUnknownPlugin(t *testing.T) { +func TestLoadNamespacesNonMultipartyUnknownPlugin(t *testing.T) { nm := newTestNamespaceManager(true) defer nm.cleanup(t) @@ -1091,7 +1091,7 @@ func TestLoadNamespacesGatewayUnknownPlugin(t *testing.T) { assert.Regexp(t, "FF10390.*unknown", err) } -func TestLoadNamespacesGatewayTokens(t *testing.T) { +func TestLoadNamespacesNonMultipartyTokens(t *testing.T) { nm := newTestNamespaceManager(true) defer nm.cleanup(t) From 0ce79caafc5889e04cdc67f88c2cfb1cd06135d0 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Wed, 29 Jun 2022 18:01:20 -0400 Subject: [PATCH 26/27] Return an error if key cannot be resolved in non-multiparty mode Signed-off-by: Andrew Richardson --- internal/identity/identitymanager.go | 5 ++++- internal/identity/identitymanager_test.go | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/internal/identity/identitymanager.go b/internal/identity/identitymanager.go index 7d1ff8b1a..7646593e7 100644 --- a/internal/identity/identitymanager.go +++ b/internal/identity/identitymanager.go @@ -229,7 +229,10 @@ func (im *identityManager) getDefaultVerifier(ctx context.Context) (verifier *co if im.defaultKey != "" { return im.normalizeKeyViaBlockchainPlugin(ctx, im.defaultKey) } - return im.GetMultipartyRootVerifier(ctx) + if im.multiparty != nil { + return im.GetMultipartyRootVerifier(ctx) + } + return nil, i18n.NewError(ctx, coremsgs.MsgNodeMissingBlockchainKey) } // GetMultipartyRootVerifier gets the blockchain verifier of the root org via the configuration diff --git a/internal/identity/identitymanager_test.go b/internal/identity/identitymanager_test.go index 7bfe9c0ab..91023fd7c 100644 --- a/internal/identity/identitymanager_test.go +++ b/internal/identity/identitymanager_test.go @@ -493,6 +493,16 @@ func TestNormalizeSigningKeyOrgFallbackErr(t *testing.T) { } +func TestNormalizeSigningKeyNoDefault(t *testing.T) { + + ctx, im := newTestIdentityManager(t) + im.multiparty = nil + + _, err := im.NormalizeSigningKey(ctx, "", KeyNormalizationBlockchainPlugin) + assert.Regexp(t, "FF10354", err) + +} + func TestResolveInputSigningKeyOk(t *testing.T) { ctx, im := newTestIdentityManager(t) From 784a4db28eef6e9254275125a605e5d4935bb0bf Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Wed, 29 Jun 2022 18:14:28 -0400 Subject: [PATCH 27/27] Allow FFIs and APIs to be created without a message ID Signed-off-by: Andrew Richardson --- ...l => 000094_allow_local_definitions.down.sql} | 0 .../000094_allow_local_definitions.up.sql | 16 ++++++++++++++++ .../postgres/000094_allow_local_identity.up.sql | 6 ------ ...l => 000094_allow_local_definitions.down.sql} | 0 .../sqlite/000094_allow_local_definitions.up.sql | 14 ++++++++++++++ .../sqlite/000094_allow_local_identity.up.sql | 4 ---- 6 files changed, 30 insertions(+), 10 deletions(-) rename db/migrations/postgres/{000094_allow_local_identity.down.sql => 000094_allow_local_definitions.down.sql} (100%) create mode 100644 db/migrations/postgres/000094_allow_local_definitions.up.sql delete mode 100644 db/migrations/postgres/000094_allow_local_identity.up.sql rename db/migrations/sqlite/{000094_allow_local_identity.down.sql => 000094_allow_local_definitions.down.sql} (100%) create mode 100644 db/migrations/sqlite/000094_allow_local_definitions.up.sql delete mode 100644 db/migrations/sqlite/000094_allow_local_identity.up.sql diff --git a/db/migrations/postgres/000094_allow_local_identity.down.sql b/db/migrations/postgres/000094_allow_local_definitions.down.sql similarity index 100% rename from db/migrations/postgres/000094_allow_local_identity.down.sql rename to db/migrations/postgres/000094_allow_local_definitions.down.sql diff --git a/db/migrations/postgres/000094_allow_local_definitions.up.sql b/db/migrations/postgres/000094_allow_local_definitions.up.sql new file mode 100644 index 000000000..ed135221c --- /dev/null +++ b/db/migrations/postgres/000094_allow_local_definitions.up.sql @@ -0,0 +1,16 @@ +BEGIN; +ALTER TABLE identities RENAME COLUMN messages_claim TO messages_claim_old; +ALTER TABLE identities ADD COLUMN messages_claim UUID; +UPDATE identities SET messages_claim = messages_claim_old; +ALTER TABLE identities DROP COLUMN messages_claim_old; + +ALTER TABLE ffi RENAME COLUMN message_id TO message_id_old; +ALTER TABLE ffi ADD COLUMN message_id UUID; +UPDATE ffi SET message_id = message_id_old; +ALTER TABLE ffi DROP COLUMN message_id_old; + +ALTER TABLE contractapis RENAME COLUMN message_id TO message_id_old; +ALTER TABLE contractapis ADD COLUMN message_id UUID; +UPDATE contractapis SET message_id = message_id_old; +ALTER TABLE contractapis DROP COLUMN message_id_old; +COMMIT; diff --git a/db/migrations/postgres/000094_allow_local_identity.up.sql b/db/migrations/postgres/000094_allow_local_identity.up.sql deleted file mode 100644 index 69fa7a962..000000000 --- a/db/migrations/postgres/000094_allow_local_identity.up.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; -ALTER TABLE identities RENAME COLUMN messages_claim TO messages_claim_old; -ALTER TABLE identities ADD COLUMN messages_claim UUID; -UPDATE identities SET messages_claim = messages_claim_old; -ALTER TABLE identities DROP COLUMN messages_claim_old; -COMMIT; diff --git a/db/migrations/sqlite/000094_allow_local_identity.down.sql b/db/migrations/sqlite/000094_allow_local_definitions.down.sql similarity index 100% rename from db/migrations/sqlite/000094_allow_local_identity.down.sql rename to db/migrations/sqlite/000094_allow_local_definitions.down.sql diff --git a/db/migrations/sqlite/000094_allow_local_definitions.up.sql b/db/migrations/sqlite/000094_allow_local_definitions.up.sql new file mode 100644 index 000000000..9e53cabf7 --- /dev/null +++ b/db/migrations/sqlite/000094_allow_local_definitions.up.sql @@ -0,0 +1,14 @@ +ALTER TABLE identities RENAME COLUMN messages_claim TO messages_claim_old; +ALTER TABLE identities ADD COLUMN messages_claim UUID; +UPDATE identities SET messages_claim = messages_claim_old; +ALTER TABLE identities DROP COLUMN messages_claim_old; + +ALTER TABLE ffi RENAME COLUMN message_id TO message_id_old; +ALTER TABLE ffi ADD COLUMN message_id UUID; +UPDATE ffi SET message_id = message_id_old; +ALTER TABLE ffi DROP COLUMN message_id_old; + +ALTER TABLE contractapis RENAME COLUMN message_id TO message_id_old; +ALTER TABLE contractapis ADD COLUMN message_id UUID; +UPDATE contractapis SET message_id = message_id_old; +ALTER TABLE contractapis DROP COLUMN message_id_old; diff --git a/db/migrations/sqlite/000094_allow_local_identity.up.sql b/db/migrations/sqlite/000094_allow_local_identity.up.sql deleted file mode 100644 index cef04a1c0..000000000 --- a/db/migrations/sqlite/000094_allow_local_identity.up.sql +++ /dev/null @@ -1,4 +0,0 @@ -ALTER TABLE identities RENAME COLUMN messages_claim TO messages_claim_old; -ALTER TABLE identities ADD COLUMN messages_claim UUID; -UPDATE identities SET messages_claim = messages_claim_old; -ALTER TABLE identities DROP COLUMN messages_claim_old;