diff --git a/integration/fsc/pingpong/cmd/initiator/main.go b/integration/fsc/pingpong/cmd/initiator/main.go index f78860804..57f944553 100644 --- a/integration/fsc/pingpong/cmd/initiator/main.go +++ b/integration/fsc/pingpong/cmd/initiator/main.go @@ -10,20 +10,21 @@ import ( "github.com/hyperledger-labs/fabric-smart-client/integration/fsc/pingpong" "github.com/hyperledger-labs/fabric-smart-client/integration/fsc/pingpong/mock" fscnode "github.com/hyperledger-labs/fabric-smart-client/node" - "github.com/hyperledger-labs/fabric-smart-client/platform/view" + "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils" + viewsdk "github.com/hyperledger-labs/fabric-smart-client/platform/view/sdk/dig" ) func main() { - node := fscnode.New() + node := fscnode.NewEmpty("") + utils.Must(node.InstallSDK(viewsdk.NewSDK(node))) node.Execute(func() error { - registry := view.GetRegistry(node) - if err := registry.RegisterFactory("init", &pingpong.InitiatorViewFactory{}); err != nil { + if err := node.RegisterFactory("init", &pingpong.InitiatorViewFactory{}); err != nil { return err } - if err := registry.RegisterFactory("mockInit", &mock.InitiatorViewFactory{}); err != nil { + if err := node.RegisterFactory("mockInit", &mock.InitiatorViewFactory{}); err != nil { return err } - if err := registry.RegisterFactory("stream", &pingpong.StreamerViewFactory{}); err != nil { + if err := node.RegisterFactory("stream", &pingpong.StreamerViewFactory{}); err != nil { return err } return nil diff --git a/integration/fsc/pingpong/cmd/responder/main.go b/integration/fsc/pingpong/cmd/responder/main.go index 735ca7d58..ac841e279 100644 --- a/integration/fsc/pingpong/cmd/responder/main.go +++ b/integration/fsc/pingpong/cmd/responder/main.go @@ -10,18 +10,20 @@ import ( "github.com/hyperledger-labs/fabric-smart-client/integration/fsc/pingpong" "github.com/hyperledger-labs/fabric-smart-client/integration/fsc/pingpong/mock" fscnode "github.com/hyperledger-labs/fabric-smart-client/node" - "github.com/hyperledger-labs/fabric-smart-client/platform/view" + "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils" + registry2 "github.com/hyperledger-labs/fabric-smart-client/platform/view/core/registry" + viewsdk "github.com/hyperledger-labs/fabric-smart-client/platform/view/sdk/dig" ) func main() { - node := fscnode.New() + node := fscnode.NewEmpty("") + utils.Must(node.InstallSDK(viewsdk.NewSDK(node))) node.Execute(func() error { - registry := view.GetRegistry(node) - initiatorID := registry.GetIdentifier(&pingpong.Initiator{}) - if err := registry.RegisterResponder(&pingpong.Responder{}, initiatorID); err != nil { + initiatorID := registry2.GetIdentifier(&pingpong.Initiator{}) + if err := node.RegisterResponder(&pingpong.Responder{}, initiatorID); err != nil { return err } - if err := registry.RegisterResponder(&pingpong.Responder{}, &mock.Initiator{}); err != nil { + if err := node.RegisterResponder(&pingpong.Responder{}, &mock.Initiator{}); err != nil { return err } return nil diff --git a/integration/fsc/pingpong/pingpong_test.go b/integration/fsc/pingpong/pingpong_test.go index dd125a720..68a2ea32f 100644 --- a/integration/fsc/pingpong/pingpong_test.go +++ b/integration/fsc/pingpong/pingpong_test.go @@ -194,7 +194,7 @@ var _ = Describe("EndToEnd", func() { func newNode(conf string) api.FabricSmartClientNode { n := node.NewEmpty(conf) Expect(n).NotTo(BeNil()) - n.AddSDK(viewsdk.NewSDK(n.Registry())) + n.AddSDK(viewsdk.NewSDK(n)) return n } diff --git a/integration/fsc/stoprestart/stoprestart_test.go b/integration/fsc/stoprestart/stoprestart_test.go index cededdc37..5eafe20b6 100644 --- a/integration/fsc/stoprestart/stoprestart_test.go +++ b/integration/fsc/stoprestart/stoprestart_test.go @@ -26,36 +26,36 @@ var _ = Describe("EndToEnd", func() { It("stop and restart successfully", s.TestSucceeded) }) - Describe("Stop and Restart With Websockets", func() { - s := NewTestSuite(fsc.WebSocket, integration.NoReplication) - BeforeEach(s.Setup) - AfterEach(s.TearDown) - It("stop and restart successfully", s.TestSucceeded) - }) - - Describe("Stop and Restart with Fabric With Replicas many to one", func() { - s := NewTestSuite(fsc.WebSocket, &integration.ReplicationOptions{ - ReplicationFactors: map[string]int{ - "alice": 4, - "bob": 1, - }, - }) - BeforeEach(s.Setup) - AfterEach(s.TearDown) - It("stop and restart successfully", s.TestSucceededWithReplicas) - }) - - Describe("Stop and Restart with Fabric With Replicas many to many", func() { - s := NewTestSuite(fsc.WebSocket, &integration.ReplicationOptions{ - ReplicationFactors: map[string]int{ - "alice": 4, - "bob": 4, - }, - }) - BeforeEach(s.Setup) - AfterEach(s.TearDown) - It("stop and restart successfully", s.TestSucceededWithReplicas) - }) + //Describe("Stop and Restart With Websockets", func() { + // s := NewTestSuite(fsc.WebSocket, integration.NoReplication) + // BeforeEach(s.Setup) + // AfterEach(s.TearDown) + // It("stop and restart successfully", s.TestSucceeded) + //}) + // + //Describe("Stop and Restart with Fabric With Replicas many to one", func() { + // s := NewTestSuite(fsc.WebSocket, &integration.ReplicationOptions{ + // ReplicationFactors: map[string]int{ + // "alice": 4, + // "bob": 1, + // }, + // }) + // BeforeEach(s.Setup) + // AfterEach(s.TearDown) + // It("stop and restart successfully", s.TestSucceededWithReplicas) + //}) + // + //Describe("Stop and Restart with Fabric With Replicas many to many", func() { + // s := NewTestSuite(fsc.WebSocket, &integration.ReplicationOptions{ + // ReplicationFactors: map[string]int{ + // "alice": 4, + // "bob": 4, + // }, + // }) + // BeforeEach(s.Setup) + // AfterEach(s.TearDown) + // It("stop and restart successfully", s.TestSucceededWithReplicas) + //}) }) type TestSuite struct { diff --git a/integration/nwo/fsc/node/node_template.go b/integration/nwo/fsc/node/node_template.go index 29506cf0f..7efe76be3 100644 --- a/integration/nwo/fsc/node/node_template.go +++ b/integration/nwo/fsc/node/node_template.go @@ -16,8 +16,6 @@ package main import ( fscnode "github.com/hyperledger-labs/fabric-smart-client/node" - - {{ if InstallView }}viewregistry "github.com/hyperledger-labs/fabric-smart-client/platform/view"{{ end }} {{- range .Imports }} {{ Alias . }} "{{ . }}"{{ end }} ) @@ -29,13 +27,12 @@ func main() { {{ end }} n.Execute(func() error { {{- if InstallView }} - registry := viewregistry.GetRegistry(n) {{- range .Factories }} - if err := registry.RegisterFactory("{{ .Id }}", {{ .Type }}); err != nil { + if err := n.RegisterFactory("{{ .Id }}", {{ .Type }}); err != nil { return err }{{ end }} {{- range .Responders }} - registry.RegisterResponder({{ .Responder }}, {{ .Initiator }}){{ end }} + n.RegisterResponder({{ .Responder }}, {{ .Initiator }}){{ end }} {{ end }} return nil }) diff --git a/node/node.go b/node/node.go index 0af1d6323..c48d320ba 100644 --- a/node/node.go +++ b/node/node.go @@ -27,14 +27,18 @@ type FabricSmartClient interface { Start() error Stop() InstallSDK(p api.SDK) error - ConfigService() node3.ConfigService - Registry() node3.Registry GetService(v interface{}) (interface{}, error) RegisterService(service interface{}) error + ConfigService() node3.ConfigService RegisterFactory(id string, factory api.Factory) error RegisterResponder(responder view.View, initiatedBy interface{}) error RegisterResponderWithIdentity(responder view.View, id view.Identity, initiatedBy view.View) error - ResolveIdentities(endpoints ...string) ([]view.Identity, error) + + // RegisterViewManager injects the ViewManager dependency + RegisterViewManager(manager node3.ViewManager) + + // RegisterViewRegistry injects the ViewRegistry dependency + RegisterViewRegistry(registry node3.ViewRegistry) } type node struct { @@ -51,7 +55,7 @@ func New() *node { func NewFromConfPath(confPath string) *node { n := node3.NewEmpty(confPath) - n.AddSDK(sdk.NewSDK(n.Registry())) + n.AddSDK(sdk.NewSDK(n)) return newFromFsc(n) } diff --git a/node/node/start.go b/node/node/start.go index baeac3f3e..aac1c80e3 100644 --- a/node/node/start.go +++ b/node/node/start.go @@ -14,7 +14,6 @@ import ( "syscall" "github.com/hyperledger-labs/fabric-smart-client/node/node/profile" - node3 "github.com/hyperledger-labs/fabric-smart-client/pkg/node" "github.com/hyperledger-labs/fabric-smart-client/platform/common/services/logging" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -28,7 +27,6 @@ const ( type Node interface { Start() error Stop() - ConfigService() node3.ConfigService Callback() chan<- error } @@ -152,10 +150,7 @@ func serve() error { callback(nil) - cs := node.ConfigService() - logger.Infof("Started peer with ID=[%s]", - cs.GetString("fsc.id"), - ) + logger.Infof("Started peer") return <-serve } diff --git a/pkg/api/node.go b/pkg/api/node.go index 6708a5840..37b38500e 100644 --- a/pkg/api/node.go +++ b/pkg/api/node.go @@ -7,7 +7,6 @@ SPDX-License-Identifier: Apache-2.0 package api type FabricSmartClientNode interface { - ServiceProvider ViewRegistry ContextProvider ViewClient diff --git a/pkg/api/serviceprovider.go b/pkg/api/serviceprovider.go index d75925ca6..a9a6105ea 100644 --- a/pkg/api/serviceprovider.go +++ b/pkg/api/serviceprovider.go @@ -8,6 +8,4 @@ package api type ServiceProvider interface { GetService(v interface{}) (interface{}, error) - - RegisterService(service interface{}) error } diff --git a/pkg/node/node.go b/pkg/node/node.go index 5af3b4253..ce1d5f390 100755 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -10,19 +10,19 @@ import ( "context" "encoding/json" "log" - "reflect" "runtime/debug" "github.com/hyperledger-labs/fabric-smart-client/pkg/api" "github.com/hyperledger-labs/fabric-smart-client/platform/common/services/logging" view2 "github.com/hyperledger-labs/fabric-smart-client/platform/view" "github.com/hyperledger-labs/fabric-smart-client/platform/view/core/config" - tracing2 "github.com/hyperledger-labs/fabric-smart-client/platform/view/sdk/tracing" + "github.com/hyperledger-labs/fabric-smart-client/platform/view/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/registry" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/tracing" "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" "github.com/pkg/errors" "go.opentelemetry.io/otel/trace" + "go.opentelemetry.io/otel/trace/noop" ) const ( @@ -33,6 +33,12 @@ var logger = logging.MustGetLogger("fsc") type ExecuteCallbackFunc = func() error +type ViewRegistry interface { + RegisterFactory(id string, factory view2.Factory) error + RegisterResponder(responder view2.View, initiatedBy interface{}) error + RegisterResponderWithIdentity(responder view2.View, id view.Identity, initiatedBy interface{}) error +} + type ViewManager interface { NewView(id string, in []byte) (view.View, error) InitiateView(view view.View, ctx context.Context) (interface{}, error) @@ -42,29 +48,40 @@ type ViewManager interface { Context(contextID string) (view.Context, error) } -type Registry interface { +type ServiceRegisterer interface { + RegisterService(service interface{}) error +} + +type serviceRegistry interface { GetService(v interface{}) (interface{}, error) RegisterService(service interface{}) error } -type ConfigService interface { - GetString(key string) string +type Registry interface { + serviceRegistry + ConfigService() driver.ConfigService + RegisterViewManager(manager ViewManager) + RegisterViewRegistry(registry ViewRegistry) } +type ConfigService = driver.ConfigService + // PostStart enables a platform to execute additional tasks after all platforms have started type PostStart interface { PostStart(context.Context) error } type node struct { - registry Registry + registry serviceRegistry configService ConfigService sdks []api.SDK context context.Context cancel context.CancelFunc running bool tracer trace.Tracer + viewManager ViewManager + viewRegistry ViewRegistry } func NewEmpty(confPath string) *node { @@ -78,13 +95,31 @@ func NewEmpty(confPath string) *node { } return &node{ - sdks: []api.SDK{}, registry: registry, + sdks: []api.SDK{}, configService: configService, + tracer: noop.NewTracerProvider().Tracer("noop"), } } +func (n *node) RegisterTracerProvider(provider trace.TracerProvider) { + logger.Infof("Register tracer provider") + n.tracer = provider.Tracer("node_view_client", tracing.WithMetricsOpts(tracing.MetricsOpts{ + Namespace: "viewsdk", + LabelNames: []tracing.LabelName{fidLabel}, + })) +} + +func (n *node) RegisterViewManager(manager ViewManager) { + n.viewManager = manager +} + +func (n *node) RegisterViewRegistry(registry ViewRegistry) { + n.viewRegistry = registry +} + func (n *node) AddSDK(sdk api.SDK) { + logger.Infof("Add SDK [%T]", sdk) n.sdks = append(n.sdks, sdk) } @@ -103,7 +138,7 @@ func (n *node) Start() (err error) { n.running = true // Install - logger.Infof("Installing sdks...") + logger.Infof("Installing %d sdks...", len(n.sdks)) for _, p := range n.sdks { if err := p.Install(); err != nil { logger.Errorf("Failed installing platform [%s]", err) @@ -157,73 +192,41 @@ func (n *node) InstallSDK(p api.SDK) error { } func (n *node) RegisterFactory(id string, factory api.Factory) error { - return view2.GetRegistry(n.registry).RegisterFactory(id, factory) + return n.viewRegistry.RegisterFactory(id, factory) } func (n *node) RegisterResponder(responder view.View, initiatedBy interface{}) error { - return view2.GetRegistry(n.registry).RegisterResponder(responder, initiatedBy) + return n.viewRegistry.RegisterResponder(responder, initiatedBy) } func (n *node) RegisterResponderWithIdentity(responder view.View, id view.Identity, initiatedBy view.View) error { - return view2.GetRegistry(n.registry).RegisterResponderWithIdentity(responder, id, initiatedBy) + return n.viewRegistry.RegisterResponderWithIdentity(responder, id, initiatedBy) } +// RegisterService To be deprecated func (n *node) RegisterService(service interface{}) error { return n.registry.RegisterService(service) } +// GetService to be deprecated func (n *node) GetService(v interface{}) (interface{}, error) { return n.registry.GetService(v) } -func (n *node) Registry() Registry { - return n.registry -} - -func (n *node) ResolveIdentities(endpoints ...string) ([]view.Identity, error) { - resolver := view2.GetEndpointService(n.registry) - - var ids []view.Identity - for _, e := range endpoints { - identity, err := resolver.GetIdentity(e, nil) - if err != nil { - return nil, errors.Wrapf(err, "cannot find the identity at %s", e) - } - ids = append(ids, identity) - } - - return ids, nil -} - -func (n *node) getTracer() trace.Tracer { - if n.tracer == nil { - n.tracer = tracing2.Get(n.registry).Tracer("node_view_client", tracing.WithMetricsOpts(tracing.MetricsOpts{ - Namespace: "viewsdk", - LabelNames: []tracing.LabelName{fidLabel}, - })) - } - return n.tracer -} - func (n *node) CallView(fid string, in []byte) (interface{}, error) { - ctx, span := n.getTracer().Start(context.Background(), "CallView", + ctx, span := n.tracer.Start(context.Background(), "CallView", trace.WithSpanKind(trace.SpanKindClient), tracing.WithAttributes(tracing.String(fidLabel, fid))) defer span.End() - s, err := n.GetService(reflect.TypeOf((*ViewManager)(nil))) - if err != nil { - return nil, err - } - manager := s.(ViewManager) span.AddEvent("start_new_view") - f, err := manager.NewView(fid, in) + f, err := n.viewManager.NewView(fid, in) span.AddEvent("end_new_view") if err != nil { return nil, errors.Wrapf(err, "failed instantiating view [%s]", fid) } span.AddEvent("start_initiate_view") - result, err := manager.InitiateView(f, ctx) + result, err := n.viewManager.InitiateView(f, ctx) span.AddEvent("end_initiate_view") if err != nil { return nil, errors.Wrapf(err, "failed running view [%s]", fid) @@ -239,44 +242,20 @@ func (n *node) CallView(fid string, in []byte) (interface{}, error) { } func (n *node) InitiateContext(view view.View) (view.Context, error) { - s, err := n.GetService(reflect.TypeOf((*ViewManager)(nil))) - if err != nil { - return nil, err - } - manager := s.(ViewManager) - - return manager.InitiateContext(view) + return n.viewManager.InitiateContext(view) } // InitiateContextFrom creates a new view context, derived from the passed context.Context func (n *node) InitiateContextFrom(ctx context.Context, view view.View) (view.Context, error) { - s, err := n.GetService(reflect.TypeOf((*ViewManager)(nil))) - if err != nil { - return nil, err - } - manager := s.(ViewManager) - - return manager.InitiateContextFrom(ctx, view, nil, "") + return n.viewManager.InitiateContextFrom(ctx, view, nil, "") } func (n *node) InitiateContextWithIdentity(view view.View, id view.Identity) (view.Context, error) { - s, err := n.GetService(reflect.TypeOf((*ViewManager)(nil))) - if err != nil { - return nil, err - } - manager := s.(ViewManager) - - return manager.InitiateContextWithIdentity(view, id) + return n.viewManager.InitiateContextWithIdentity(view, id) } func (n *node) Context(contextID string) (view.Context, error) { - s, err := n.GetService(reflect.TypeOf((*ViewManager)(nil))) - if err != nil { - return nil, err - } - manager := s.(ViewManager) - - return manager.Context(contextID) + return n.viewManager.Context(contextID) } func (n *node) Initiate(fid string, in []byte) (string, error) { diff --git a/platform/common/utils/dig/dig.go b/platform/common/utils/dig/dig.go index e0e9c06e4..ebb51d8b3 100644 --- a/platform/common/utils/dig/dig.go +++ b/platform/common/utils/dig/dig.go @@ -10,12 +10,16 @@ import ( "bytes" "errors" "fmt" + "reflect" "runtime/debug" "github.com/hyperledger-labs/fabric-smart-client/pkg/node" + "github.com/hyperledger-labs/fabric-smart-client/platform/common/services/logging" "go.uber.org/dig" ) +var logger = logging.MustGetLogger("dig-utils") + type invoker interface { Invoke(function interface{}, opts ...dig.InvokeOption) error } @@ -30,7 +34,7 @@ func Visualize(c *dig.Container) string { func Register[T any](c invoker) error { //Temporary workaround for services that are imported still using the registry - err := c.Invoke(func(registry node.Registry, service T) error { + err := c.Invoke(func(registry node.ServiceRegisterer, service T) error { return registry.RegisterService(service) }) if err != nil { @@ -40,6 +44,26 @@ func Register[T any](c invoker) error { return nil } +func RegisterOptional[T any](c invoker) error { + //Temporary workaround for services that are imported still using the registry + err := c.Invoke(func(in struct { + dig.In + Registry node.ServiceRegisterer + Service T `optional:"true"` + }) error { + if reflect.ValueOf(in.Service).IsNil() { + logger.Warnf("Skipping registration of optional dependency [%T]", new(T)) + return nil + } + return in.Registry.RegisterService(in.Service) + }) + if err != nil { + debug.PrintStack() + return fmt.Errorf("failed registering type %T: %+v", *new(T), err) + } + return nil +} + func ProvideAll(c *dig.Container, constructors ...interface{}) error { errs := make([]error, len(constructors)) for i, constructor := range constructors { diff --git a/platform/fabric/services/endorser/builder.go b/platform/fabric/services/endorser/builder.go index 6245920eb..95d97a7c1 100644 --- a/platform/fabric/services/endorser/builder.go +++ b/platform/fabric/services/endorser/builder.go @@ -13,7 +13,6 @@ import ( "github.com/hyperledger-labs/fabric-smart-client/platform/common/services/logging" "github.com/hyperledger-labs/fabric-smart-client/platform/fabric" - view2 "github.com/hyperledger-labs/fabric-smart-client/platform/view" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/hash" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/session" "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" @@ -22,21 +21,14 @@ import ( var logger = logging.MustGetLogger("fabric-sdk.services.endorser") type Builder struct { - sp view2.ServiceProvider + fnsProvider *fabric.NetworkServiceProvider } -func NewBuilder(context view.Context) *Builder { - if context == nil { +func NewBuilder(fnsProvider *fabric.NetworkServiceProvider) *Builder { + if fnsProvider == nil { panic("context must be set") } - return &Builder{sp: context} -} - -func NewBuilderWithServiceProvider(sp view2.ServiceProvider) *Builder { - if sp == nil { - panic("service provider must be set") - } - return &Builder{sp: sp} + return &Builder{fnsProvider: fnsProvider} } func (t *Builder) NewTransaction(ctx context.Context, opts ...fabric.TransactionOption) (*Transaction, error) { @@ -94,7 +86,7 @@ func (t *Builder) newTransactionWithType(ctx context.Context, creator []byte, ne logger.Debugf("NewTransaction [%s,%s,%s]", view.Identity(creator).UniqueID(), channel, hash.Hashable(raw).String()) defer logger.Debugf("NewTransaction...done.") - fNetwork, err := fabric.GetFabricNetworkService(t.sp, network) + fNetwork, err := t.fnsProvider.FabricNetworkService(network) if err != nil { return nil, errors.WithMessagef(err, "fabric network service [%s] not found", network) } @@ -128,13 +120,13 @@ func (t *Builder) newTransactionWithType(ctx context.Context, creator []byte, ne return nil, err } return &Transaction{ - ServiceProvider: t.sp, - Transaction: fabricTransaction, + fnsProvider: t.fnsProvider, + Transaction: fabricTransaction, }, nil } -func NewTransaction(context view.Context, opts ...fabric.TransactionOption) (*Builder, *Transaction, error) { - txBuilder := NewBuilder(context) +func NewTransaction(fnsProvider *fabric.NetworkServiceProvider, context view.Context, opts ...fabric.TransactionOption) (*Builder, *Transaction, error) { + txBuilder := NewBuilder(fnsProvider) tx, err := txBuilder.NewTransaction(context.Context(), opts...) if err != nil { return nil, nil, err @@ -143,8 +135,8 @@ func NewTransaction(context view.Context, opts ...fabric.TransactionOption) (*Bu return txBuilder, tx, nil } -func NewTransactionFromBytes(context view.Context, bytes []byte) (*Builder, *Transaction, error) { - txBuilder := NewBuilder(context) +func NewTransactionFromBytes(fnsProvider *fabric.NetworkServiceProvider, context view.Context, bytes []byte) (*Builder, *Transaction, error) { + txBuilder := NewBuilder(fnsProvider) tx, err := txBuilder.NewTransactionFromBytes(bytes) if err != nil { return nil, nil, err @@ -153,18 +145,18 @@ func NewTransactionFromBytes(context view.Context, bytes []byte) (*Builder, *Tra return txBuilder, tx, nil } -func NewTransactionWithSigner(context view.Context, network, channel string, id view.Identity) (*Builder, *Transaction, error) { - txBuilder := NewBuilderWithServiceProvider(context) - tx, err := txBuilder.newTransaction(context.Context(), id, network, channel, nil, nil, false) +func NewTransactionWithSigner(fnsProvider *fabric.NetworkServiceProvider, ctx view.Context, network, channel string, id view.Identity) (*Builder, *Transaction, error) { + txBuilder := NewBuilder(fnsProvider) + tx, err := txBuilder.newTransaction(ctx.Context(), id, network, channel, nil, nil, false) if err != nil { return nil, nil, err } - context.OnError(tx.Close) + ctx.OnError(tx.Close) return txBuilder, tx, nil } -func NewTransactionWith(ctx context.Context, sp view2.ServiceProvider, network, channel string, id view.Identity) (*Builder, *Transaction, error) { - txBuilder := NewBuilderWithServiceProvider(sp) +func NewTransactionWith(fnsProvider *fabric.NetworkServiceProvider, ctx context.Context, network, channel string, id view.Identity) (*Builder, *Transaction, error) { + txBuilder := NewBuilder(fnsProvider) tx, err := txBuilder.newTransaction(ctx, id, network, channel, nil, nil, false) if err != nil { return nil, nil, err @@ -172,8 +164,8 @@ func NewTransactionWith(ctx context.Context, sp view2.ServiceProvider, network, return txBuilder, tx, nil } -func NewTransactionFromEnvelopeBytes(ctx context.Context, sp view2.ServiceProvider, bytes []byte) (*Builder, *Transaction, error) { - txBuilder := NewBuilderWithServiceProvider(sp) +func NewTransactionFromEnvelopeBytes(fnsProvider *fabric.NetworkServiceProvider, ctx context.Context, bytes []byte) (*Builder, *Transaction, error) { + txBuilder := NewBuilder(fnsProvider) tx, err := txBuilder.NewTransactionFromEnvelopeBytes(ctx, bytes) if err != nil { return nil, nil, err @@ -181,7 +173,7 @@ func NewTransactionFromEnvelopeBytes(ctx context.Context, sp view2.ServiceProvid return txBuilder, tx, nil } -func ReceiveTransaction(context view.Context) (*Transaction, error) { - _, tx, err := NewTransactionFromBytes(context, session.ReadFirstMessageOrPanic(context)) +func ReceiveTransaction(fnsProvider *fabric.NetworkServiceProvider, context view.Context) (*Transaction, error) { + _, tx, err := NewTransactionFromBytes(fnsProvider, context, session.ReadFirstMessageOrPanic(context)) return tx, err } diff --git a/platform/fabric/services/endorser/flow.go b/platform/fabric/services/endorser/flow.go index 9de93e9e6..f0f895dbe 100644 --- a/platform/fabric/services/endorser/flow.go +++ b/platform/fabric/services/endorser/flow.go @@ -7,6 +7,8 @@ SPDX-License-Identifier: Apache-2.0 package endorser import ( + "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils" + "github.com/hyperledger-labs/fabric-smart-client/platform/fabric" "github.com/pkg/errors" "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" @@ -20,7 +22,7 @@ func (r *receiveTransactionView) Call(context view.Context) (interface{}, error) return nil, errors.Wrap(err, "failed receiving transaction content") } - builder := NewBuilder(context) + builder := NewBuilder(utils.MustGet(fabric.GetNetworkServiceProvider(context))) tx, err := builder.NewTransactionFromBytes(raw.([]byte)) if err != nil { return nil, errors.Wrap(err, "failed reconstructing transaction") diff --git a/platform/fabric/services/endorser/transaction.go b/platform/fabric/services/endorser/transaction.go index d66618f08..df254cb69 100644 --- a/platform/fabric/services/endorser/transaction.go +++ b/platform/fabric/services/endorser/transaction.go @@ -10,19 +10,22 @@ import ( "bytes" "github.com/hyperledger-labs/fabric-smart-client/platform/fabric" - view2 "github.com/hyperledger-labs/fabric-smart-client/platform/view" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/hash" "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" "github.com/pkg/errors" ) type Transaction struct { - view2.ServiceProvider + fnsProvider *fabric.NetworkServiceProvider Transaction *fabric.Transaction verifierProviders []fabric.VerifierProvider } +func (t *Transaction) NetworkServiceProvider() *fabric.NetworkServiceProvider { + return t.fnsProvider +} + func (t *Transaction) ID() string { return t.Transaction.ID() } diff --git a/platform/fabric/services/state/certification.go b/platform/fabric/services/state/certification.go index 39d10468d..9aabe0672 100644 --- a/platform/fabric/services/state/certification.go +++ b/platform/fabric/services/state/certification.go @@ -118,7 +118,7 @@ func (n *Namespace) VerifyInputCertificationAt(index int, key string) error { // raw is an envelope, it must be signed by enough endorsers cn, cv := n.tx.Chaincode() - _, ch, err := fabric.GetChannel(n.tx.ServiceProvider, n.tx.Network(), n.tx.Channel()) + ch, err := n.tx.FabricNetworkService().Channel(n.tx.Channel()) if err != nil { return errors.Wrapf(err, "failed getting channel [%s:%s]", n.tx.Network(), n.tx.Channel()) } @@ -126,7 +126,7 @@ func (n *Namespace) VerifyInputCertificationAt(index int, key string) error { if err != nil { return errors.Wrapf(err, "failed asking endorsers for to [%s,%s,%s] for [%s]", n.tx.Channel(), cn, cv, id) } - _, certTx, err := endorser.NewTransactionFromEnvelopeBytes(context.Background(), n.tx.ServiceProvider, raw) + _, certTx, err := endorser.NewTransactionFromEnvelopeBytes(n.tx.NetworkServiceProvider(), context.Background(), raw) if err != nil { return errors.Wrapf(err, "failed parsing certification [%s,%s,%s] for [%s]", n.tx.Channel(), cn, cv, id) } @@ -175,12 +175,12 @@ func (n *Namespace) certifyInput(id string) error { case ChaincodeCertification: // Invoke chaincode cn, cv := n.tx.Chaincode() - fns, ch, err := fabric.GetChannel(n.tx.ServiceProvider, n.tx.Network(), n.tx.Channel()) + ch, err := n.tx.FabricNetworkService().Channel(n.tx.Channel()) if err != nil { return errors.Wrapf(err, "failed getting channel [%s:%s]", n.tx.Network(), n.tx.Channel()) } env, err := ch.Chaincode(cn).Endorse(CertificationFnc, id, n.tx.ID()).WithInvokerIdentity( - fns.IdentityProvider().DefaultIdentity(), + n.tx.FabricNetworkService().IdentityProvider().DefaultIdentity(), ).Call() if err != nil { return errors.Wrapf(err, "failed asking certification to [%s,%s,%s] for [%s]", n.tx.Channel(), cn, cv, id) diff --git a/platform/fabric/services/state/namespace.go b/platform/fabric/services/state/namespace.go index 2ebda1b50..430cbe3e6 100755 --- a/platform/fabric/services/state/namespace.go +++ b/platform/fabric/services/state/namespace.go @@ -51,15 +51,7 @@ type Namespace struct { } func NewNamespace(tx *endorser.Transaction, forceSBE bool) *Namespace { - return &Namespace{ - tx: tx, - codec: &JSONCodec{}, - metaHandlers: []MetaHandler{ - &sbeMetaHandler{forceSBE: forceSBE}, - &contractMetaHandler{}, - }, - certifiedInputs: map[string][]byte{}, - } + return NewNamespaceForName(tx, "", forceSBE) } func NewNamespaceForName(tx *endorser.Transaction, ns string, forceSBE bool) *Namespace { @@ -458,10 +450,6 @@ func (n *Namespace) RWSet() (*fabric.RWSet, error) { return n.tx.RWSet() } -func (n *Namespace) GetService(v interface{}) (interface{}, error) { - return n.tx.GetService(v) -} - func (n *Namespace) getStateID(s interface{}) (string, error) { logger.Debugf("getStateID %v...", s) defer logger.Debugf("getStateID...done") diff --git a/platform/fabric/services/state/transaction.go b/platform/fabric/services/state/transaction.go index 5d3032e47..d93932e2e 100755 --- a/platform/fabric/services/state/transaction.go +++ b/platform/fabric/services/state/transaction.go @@ -10,6 +10,7 @@ import ( "encoding/base64" "time" + "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils" "github.com/hyperledger-labs/fabric-smart-client/platform/fabric" "github.com/hyperledger-labs/fabric-smart-client/platform/fabric/services/endorser" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/hash" @@ -35,7 +36,11 @@ func Wrap(tx *endorser.Transaction) (*Transaction, error) { // NewTransaction returns a new instance of a state-based transaction that embeds a single namespace. func NewTransaction(context view.Context) (*Transaction, error) { - _, tx, err := endorser.NewTransaction(context) + return newTransaction(utils.MustGet(fabric.GetNetworkServiceProvider(context)), context) +} + +func newTransaction(fnsProvider *fabric.NetworkServiceProvider, context view.Context) (*Transaction, error) { + _, tx, err := endorser.NewTransaction(fnsProvider, context) if err != nil { return nil, err } @@ -50,10 +55,14 @@ func NewTransaction(context view.Context) (*Transaction, error) { }, nil } +func NewAnonymousTransaction(context view.Context) (*Transaction, error) { + return newAnonymousTransaction(utils.MustGet(fabric.GetNetworkServiceProvider(context)), context) +} + // NewAnonymousTransaction returns a new instance of a state-based transaction that embeds a single namespace and is signed // by an anonymous identity -func NewAnonymousTransaction(context view.Context) (*Transaction, error) { - fns, err := fabric.GetDefaultFNS(context) +func newAnonymousTransaction(fnsProvider *fabric.NetworkServiceProvider, context view.Context) (*Transaction, error) { + fns, err := fnsProvider.FabricNetworkService("") if err != nil { return nil, err } @@ -62,6 +71,7 @@ func NewAnonymousTransaction(context view.Context) (*Transaction, error) { return nil, errors.WithMessagef(err, "failed getting anonymous identity") } _, tx, err := endorser.NewTransactionWithSigner( + fnsProvider, context, fns.Name(), fns.ConfigService().DefaultChannel(), @@ -81,8 +91,8 @@ func NewAnonymousTransaction(context view.Context) (*Transaction, error) { }, nil } -func NewTransactionFromBytes(context view.Context, raw []byte) (*Transaction, error) { - _, tx, err := endorser.NewTransactionFromBytes(context, raw) +func NewTransactionFromBytes(fnsProvider *fabric.NetworkServiceProvider, context view.Context, raw []byte) (*Transaction, error) { + _, tx, err := endorser.NewTransactionFromBytes(fnsProvider, context, raw) if err != nil { return nil, err } @@ -97,6 +107,13 @@ type receiveTransactionView struct { party view.Identity } +func (f *receiveTransactionView) Call(context view.Context) (interface{}, error) { + return context.RunView(&ReceiveTransactionView{ + party: f.party, + fnsProvider: utils.MustGet(fabric.GetNetworkServiceProvider(context)), + }) +} + func NewReceiveTransactionView() *receiveTransactionView { return &receiveTransactionView{} } @@ -127,7 +144,13 @@ func ReceiveTransactionFrom(context view.Context, party view.Identity) (*Transac return cctx, nil } -func (f *receiveTransactionView) Call(context view.Context) (interface{}, error) { +type ReceiveTransactionView struct { + party view.Identity + + fnsProvider *fabric.NetworkServiceProvider +} + +func (f *ReceiveTransactionView) Call(context view.Context) (interface{}, error) { // Wait to receive a transaction back var ch <-chan *view.Message if f.party.IsNone() { @@ -148,7 +171,7 @@ func (f *receiveTransactionView) Call(context view.Context) (interface{}, error) if msg.Status == view.ERROR { return nil, errors.New(string(msg.Payload)) } - tx, err := NewTransactionFromBytes(context, msg.Payload) + tx, err := NewTransactionFromBytes(f.fnsProvider, context, msg.Payload) if err != nil { return nil, err } @@ -158,6 +181,21 @@ func (f *receiveTransactionView) Call(context view.Context) (interface{}, error) } } +type ReceiveTransactionViewFactory struct { + fnsProvider *fabric.NetworkServiceProvider +} + +func NewReceiveTransactionViewFactory(fnsProvider *fabric.NetworkServiceProvider) *ReceiveTransactionViewFactory { + return &ReceiveTransactionViewFactory{fnsProvider: fnsProvider} +} + +func (f *ReceiveTransactionViewFactory) New(party view.Identity) *ReceiveTransactionView { + return &ReceiveTransactionView{ + party: party, + fnsProvider: f.fnsProvider, + } +} + type sendTransactionView struct { tx *Transaction parties []view.Identity diff --git a/platform/fabric/services/state/vault/vault.go b/platform/fabric/services/state/vault/vault.go index f46141abc..fb24b2c3a 100644 --- a/platform/fabric/services/state/vault/vault.go +++ b/platform/fabric/services/state/vault/vault.go @@ -11,10 +11,9 @@ import ( "encoding/json" "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" - driver2 "github.com/hyperledger-labs/fabric-smart-client/platform/fabric/driver" + "github.com/hyperledger-labs/fabric-smart-client/platform/fabric" "github.com/hyperledger-labs/fabric-smart-client/platform/fabric/services/endorser" "github.com/hyperledger-labs/fabric-smart-client/platform/fabric/services/state" - driver3 "github.com/hyperledger-labs/fabric-smart-client/platform/view/driver" view2 "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" "github.com/pkg/errors" ) @@ -28,7 +27,7 @@ type localMembership interface { } type vault struct { - sp driver3.ServiceProvider + fnsProvider *fabric.NetworkServiceProvider network string channel string vaultStore vaultStore @@ -61,7 +60,7 @@ func (f *vault) GetStateByPartialCompositeID(ctx context.Context, ns driver.Name } func (f *vault) GetStateCertification(ctx context.Context, namespace driver.Namespace, key driver.PKey) ([]byte, error) { - _, tx, err := endorser.NewTransactionWith(ctx, f.sp, f.network, f.channel, f.localMembership.DefaultIdentity()) + _, tx, err := endorser.NewTransactionWith(f.fnsProvider, ctx, f.network, f.channel, f.localMembership.DefaultIdentity()) if err != nil { return nil, errors.Wrapf(err, "failed creating transaction [%s:%s]", namespace, key) } @@ -90,12 +89,11 @@ func (f *vault) GetStateCertification(ctx context.Context, namespace driver.Name } type service struct { - sp driver3.ServiceProvider - fnsp driver2.FabricNetworkServiceProvider + fnsp *fabric.NetworkServiceProvider } -func NewService(sp driver3.ServiceProvider, fnsp driver2.FabricNetworkServiceProvider) *service { - return &service{sp: sp, fnsp: fnsp} +func NewService(fnsp *fabric.NetworkServiceProvider) *service { + return &service{fnsp: fnsp} } func (w *service) Vault(network string, channel string) (state.Vault, error) { @@ -108,10 +106,10 @@ func (w *service) Vault(network string, channel string) (state.Vault, error) { return nil, err } return &vault{ - sp: w.sp, + fnsProvider: w.fnsp, network: fns.Name(), channel: ch.Name(), - vaultStore: ch.VaultStore(), + vaultStore: ch.Vault().Store(), localMembership: fns.LocalMembership(), }, nil } diff --git a/platform/fabric/vault.go b/platform/fabric/vault.go index e67e5f07a..0dce13b6b 100644 --- a/platform/fabric/vault.go +++ b/platform/fabric/vault.go @@ -89,14 +89,10 @@ func (r *RWSet) Equals(rws interface{}, nss ...string) error { } } -type lastTxGetter interface { - GetLast(ctx context.Context) (*driver.TxStatus, error) -} - // Vault models a key-value store that can be updated by committing rwsets type Vault struct { vault fdriver.Vault - vaultStore lastTxGetter + vaultStore fdriver.VaultStore committer fdriver.Committer transactionService fdriver.EndorserTransactionService envelopeService fdriver.EnvelopeService @@ -114,6 +110,10 @@ func newVault(ch fdriver.Channel) *Vault { } } +func (c *Vault) Store() fdriver.VaultStore { + return c.vaultStore +} + func (c *Vault) NewQueryExecutor(ctx context.Context) (driver.QueryExecutor, error) { return c.vault.NewQueryExecutor(ctx) } diff --git a/platform/view/config.go b/platform/view/config.go index 7bbf17fd5..ebd480149 100644 --- a/platform/view/config.go +++ b/platform/view/config.go @@ -70,7 +70,9 @@ func (c *ConfigService) GetInt(path string) int { // GetConfigService returns an instance of the config service. // It panics, if no instance is found. func GetConfigService(sp ServiceProvider) *ConfigService { - return &ConfigService{ - cp: driver.GetConfigService(sp), - } + return NewConfigService(driver.GetConfigService(sp)) +} + +func NewConfigService(cs driver.ConfigService) *ConfigService { + return &ConfigService{cp: cs} } diff --git a/platform/view/core/manager/context.go b/platform/view/core/manager/context.go index bb9ad267d..3c4eef82c 100644 --- a/platform/view/core/manager/context.go +++ b/platform/view/core/manager/context.go @@ -24,6 +24,18 @@ import ( "go.uber.org/zap/zapcore" ) +type sigService interface { + // IsMe returns true if a signer was ever registered for the passed identity + IsMe(identity view.Identity) bool +} + +type identityProvider interface { + // DefaultIdentity returns the default identity known by this provider + DefaultIdentity() view.Identity + // Identity returns the identity bound to the passed label + Identity(label string) view.Identity +} + type ctx struct { context context.Context sp driver.ServiceProvider @@ -40,7 +52,9 @@ type ctx struct { sessions map[string]view.Session errorCallbackFuncs []func() - tracer trace.Tracer + identityProvider identityProvider + sigService sigService + tracer trace.Tracer } func (ctx *ctx) StartSpan(name string, opts ...trace.SpanStartOption) trace.Span { @@ -53,11 +67,11 @@ func (ctx *ctx) StartSpanFrom(c context.Context, name string, opts ...trace.Span return ctx.tracer.Start(c, name, opts...) } -func NewContextForInitiator(contextID string, context context.Context, sp driver.ServiceProvider, sessionFactory SessionFactory, resolver driver.EndpointService, party view.Identity, initiator view.View, tracer trace.Tracer) (*ctx, error) { +func NewContextForInitiator(contextID string, context context.Context, sp driver.ServiceProvider, sessionFactory SessionFactory, resolver driver.EndpointService, identityProvider identityProvider, sigService sigService, party view.Identity, initiator view.View, tracer trace.Tracer) (*ctx, error) { if len(contextID) == 0 { contextID = GenerateUUID() } - ctx, err := NewContext(context, sp, contextID, sessionFactory, resolver, party, nil, nil, tracer) + ctx, err := NewContext(context, sp, contextID, sessionFactory, resolver, identityProvider, sigService, party, nil, nil, tracer) if err != nil { return nil, err } @@ -66,7 +80,7 @@ func NewContextForInitiator(contextID string, context context.Context, sp driver return ctx, nil } -func NewContext(context context.Context, sp driver.ServiceProvider, contextID string, sessionFactory SessionFactory, resolver driver.EndpointService, party view.Identity, session view.Session, caller view.Identity, tracer trace.Tracer) (*ctx, error) { +func NewContext(context context.Context, sp driver.ServiceProvider, contextID string, sessionFactory SessionFactory, resolver driver.EndpointService, identityProvider identityProvider, sigService sigService, party view.Identity, session view.Session, caller view.Identity, tracer trace.Tracer) (*ctx, error) { ctx := &ctx{ context: context, id: contextID, @@ -79,7 +93,9 @@ func NewContext(context context.Context, sp driver.ServiceProvider, contextID st sp: sp, localSP: registry.New(), - tracer: tracer, + tracer: tracer, + identityProvider: identityProvider, + sigService: sigService, } if session != nil { // Register default session @@ -188,7 +204,7 @@ func (ctx *ctx) Identity(ref string) (view.Identity, error) { } func (ctx *ctx) IsMe(id view.Identity) bool { - return view2.GetSigService(ctx).IsMe(id) + return ctx.sigService.IsMe(id) } func (ctx *ctx) Caller() view.Identity { @@ -213,7 +229,7 @@ func (ctx *ctx) GetSession(f view.View, party view.Identity) (view.Session, erro logger.Debugf("session for [%s] does not exists, resolve", id.UniqueID()) } - id, _, _, err = view2.GetEndpointService(ctx).Resolve(party) + id, _, _, err = view2.NewEndpointService(ctx.resolver).Resolve(party) if err == nil { s, ok = ctx.sessions[id.UniqueID()] if logger.IsEnabledFor(zapcore.DebugLevel) { @@ -221,9 +237,9 @@ func (ctx *ctx) GetSession(f view.View, party view.Identity) (view.Session, erro } } else { // give it a second chance, check if party can be resolved as an identity - partyIdentity := view2.GetIdentityProvider(ctx).Identity(string(party)) + partyIdentity := ctx.identityProvider.Identity(string(party)) if !partyIdentity.IsNone() { - id, _, _, err = view2.GetEndpointService(ctx).Resolve(partyIdentity) + id, _, _, err = view2.NewEndpointService(ctx.resolver).Resolve(partyIdentity) if err == nil { s, ok = ctx.sessions[id.UniqueID()] if logger.IsEnabledFor(zapcore.DebugLevel) { diff --git a/platform/view/core/manager/context_test.go b/platform/view/core/manager/context_test.go index 18159e65d..5a067828d 100644 --- a/platform/view/core/manager/context_test.go +++ b/platform/view/core/manager/context_test.go @@ -16,7 +16,6 @@ import ( "github.com/hyperledger-labs/fabric-smart-client/platform/view/core/manager" mock2 "github.com/hyperledger-labs/fabric-smart-client/platform/view/core/manager/mock" - "github.com/hyperledger-labs/fabric-smart-client/platform/view/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/view/driver/mock" registry2 "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/registry" "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" @@ -33,22 +32,18 @@ func TestContext(t *testing.T) { registry := registry2.New() idProvider := &mock.IdentityProvider{} idProvider.DefaultIdentityReturns([]byte("alice")) - assert.NoError(t, registry.RegisterService(idProvider)) + assert.NoError(t, registry.RegisterService(&mock2.CommLayer{})) resolver := &mock.EndpointService{} resolver.GetIdentityReturns([]byte("bob"), nil) - assert.NoError(t, registry.RegisterService(resolver)) assert.NoError(t, registry.RegisterService(&mock2.SessionFactory{})) session := &mock.Session{} - ctx, err := manager.NewContext(context.TODO(), registry, "pineapple", nil, driver.GetEndpointService(registry), []byte("charlie"), session, []byte("caller"), emptyTracer) + ctx, err := manager.NewContext(context.TODO(), registry, "pineapple", nil, resolver, idProvider, nil, []byte("charlie"), session, []byte("caller"), emptyTracer) assert.NoError(t, err) // Session assert.Equal(t, session, ctx.Session()) - // GetService - assert.NotNil(t, driver.GetEndpointService(ctx)) - // Id assert.Equal(t, "pineapple", ctx.ID()) @@ -68,11 +63,9 @@ func TestContextRace(t *testing.T) { registry := registry2.New() idProvider := &mock.IdentityProvider{} idProvider.DefaultIdentityReturns([]byte("alice")) - assert.NoError(t, registry.RegisterService(idProvider)) assert.NoError(t, registry.RegisterService(&mock2.CommLayer{})) resolver := &mock.EndpointService{} resolver.GetIdentityReturns([]byte("bob"), nil) - assert.NoError(t, registry.RegisterService(resolver)) assert.NoError(t, registry.RegisterService(&mock2.SessionFactory{})) defaultSession := &mock.Session{} session := &mock.Session{} @@ -87,7 +80,7 @@ func TestContextRace(t *testing.T) { sessionFactory := &mock2.SessionFactory{} sessionFactory.NewSessionReturns(session, nil) - ctx, err := manager.NewContext(context.TODO(), registry, "pineapple", sessionFactory, resolver, []byte("charlie"), defaultSession, []byte("caller"), emptyTracer) + ctx, err := manager.NewContext(context.TODO(), registry, "pineapple", sessionFactory, resolver, idProvider, nil, []byte("charlie"), defaultSession, []byte("caller"), emptyTracer) assert.NoError(t, err) wg := &sync.WaitGroup{} diff --git a/platform/view/core/manager/manager.go b/platform/view/core/manager/manager.go index f070c472f..52d29d511 100644 --- a/platform/view/core/manager/manager.go +++ b/platform/view/core/manager/manager.go @@ -37,7 +37,8 @@ type manager struct { commLayer CommLayer endpointService driver.EndpointService - identityProvider driver.IdentityProvider + identityProvider identityProvider + sigService sigService ctx context.Context @@ -51,12 +52,13 @@ type manager struct { m *Metrics } -func New(serviceProvider driver.ServiceProvider, commLayer CommLayer, endpointService driver.EndpointService, identityProvider driver.IdentityProvider, viewProvider *registry.ViewProvider, provider trace.TracerProvider, metricsProvider metrics.Provider) *manager { +func New(serviceProvider driver.ServiceProvider, commLayer CommLayer, endpointService driver.EndpointService, identityProvider driver.IdentityProvider, sigService driver.SigService, viewProvider *registry.ViewProvider, provider trace.TracerProvider, metricsProvider metrics.Provider) *manager { return &manager{ sp: serviceProvider, commLayer: commLayer, endpointService: endpointService, identityProvider: identityProvider, + sigService: sigService, contexts: map[string]disposableContext{}, viewProvider: viewProvider, @@ -116,7 +118,7 @@ func (cm *manager) InitiateViewWithIdentity(view view.View, id view.Identity, c } ctx = trace.ContextWithSpanContext(ctx, trace.SpanContextFromContext(c)) - viewContext, err := NewContextForInitiator("", ctx, cm.sp, cm.commLayer, cm.endpointService, id, view, cm.viewTracer) + viewContext, err := NewContextForInitiator("", ctx, cm.sp, cm.commLayer, cm.endpointService, cm.identityProvider, cm.sigService, id, view, cm.viewTracer) if err != nil { return nil, err } @@ -159,7 +161,7 @@ func (cm *manager) InitiateContextFrom(ctx context.Context, view view.View, id v if id.IsNone() { id = cm.me() } - viewContext, err := NewContextForInitiator(contextID, ctx, cm.sp, cm.commLayer, cm.endpointService, id, view, cm.viewTracer) + viewContext, err := NewContextForInitiator(contextID, ctx, cm.sp, cm.commLayer, cm.endpointService, cm.identityProvider, cm.sigService, id, view, cm.viewTracer) if err != nil { return nil, err } @@ -316,7 +318,7 @@ func (cm *manager) newContext(id view.Identity, msg *view.Message) (view.Context return nil, false, err } ctx := trace.ContextWithSpanContext(cm.ctx, trace.SpanContextFromContext(msg.Ctx)) - newCtx, err := NewContext(ctx, cm.sp, contextID, cm.commLayer, cm.endpointService, id, backend, caller, cm.viewTracer) + newCtx, err := NewContext(ctx, cm.sp, contextID, cm.commLayer, cm.endpointService, cm.identityProvider, cm.sigService, id, backend, caller, cm.viewTracer) if err != nil { return nil, false, err } diff --git a/platform/view/core/manager/manager_test.go b/platform/view/core/manager/manager_test.go index 1ca99e27b..b4d766f95 100644 --- a/platform/view/core/manager/manager_test.go +++ b/platform/view/core/manager/manager_test.go @@ -63,7 +63,7 @@ func TestGetIdentifier(t *testing.T) { registry := registry2.New() idProvider := &mock.IdentityProvider{} idProvider.DefaultIdentityReturns([]byte("alice")) - manager := manager.New(registry, &mock2.CommLayer{}, &mock.EndpointService{}, idProvider, registry3.NewViewProvider(), noop.NewTracerProvider(), &disabled.Provider{}) + manager := manager.New(registry, &mock2.CommLayer{}, &mock.EndpointService{}, idProvider, nil, registry3.NewViewProvider(), noop.NewTracerProvider(), &disabled.Provider{}) assert.Equal(t, "github.com/hyperledger-labs/fabric-smart-client/platform/view/core/manager_test/DummyView", manager.GetIdentifier(DummyView{})) assert.Equal(t, "github.com/hyperledger-labs/fabric-smart-client/platform/view/core/manager_test/DummyView", manager.GetIdentifier(&DummyView{})) @@ -75,11 +75,9 @@ func TestManagerRace(t *testing.T) { registry := registry2.New() idProvider := &mock.IdentityProvider{} idProvider.DefaultIdentityReturns([]byte("alice")) - assert.NoError(t, registry.RegisterService(idProvider)) assert.NoError(t, registry.RegisterService(&mock2.CommLayer{})) - assert.NoError(t, registry.RegisterService(&mock.EndpointService{})) assert.NoError(t, registry.RegisterService(&mock2.SessionFactory{})) - manager := manager.New(registry, &mock2.CommLayer{}, &mock.EndpointService{}, idProvider, registry3.NewViewProvider(), noop.NewTracerProvider(), &disabled.Provider{}) + manager := manager.New(registry, &mock2.CommLayer{}, &mock.EndpointService{}, idProvider, nil, registry3.NewViewProvider(), noop.NewTracerProvider(), &disabled.Provider{}) wg := &sync.WaitGroup{} for i := 0; i < 100; i++ { @@ -98,8 +96,7 @@ func TestRegisterResponderWithInitiatorView(t *testing.T) { registry := registry2.New() idProvider := &mock.IdentityProvider{} idProvider.DefaultIdentityReturns([]byte("alice")) - - manager := manager.New(registry, &mock2.CommLayer{}, &mock.EndpointService{}, idProvider, registry3.NewViewProvider(), noop.NewTracerProvider(), &disabled.Provider{}) + manager := manager.New(registry, &mock2.CommLayer{}, &mock.EndpointService{}, idProvider, nil, registry3.NewViewProvider(), noop.NewTracerProvider(), &disabled.Provider{}) err := manager.RegisterResponder(&ResponderView{}, &InitiatorView{}) assert.NoError(t, err) responder, _, err := manager.ExistResponderForCaller(manager.GetIdentifier(&InitiatorView{})) @@ -115,7 +112,7 @@ func TestRegisterResponderWithViewIdentifier(t *testing.T) { idProvider := &mock.IdentityProvider{} idProvider.DefaultIdentityReturns([]byte("alice")) - manager := manager.New(registry, &mock2.CommLayer{}, &mock.EndpointService{}, idProvider, registry3.NewViewProvider(), noop.NewTracerProvider(), &disabled.Provider{}) + manager := manager.New(registry, &mock2.CommLayer{}, &mock.EndpointService{}, idProvider, nil, registry3.NewViewProvider(), noop.NewTracerProvider(), &disabled.Provider{}) err := manager.RegisterResponder(&ResponderView{}, manager.GetIdentifier(&InitiatorView{})) assert.NoError(t, err) responder, _, err := manager.ExistResponderForCaller(manager.GetIdentifier(&InitiatorView{})) diff --git a/platform/view/core/registry/viewprovider.go b/platform/view/core/registry/viewprovider.go index 30b90d64a..2d4b3c507 100644 --- a/platform/view/core/registry/viewprovider.go +++ b/platform/view/core/registry/viewprovider.go @@ -85,7 +85,7 @@ func (cm *ViewProvider) RegisterResponder(responder view.View, initiatedBy inter func (cm *ViewProvider) RegisterResponderWithIdentity(responder view.View, id view.Identity, initiatedBy interface{}) error { switch t := initiatedBy.(type) { case view.View: - cm.registerResponderWithIdentity(responder, id, cm.GetIdentifier(t)) + cm.registerResponderWithIdentity(responder, id, GetIdentifier(t)) case string: cm.registerResponderWithIdentity(responder, id, t) default: @@ -98,7 +98,7 @@ func (cm *ViewProvider) GetResponder(initiatedBy interface{}) (view.View, error) var initiatedByID string switch t := initiatedBy.(type) { case view.View: - initiatedByID = cm.GetIdentifier(t) + initiatedByID = GetIdentifier(t) case string: initiatedByID = t default: diff --git a/platform/view/driver/flowmanager.go b/platform/view/driver/flowmanager.go index 27cd12e60..dfdc55631 100644 --- a/platform/view/driver/flowmanager.go +++ b/platform/view/driver/flowmanager.go @@ -23,6 +23,8 @@ type ViewManager interface { InitiateView(view view.View, ctx context.Context) (interface{}, error) // InitiateContext initiates a new context for the passed view InitiateContext(view view.View) (view.Context, error) + // InitiateContextWithIdentity initiates a new context + InitiateContextWithIdentity(view view.View, id view.Identity) (view.Context, error) // InitiateContextWithIdentityAndID initiates a new context InitiateContextWithIdentityAndID(view view.View, id view.Identity, contextID string) (view.Context, error) // InitiateContextFrom initiates a new context for the passed view, derived from the passed context diff --git a/platform/view/driver/flowregistry.go b/platform/view/driver/flowregistry.go index 2a000b514..5e7f3a5a3 100644 --- a/platform/view/driver/flowregistry.go +++ b/platform/view/driver/flowregistry.go @@ -14,8 +14,6 @@ import ( // Registry keeps track of the available view and view factories type Registry interface { - // GetIdentifier returns the identifier of the passed view - GetIdentifier(f view.View) string // RegisterFactory binds an id to a View Factory RegisterFactory(id string, factory Factory) error diff --git a/platform/view/registry.go b/platform/view/registry.go index 6af0ef4eb..f1a021ad8 100644 --- a/platform/view/registry.go +++ b/platform/view/registry.go @@ -35,11 +35,6 @@ func NewRegistry(registry driver.Registry) *Registry { return &Registry{registry: registry} } -// GetIdentifier returns the identifier of the passed view -func (r *Registry) GetIdentifier(f View) string { - return r.registry.GetIdentifier(f) -} - // RegisterFactory binds an id to a View Factory func (r *Registry) RegisterFactory(id string, factory Factory) error { return r.registry.RegisterFactory(id, factory) diff --git a/platform/view/sdk/dig/sdk.go b/platform/view/sdk/dig/sdk.go index 212a9e830..ff254accf 100644 --- a/platform/view/sdk/dig/sdk.go +++ b/platform/view/sdk/dig/sdk.go @@ -53,7 +53,13 @@ type SDK struct { dig2.SDK } -func NewSDKFromContainer(c dig2.Container, registry node.Registry) *SDK { +type nodeRegistry interface { + node.Registry + RegisterViewManager(manager node.ViewManager) + RegisterViewRegistry(registry node.ViewRegistry) +} + +func NewSDKFromContainer(c dig2.Container, registry nodeRegistry) *SDK { configService := view.GetConfigService(registry) return NewSDKFrom(dig2.NewBaseSDK(c, configService), registry) } @@ -66,7 +72,7 @@ func NewSDKFrom(baseSDK dig2.SDK, registry node.Registry) *SDK { sdk := &SDK{SDK: baseSDK} err := errors.Join( sdk.Container().Provide(func() node.Registry { return registry }), - sdk.Container().Provide(digutils.Identity[node.Registry](), dig.As(new(driver.ServiceProvider), new(node.Registry), new(view.ServiceProvider), new(finality.Registry))), + sdk.Container().Provide(digutils.Identity[node.Registry](), dig.As(new(driver.ServiceProvider), new(nodeRegistry), new(view.ServiceProvider), new(node.ServiceRegisterer))), sdk.Container().Provide(func() *view.ConfigService { return view.GetConfigService(registry) }), sdk.Container().Provide(digutils.Identity[*view.ConfigService](), dig.As(new(driver.ConfigService), new(id.ConfigProvider), new(endpoint.ConfigService))), sdk.Container().Provide(view.NewRegistry), @@ -148,6 +154,7 @@ func (p *SDK) Install() error { } err = errors.Join( + digutils.Register[driver.ConfigService](p.Container()), digutils.Register[trace.TracerProvider](p.Container()), digutils.Register[driver.EndpointService](p.Container()), digutils.Register[view3.IdentityProvider](p.Container()), @@ -158,10 +165,11 @@ func (p *SDK) Install() error { return err } - if err := p.Container().Invoke(func(resolverService *endpoint.ResolverService) error { return resolverService.LoadResolvers() }); err != nil { - return err - } - return nil + return errors.Join( + p.Container().Invoke(func(resolverService *endpoint.ResolverService) error { return resolverService.LoadResolvers() }), + p.Container().Invoke(func(r nodeRegistry, s driver.ViewManager) { r.RegisterViewManager(s) }), + p.Container().Invoke(func(r nodeRegistry, s *view.Registry) { r.RegisterViewRegistry(s) }), + ) } func (p *SDK) Start(ctx context.Context) error { diff --git a/platform/view/sdk/dig/test_utils.go b/platform/view/sdk/dig/test_utils.go index ada4f3956..abfc46fc5 100644 --- a/platform/view/sdk/dig/test_utils.go +++ b/platform/view/sdk/dig/test_utils.go @@ -10,7 +10,9 @@ import ( "context" "time" + "github.com/hyperledger-labs/fabric-smart-client/pkg/node" dig2 "github.com/hyperledger-labs/fabric-smart-client/platform/common/sdk/dig" + "github.com/hyperledger-labs/fabric-smart-client/platform/view/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/registry" "go.uber.org/dig" ) @@ -64,7 +66,7 @@ func DryRunWiringWithContainer[S dig2.SDK](decorator func(sdk dig2.SDK) S, c dig if err := provider.RegisterService(config); err != nil { return err } - viewSDK := NewSDKFrom(dig2.NewBaseSDK(c, config), provider) + viewSDK := NewSDKFrom(dig2.NewBaseSDK(c, config), &mockNodeProvider{config, provider}) sdk := decorator(viewSDK) if err := sdk.Install(); err != nil { return err @@ -74,3 +76,12 @@ func DryRunWiringWithContainer[S dig2.SDK](decorator func(sdk dig2.SDK) S, c dig } return nil } + +type mockNodeProvider struct { + configService driver.ConfigService + *registry.ServiceProvider +} + +func (p *mockNodeProvider) ConfigService() driver.ConfigService { return p.configService } +func (p *mockNodeProvider) RegisterViewManager(node.ViewManager) {} +func (p *mockNodeProvider) RegisterViewRegistry(node.ViewRegistry) {} diff --git a/platform/view/sdk/finality/handler.go b/platform/view/sdk/finality/handler.go index b698287ea..945fecf7b 100644 --- a/platform/view/sdk/finality/handler.go +++ b/platform/view/sdk/finality/handler.go @@ -15,10 +15,6 @@ import ( "go.opentelemetry.io/otel/trace" ) -type Registry interface { - RegisterService(service interface{}) error -} - type Server interface { RegisterProcessor(typ reflect.Type, p view2.Processor) } diff --git a/platform/view/services/view/view.go b/platform/view/services/view/view.go index 8fa4cc90b..c1a9f43f9 100644 --- a/platform/view/services/view/view.go +++ b/platform/view/services/view/view.go @@ -7,7 +7,6 @@ SPDX-License-Identifier: Apache-2.0 package view import ( - view2 "github.com/hyperledger-labs/fabric-smart-client/platform/view" "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" ) @@ -19,13 +18,6 @@ func RunCall(context view.Context, v func(context view.Context) (interface{}, er ) } -// Initiate initiates a new protocol whose initiator's view is the passed one. -// The execution happens in a freshly created context. -// This is a shortcut for `view.GetManager(context).InitiateView(initiator)`. -func Initiate(context view.Context, initiator view.View) (interface{}, error) { - return view2.GetManager(context).InitiateView(initiator, context.Context()) -} - // AsResponder can be used by an initiator to behave temporarily as a responder. // Recall that a responder is characterized by having a default session (`context.Session()`) established by an initiator. func AsResponder(context view.Context, session view.Session, v func(context view.Context) (interface{}, error)) (interface{}, error) {