Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit ecb7b03

Browse files
committed
[FAB-8944] Channel configuration cache refresh
Change-Id: I652baea135602648059fdb61be45239306beac5c Signed-off-by: Divyank Katira <Divyank.Katira@securekey.com>
1 parent ff9763c commit ecb7b03

26 files changed

+531
-115
lines changed

pkg/client/channel/chclient.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,10 @@ func (cc *Client) prepareHandlerContexts(reqCtx reqContext.Context, request Requ
174174
return nil, nil, errors.New("ChaincodeID and Fcn are required")
175175
}
176176

177-
chConfig := cc.context.ChannelService().ChannelConfig()
177+
chConfig, err := cc.context.ChannelService().ChannelConfig()
178+
if err != nil {
179+
return nil, nil, errors.WithMessage(err, "failed to retrieve channel config")
180+
}
178181
transactor, err := cc.context.InfraProvider().CreateChannelTransactor(reqCtx, chConfig)
179182
if err != nil {
180183
return nil, nil, errors.WithMessage(err, "failed to create transactor")

pkg/client/resmgmt/resmgmt.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,10 @@ func (rc *Client) sendCCProposal(reqCtx reqContext.Context, ccProposalType chain
546546
return errors.WithMessage(err, "Unable to get channel service")
547547
}
548548

549-
chConfig := channelService.ChannelConfig()
549+
chConfig, err := channelService.ChannelConfig()
550+
if err != nil {
551+
return errors.WithMessage(err, "get channel config failed")
552+
}
550553
transactor, err := rc.ctx.InfraProvider().CreateChannelTransactor(reqCtx, chConfig)
551554
if err != nil {
552555
return errors.WithMessage(err, "get channel transactor failed")

pkg/common/providers/core/provider.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ const (
9191
PeerResponse
9292
// ResMgmt timeout is default overall timeout for all resource management operations
9393
ResMgmt
94+
// ChannelConfigRefresh channel configuration refresh interval
95+
ChannelConfigRefresh
96+
// ChannelMembershipRefresh channel membership refresh interval
97+
ChannelMembershipRefresh
9498
)
9599

96100
// EventServiceType specifies the type of event service to use

pkg/common/providers/fab/context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ type ChannelService interface {
1111
Config() (ChannelConfig, error)
1212
EventService() (EventService, error)
1313
Membership() (ChannelMembership, error)
14-
ChannelConfig() ChannelCfg
14+
ChannelConfig() (ChannelCfg, error)
1515
}
1616

1717
// Transactor supplies methods for sending transaction proposals and transactions.

pkg/common/providers/fab/provider.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ type ClientContext interface {
2929
// InfraProvider enables access to fabric objects such as peer and user based on config or
3030
type InfraProvider interface {
3131
CreateChannelConfig(name string) (ChannelConfig, error)
32+
CreateChannelCfg(ctx ClientContext, channelID string) (ChannelCfg, error)
3233
CreateChannelTransactor(reqCtx reqContext.Context, cfg ChannelCfg) (Transactor, error)
33-
CreateChannelMembership(cfg ChannelCfg) (ChannelMembership, error)
34-
CreateEventService(ctx ClientContext, chConfig ChannelCfg) (EventService, error)
34+
CreateChannelMembership(ctx ClientContext, channelID string) (ChannelMembership, error)
35+
CreateEventService(ctx ClientContext, channelID string) (EventService, error)
3536
CreatePeerFromConfig(peerCfg *core.NetworkPeer) (Peer, error)
3637
CreateOrdererFromConfig(cfg *core.OrdererConfig) (Orderer, error)
3738
CommManager() CommManager

pkg/core/config/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,10 @@ func (c *Config) getTimeout(tType core.TimeoutType) time.Duration {
572572
timeout = c.configViper.GetDuration("client.orderer.timeout.connection")
573573
case core.OrdererResponse:
574574
timeout = c.configViper.GetDuration("client.orderer.timeout.response")
575+
case core.ChannelConfigRefresh:
576+
timeout = c.configViper.GetDuration("client.global.timeout.cache.channelConfig")
577+
case core.ChannelMembershipRefresh:
578+
timeout = c.configViper.GetDuration("client.global.timeout.cache.channelMembership")
575579
case core.CacheSweepInterval: // EXPERIMENTAL - do we need this to be configurable?
576580
timeout = c.configViper.GetDuration("client.cache.interval.sweep")
577581
if timeout == 0 {
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
Copyright SecureKey Technologies Inc. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package membership
8+
9+
import (
10+
"crypto/sha256"
11+
"time"
12+
13+
"github.com/hyperledger/fabric-sdk-go/pkg/util/concurrent/lazycache"
14+
"github.com/hyperledger/fabric-sdk-go/pkg/util/concurrent/lazyref"
15+
16+
"github.com/pkg/errors"
17+
)
18+
19+
// CacheKey membership reference cache key
20+
type CacheKey interface {
21+
lazycache.Key
22+
Context() Context
23+
ChannelID() string
24+
ChConfigRef() *lazyref.Reference
25+
}
26+
27+
// CacheKey holds a key for the cache
28+
type cacheKey struct {
29+
key string
30+
context Context
31+
channelID string
32+
chConfigRef *lazyref.Reference
33+
}
34+
35+
// NewCacheKey returns a new CacheKey
36+
func NewCacheKey(context Context, chConfigRef *lazyref.Reference, channelID string) (CacheKey, error) {
37+
h := sha256.New()
38+
hash := h.Sum([]byte(channelID))
39+
40+
return &cacheKey{
41+
key: string(hash),
42+
context: context,
43+
chConfigRef: chConfigRef,
44+
channelID: channelID,
45+
}, nil
46+
}
47+
48+
// NewRefCache a cache of membership references that refreshed with the
49+
// given interval
50+
func NewRefCache(refresh time.Duration) *lazycache.Cache {
51+
initializer := func(key lazycache.Key) (interface{}, error) {
52+
ck, ok := key.(CacheKey)
53+
if !ok {
54+
return nil, errors.New("Unexpected cache key")
55+
}
56+
return NewRef(refresh, ck.Context(), ck.ChConfigRef()), nil
57+
}
58+
59+
return lazycache.New("Membership_Cache", initializer)
60+
}
61+
62+
// String returns the key as a string
63+
func (k *cacheKey) String() string {
64+
return k.key
65+
}
66+
67+
// Context returns the context
68+
func (k *cacheKey) Context() Context {
69+
return k.context
70+
}
71+
72+
// ChannelID returns the channelID
73+
func (k *cacheKey) ChannelID() string {
74+
return k.channelID
75+
}
76+
77+
// ChConfigRef returns the channel config reference
78+
func (k *cacheKey) ChConfigRef() *lazyref.Reference {
79+
return k.chConfigRef
80+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
Copyright SecureKey Technologies Inc. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package membership
8+
9+
import (
10+
"time"
11+
12+
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
13+
"github.com/hyperledger/fabric-sdk-go/pkg/util/concurrent/lazyref"
14+
"github.com/pkg/errors"
15+
)
16+
17+
// Ref membership reference that refreshes to load the given channel config reference
18+
type Ref struct {
19+
*lazyref.Reference
20+
chConfigRef *lazyref.Reference
21+
context Context
22+
}
23+
24+
// NewRef returns a new membership reference
25+
func NewRef(refresh time.Duration, context Context, chConfigRef *lazyref.Reference) *Ref {
26+
ref := &Ref{
27+
chConfigRef: chConfigRef,
28+
context: context,
29+
}
30+
31+
ref.Reference = lazyref.New(
32+
ref.initializer(),
33+
lazyref.WithRefreshInterval(lazyref.InitImmediately, refresh),
34+
)
35+
36+
return ref
37+
}
38+
39+
// Validate calls validate on the underlying reference
40+
func (ref *Ref) Validate(serializedID []byte) error {
41+
membership, err := ref.get()
42+
if err != nil {
43+
return err
44+
}
45+
return membership.Validate(serializedID)
46+
}
47+
48+
// Verify calls validate on the underlying reference
49+
func (ref *Ref) Verify(serializedID []byte, msg []byte, sig []byte) error {
50+
membership, err := ref.get()
51+
if err != nil {
52+
return err
53+
}
54+
return membership.Verify(serializedID, msg, sig)
55+
}
56+
57+
func (ref *Ref) get() (fab.ChannelMembership, error) {
58+
m, err := ref.Get()
59+
if err != nil {
60+
return nil, err
61+
}
62+
return m.(fab.ChannelMembership), nil
63+
}
64+
65+
func (ref *Ref) initializer() lazyref.Initializer {
66+
return func() (interface{}, error) {
67+
logger.Debugf("Creating membership...")
68+
69+
channelCfg, err := ref.chConfigRef.Get()
70+
if err != nil {
71+
return nil, errors.WithMessage(err, "could not get channel config from reference")
72+
}
73+
cfg, ok := channelCfg.(fab.ChannelCfg)
74+
if !ok {
75+
return nil, errors.New("chConfigRef.Get() returned unexpected value ")
76+
}
77+
78+
//TODO: create new membership only if config block number has changed
79+
membership, err := New(ref.context, cfg)
80+
if err != nil {
81+
return nil, err
82+
}
83+
84+
return membership, nil
85+
}
86+
}

pkg/fab/chconfig/cache.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
Copyright SecureKey Technologies Inc. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package chconfig
8+
9+
import (
10+
"crypto/sha256"
11+
"time"
12+
13+
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
14+
"github.com/hyperledger/fabric-sdk-go/pkg/util/concurrent/lazycache"
15+
16+
"github.com/pkg/errors"
17+
)
18+
19+
// Provider provides ChannelConfig
20+
type Provider func(channelID string) (fab.ChannelConfig, error)
21+
22+
// CacheKey channel config reference cache key
23+
type CacheKey interface {
24+
lazycache.Key
25+
Context() fab.ClientContext
26+
ChannelID() string
27+
Provider() Provider
28+
}
29+
30+
// CacheKey holds a key for the provider cache
31+
type cacheKey struct {
32+
key string
33+
channelID string
34+
context fab.ClientContext
35+
pvdr Provider
36+
}
37+
38+
// NewCacheKey returns a new CacheKey
39+
func NewCacheKey(ctx fab.ClientContext, pvdr Provider, channelID string) (CacheKey, error) {
40+
identity, err := ctx.Serialize()
41+
if err != nil {
42+
return nil, err
43+
}
44+
45+
h := sha256.New()
46+
h.Write(identity)
47+
hash := h.Sum([]byte(channelID))
48+
49+
return &cacheKey{
50+
key: string(hash),
51+
channelID: channelID,
52+
context: ctx,
53+
pvdr: pvdr,
54+
}, nil
55+
}
56+
57+
// NewRefCache a cache of channel config references that refreshed with the
58+
// given interval
59+
func NewRefCache(refresh time.Duration) *lazycache.Cache {
60+
initializer := func(key lazycache.Key) (interface{}, error) {
61+
ck, ok := key.(CacheKey)
62+
if !ok {
63+
return nil, errors.New("Unexpected cache key")
64+
}
65+
return NewRef(refresh, ck.Provider(), ck.ChannelID(), ck.Context()), nil
66+
}
67+
68+
return lazycache.New("Channel_Cfg_Cache", initializer)
69+
}
70+
71+
// String returns the key as a string
72+
func (k *cacheKey) String() string {
73+
return k.key
74+
}
75+
76+
// Context returns the Context
77+
func (k *cacheKey) Context() fab.ClientContext {
78+
return k.context
79+
}
80+
81+
// ChannelID returns the channelID
82+
func (k *cacheKey) ChannelID() string {
83+
return k.channelID
84+
}
85+
86+
// Provider channel configuration provider
87+
func (k *cacheKey) Provider() Provider {
88+
return k.pvdr
89+
}

pkg/fab/chconfig/reference.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
Copyright SecureKey Technologies Inc. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package chconfig
8+
9+
import (
10+
"time"
11+
12+
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core"
13+
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
14+
contextImpl "github.com/hyperledger/fabric-sdk-go/pkg/context"
15+
"github.com/hyperledger/fabric-sdk-go/pkg/util/concurrent/lazyref"
16+
"github.com/pkg/errors"
17+
)
18+
19+
// Ref channel configuration lazy reference
20+
type Ref struct {
21+
*lazyref.Reference
22+
pvdr Provider
23+
ctx fab.ClientContext
24+
channelID string
25+
closed int32
26+
}
27+
28+
// NewRef returns a new channel config reference
29+
func NewRef(refresh time.Duration, pvdr Provider, channel string, ctx fab.ClientContext) *Ref {
30+
cfgRef := &Ref{
31+
pvdr: pvdr,
32+
ctx: ctx,
33+
channelID: channel,
34+
}
35+
36+
cfgRef.Reference = lazyref.New(
37+
cfgRef.initializer(),
38+
lazyref.WithRefreshInterval(lazyref.InitImmediately, refresh),
39+
)
40+
41+
return cfgRef
42+
}
43+
44+
func (ref *Ref) initializer() lazyref.Initializer {
45+
return func() (interface{}, error) {
46+
chConfigProvider, err := ref.pvdr(ref.channelID)
47+
if err != nil {
48+
return nil, errors.WithMessage(err, "error creating channel config provider")
49+
}
50+
51+
reqCtx, cancel := contextImpl.NewRequest(ref.ctx, contextImpl.WithTimeoutType(core.PeerResponse))
52+
defer cancel()
53+
54+
chConfig, err := chConfigProvider.Query(reqCtx)
55+
if err != nil {
56+
return nil, err
57+
}
58+
59+
return chConfig, nil
60+
}
61+
}

0 commit comments

Comments
 (0)