Skip to content
3 changes: 0 additions & 3 deletions token/driver/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ type IdentityProvider interface {
// GetSigner returns a Signer for passed identity.
GetSigner(ctx context.Context, identity Identity) (Signer, error)

// RegisterVerifier registers a Verifier for passed identity.
RegisterVerifier(ctx context.Context, identity Identity, v Verifier) error

// RegisterSigner registers a Signer and a Verifier for passed identity.
RegisterSigner(ctx context.Context, identity Identity, signer Signer, verifier Verifier, signerInfo []byte, ephemeral bool) error

Expand Down
115 changes: 49 additions & 66 deletions token/services/identity/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/hyperledger-labs/fabric-token-sdk/token/driver"
idriver "github.com/hyperledger-labs/fabric-token-sdk/token/services/identity/driver"
"github.com/hyperledger-labs/fabric-token-sdk/token/services/logging"
cache2 "github.com/hyperledger-labs/fabric-token-sdk/token/services/utils/cache"
"go.uber.org/zap/zapcore"
)

Expand Down Expand Up @@ -73,7 +74,6 @@ type Provider struct {

isMeCache cache[bool]
signers cache[*SignerEntry]
verifiers cache[*VerifierEntry]
}

// NewProvider creates a new identity provider implementing the driver.IdentityProvider interface.
Expand All @@ -91,9 +91,8 @@ func NewProvider(
enrollmentIDUnmarshaler: enrollmentIDUnmarshaler,
deserializer: deserializer,
storage: storage,
isMeCache: secondcache.NewTyped[bool](5000),
signers: secondcache.NewTyped[*SignerEntry](5000),
verifiers: secondcache.NewTyped[*VerifierEntry](5000),
isMeCache: cache2.NewNoCache[bool](),
signers: secondcache.NewTyped[*SignerEntry](50),
}
}

Expand All @@ -113,20 +112,6 @@ func (p *Provider) RegisterIdentityDescriptor(ctx context.Context, identityDescr
return nil
}

func (p *Provider) RegisterVerifier(ctx context.Context, identity driver.Identity, v driver.Verifier) error {
if v == nil {
return errors.New("invalid verifier, expected a valid instance")
}
idHash := identity.UniqueID()
entry := &VerifierEntry{Verifier: v}
if p.Logger.IsEnabledFor(zapcore.DebugLevel) {
entry.DebugStack = debug.Stack()
}
p.verifiers.Add(idHash, entry)
p.Logger.DebugfContext(ctx, "register verifier to [%s]:[%s]", idHash, logging.Identifier(v))
return nil
}

func (p *Provider) RegisterAuditInfo(ctx context.Context, identity driver.Identity, info []byte) error {
return p.storage.StoreIdentityData(ctx, identity, info, nil, nil)
}
Expand Down Expand Up @@ -261,55 +246,64 @@ func (p *Provider) areMe(ctx context.Context, identities ...driver.Identity) []s
}

