github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/identity/selector/handler.go (about)

     1  /*
     2   * Copyright (C) 2017 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package selector
    19  
    20  import (
    21  	"fmt"
    22  	"sync"
    23  
    24  	"github.com/mysteriumnetwork/node/identity"
    25  	"github.com/pkg/errors"
    26  	"github.com/rs/zerolog/log"
    27  )
    28  
    29  type handler struct {
    30  	mu            sync.Mutex
    31  	manager       identity.Manager
    32  	cache         identity.IdentityCacheInterface
    33  	signerFactory identity.SignerFactory
    34  }
    35  
    36  // NewHandler creates new identity handler used by node
    37  func NewHandler(
    38  	manager identity.Manager,
    39  	cache identity.IdentityCacheInterface,
    40  	signerFactory identity.SignerFactory,
    41  ) *handler {
    42  	return &handler{
    43  		manager:       manager,
    44  		cache:         cache,
    45  		signerFactory: signerFactory,
    46  	}
    47  }
    48  
    49  func (h *handler) UseOrCreate(address, passphrase string, chainID int64) (id identity.Identity, err error) {
    50  	h.mu.Lock()
    51  	defer h.mu.Unlock()
    52  
    53  	if len(address) > 0 {
    54  		log.Debug().Msg("Using existing identity")
    55  		return h.useExisting(address, passphrase, chainID)
    56  	}
    57  
    58  	identities := h.manager.GetIdentities()
    59  	if len(identities) == 0 {
    60  		log.Debug().Msg("Creating new identity")
    61  		return h.useNew(passphrase, chainID)
    62  	}
    63  
    64  	id, err = h.useLast(passphrase, chainID)
    65  	if err != nil || !h.manager.HasIdentity(id.Address) {
    66  		log.Debug().Msg("Using existing identity")
    67  		return h.useExisting(identities[0].Address, passphrase, chainID)
    68  	}
    69  
    70  	return
    71  }
    72  
    73  func (h *handler) SetDefault(address string) error {
    74  	id, err := h.manager.GetIdentity(address)
    75  	if err != nil {
    76  		return err
    77  	}
    78  
    79  	return h.cache.StoreIdentity(id)
    80  }
    81  
    82  func (h *handler) useExisting(address, passphrase string, chainID int64) (id identity.Identity, err error) {
    83  	log.Debug().Msg("Attempting to use existing identity")
    84  	id, err = h.manager.GetIdentity(address)
    85  	if err != nil {
    86  		return id, err
    87  	}
    88  
    89  	if err = h.manager.Unlock(chainID, id.Address, passphrase); err != nil {
    90  		return id, fmt.Errorf("failed to unlock identity: %w", err)
    91  	}
    92  
    93  	err = h.cache.StoreIdentity(id)
    94  	return id, err
    95  }
    96  
    97  func (h *handler) useLast(passphrase string, chainID int64) (identity identity.Identity, err error) {
    98  	log.Debug().Msg("Attempting to use last identity")
    99  	identity, err = h.cache.GetIdentity()
   100  	if err != nil || !h.manager.HasIdentity(identity.Address) {
   101  		return identity, errors.New("identity not found in cache")
   102  	}
   103  	log.Debug().Msg("Found identity in cache: " + identity.Address)
   104  
   105  	if err = h.manager.Unlock(chainID, identity.Address, passphrase); err != nil {
   106  		return identity, errors.Wrap(err, "failed to unlock identity")
   107  	}
   108  	log.Debug().Msg("Unlocked identity: " + identity.Address)
   109  
   110  	return identity, nil
   111  }
   112  
   113  func (h *handler) useNew(passphrase string, chainID int64) (id identity.Identity, err error) {
   114  	log.Debug().Msg("Attempting to use new identity")
   115  	// if all fails, create a new one
   116  	id, err = h.manager.CreateNewIdentity(passphrase)
   117  	if err != nil {
   118  		return id, errors.Wrap(err, "failed to create identity")
   119  	}
   120  
   121  	if err = h.manager.Unlock(chainID, id.Address, passphrase); err != nil {
   122  		return id, errors.Wrap(err, "failed to unlock identity")
   123  	}
   124  
   125  	err = h.cache.StoreIdentity(id)
   126  	return id, errors.Wrap(err, "failed to store identity in cache")
   127  }