func (p *Provider) getSigner(ctx context.Context, identity driver.Identity, idHash string) (driver.Signer, error) {
// check again the cache
entry, ok := p.signers.Get(idHash)
if ok {
signer, _, err := p.getSignerAndCache(ctx, identity, idHash, true)
return signer, err
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we said to cache only the identity whose type is x509, no?
If we still cache the signers and the cache is only of size 5 there will be even more contention, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually we said to have the first PR use NoCache and a 2nd PR avoid caching x509.
The system doesn't work with signers being NoCache, so I limited the cache to 5 instead.

but sure. I added to this PR avoiding to insert x509 into the cache and increased the signer cache to 50.

func (p *Provider) getSignerAndCache(ctx context.Context, identity driver.Identity, idHash string, shouldCache bool) (driver.Signer, bool, error) {
// check cache
if entry, ok := p.signers.Get(idHash); ok {
p.Logger.DebugfContext(ctx, "signer for [%s] found", idHash)
return entry.Signer, nil
return entry.Signer, false, nil
}

p.Logger.DebugfContext(ctx, "signer for [%s] not found, try to deserialize", idHash)
// ask the deserializer
signer, err := p.deserializeSigner(ctx, identity)
if err != nil {
return nil, errors.Wrapf(err, "failed deserializing identity for signer [%s]", identity)
}
entry = &SignerEntry{Signer: signer}
if p.Logger.IsEnabledFor(zapcore.DebugLevel) {
entry.DebugStack = debug.Stack()
}
p.signers.Add(idHash, entry)
if err := p.storage.StoreSignerInfo(ctx, identity, nil); err != nil {
return nil, errors.Wrap(err, "failed to store entry in storage for the passed signer")
}
return entry.Signer, nil
}
p.Logger.DebugfContext(ctx, "signer for [%s] not found, attempting to deserialize", idHash)

func (p *Provider) deserializeSigner(ctx context.Context, identity driver.Identity) (driver.Signer, error) {
// check that we have a deserializer
if p.deserializer == nil {
return nil, errors.Errorf("cannot find signer for [%s], no deserializer set", identity)
return nil, false, errors.Errorf("cannot find signer for [%s], no deserializer set", identity)
}
var err error

// try direct deserialization
signer, err := p.deserializer.DeserializeSigner(ctx, identity)
if err == nil {
return signer, nil
}
if err != nil {
// second chance: try a TypedIdentity
typed, err2 := UnmarshalTypedIdentity(identity)
if err2 != nil {
// neither deserializable nor a typed wrapper
return nil, false, errors.Wrapf(
err2,
"failed to unmarshal typed identity for [%s] and failed deserialization [%s]",
identity.String(), err,
)
}

// give it a second chance
if typed.Type == "x509" {
shouldCache = false
}

// is the identity wrapped in TypedIdentity?
ro, err2 := UnmarshalTypedIdentity(identity)
if err2 != nil {
// No
return nil, errors.Wrapf(err2, "failed to unmarshal raw owner for identity [%s] and failed deserialization [%s]", identity.String(), err)
// recursively resolve the inner identity
signer, shouldCache, err = p.getSignerAndCache(ctx, typed.Identity, typed.Identity.UniqueID(), shouldCache)
if err != nil {
return nil, false, errors.Wrapf(err, "failed getting signer for identity [%s]", typed.Identity)
}
}

// yes, check ro.Identity
signer, err = p.getSigner(ctx, ro.Identity, ro.Identity.UniqueID())
if err != nil {
return nil, errors.Wrapf(err, "failed getting signer for identity [%s]", ro.Identity)
// Cache the signer for the current idHash
if shouldCache {
entry := &SignerEntry{Signer: signer}
if p.Logger.IsEnabledFor(zapcore.DebugLevel) {
entry.DebugStack = debug.Stack()
}
p.signers.Add(idHash, entry)
}
return signer, nil

// Persist signer info for the current identity
if err := p.storage.StoreSignerInfo(ctx, identity, nil); err != nil {
return nil, false, errors.Wrap(err, "failed to store entry in storage for the passed signer")
}

return signer, shouldCache, nil
}

func (p *Provider) updateCaches(descriptor *idriver.IdentityDescriptor, alias driver.Identity) {
Expand All @@ -331,15 +325,4 @@ func (p *Provider) updateCaches(descriptor *idriver.IdentityDescriptor, alias dr
p.signers.Add(aliasID, entry)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are still caching any signer no matter the identity type. This will generate even more contention on the signers cache given its new size (5)

// verifiers
if descriptor.Verifier != nil {
entry := &VerifierEntry{Verifier: descriptor.Verifier}
if p.Logger.IsEnabledFor(zapcore.DebugLevel) {
entry.DebugStack = debug.Stack()
}
p.verifiers.Add(id, entry)
if setAlias {
p.verifiers.Add(aliasID, entry)
}
}
}
8 changes: 0 additions & 8 deletions token/services/identity/wallet/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,6 @@ func (s *Service) RegisterRecipientIdentity(ctx context.Context, data *driver.Re
return errors.Wrapf(err, "failed to match identity to audit infor for [%s]:[%s]", data.Identity, utils.Hashable(data.AuditInfo))
}

// register verifier and audit info
v, err := s.Deserializer.GetOwnerVerifier(ctx, data.Identity)
if err != nil {
return errors.Wrapf(err, "failed getting verifier for owner [%s]", data.Identity)
}
if err := s.IdentityProvider.RegisterVerifier(ctx, data.Identity, v); err != nil {
return errors.Wrapf(err, "failed registering verifier for owner [%s]", data.Identity)
}
if err := s.IdentityProvider.RegisterRecipientData(ctx, data); err != nil {
return errors.Wrapf(err, "failed registering audit info for owner [%s]", data.Identity)
}
Expand Down
8 changes: 0 additions & 8 deletions token/services/identity/wallet/wallets.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,14 +346,6 @@ func (w *AnonymousOwnerWallet) RegisterRecipient(ctx context.Context, data *driv
if err != nil {
return errors.Wrapf(err, "failed to match identity to audit infor for [%s]:[%s]", data.Identity, utils.Hashable(data.AuditInfo))
}
// register verifier and audit info
v, err := w.Deserializer.GetOwnerVerifier(ctx, data.Identity)
if err != nil {
return errors.Wrapf(err, "failed getting verifier for owner [%s]", data.Identity)
}
if err := w.IdentityProvider.RegisterVerifier(ctx, data.Identity, v); err != nil {
return errors.Wrapf(err, "failed registering verifier for owner [%s]", data.Identity)
}
if err := w.IdentityProvider.RegisterRecipientData(ctx, data); err != nil {
return errors.Wrapf(err, "failed registering audit info for owner [%s]", data.Identity)
}
Expand Down
Loading