github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/identity/registry/storage.go (about) 1 /* 2 * Copyright (C) 2019 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 registry 19 20 import ( 21 "fmt" 22 "sync" 23 "time" 24 25 "github.com/mysteriumnetwork/node/identity" 26 "github.com/pkg/errors" 27 ) 28 29 const registrationStatusBucket = "registry_statuses" 30 31 type persistentStorage interface { 32 Store(bucket string, data interface{}) error 33 GetOneByField(bucket string, fieldName string, key interface{}, to interface{}) error 34 GetAllFrom(bucket string, data interface{}) error 35 } 36 37 var errBoltNotFound = "not found" 38 39 // ErrNotFound represents an error where no info could be found in storage 40 var ErrNotFound = errors.New("no info for provided identity available in storage") 41 42 // RegistrationStatusStorage allows for storing of registration statuses. 43 type RegistrationStatusStorage struct { 44 lock sync.Mutex 45 bolt persistentStorage 46 } 47 48 type storedRegistrationStatus struct { 49 ID string `storm:"id"` 50 StoredRegistrationStatus 51 } 52 53 // NewRegistrationStatusStorage returns a new instance of the registration status storage 54 func NewRegistrationStatusStorage(bolt persistentStorage) *RegistrationStatusStorage { 55 return &RegistrationStatusStorage{ 56 bolt: bolt, 57 } 58 } 59 60 // Store stores the given promise for the given hermes. 61 func (rss *RegistrationStatusStorage) Store(status StoredRegistrationStatus) error { 62 rss.lock.Lock() 63 defer rss.lock.Unlock() 64 65 s, err := rss.get(status.ChainID, status.Identity) 66 if err == ErrNotFound { 67 return rss.store(status) 68 } else if err != nil { 69 return err 70 } 71 72 switch s.RegistrationStatus { 73 // can not be overridden 74 case Registered: 75 return nil 76 default: 77 s.RegistrationStatus = status.RegistrationStatus 78 } 79 80 return rss.store(s) 81 } 82 83 func (rss *RegistrationStatusStorage) store(status StoredRegistrationStatus) error { 84 status.UpdatedAt = time.Now().UTC() 85 store := &storedRegistrationStatus{ 86 ID: rss.makeKey(status.Identity, status.ChainID), 87 StoredRegistrationStatus: status, 88 } 89 90 err := rss.bolt.Store(registrationStatusBucket, store) 91 return errors.Wrap(err, "could not store registration status") 92 } 93 94 func (rss *RegistrationStatusStorage) get(chainID int64, identity identity.Identity) (StoredRegistrationStatus, error) { 95 result := &storedRegistrationStatus{} 96 err := rss.bolt.GetOneByField(registrationStatusBucket, "ID", rss.makeKey(identity, chainID), result) 97 if err != nil { 98 if err.Error() == errBoltNotFound { 99 return StoredRegistrationStatus{}, ErrNotFound 100 } 101 return StoredRegistrationStatus{}, errors.Wrap(err, "could not get registration status") 102 } 103 return result.StoredRegistrationStatus, err 104 } 105 106 // Get fetches the promise for the given hermes. 107 func (rss *RegistrationStatusStorage) Get(chainID int64, identity identity.Identity) (StoredRegistrationStatus, error) { 108 rss.lock.Lock() 109 defer rss.lock.Unlock() 110 return rss.get(chainID, identity) 111 } 112 113 // GetAll fetches all the registration statuses 114 func (rss *RegistrationStatusStorage) GetAll() ([]StoredRegistrationStatus, error) { 115 rss.lock.Lock() 116 defer rss.lock.Unlock() 117 118 list := []storedRegistrationStatus{} 119 err := rss.bolt.GetAllFrom(registrationStatusBucket, &list) 120 if err != nil { 121 if err.Error() == errBoltNotFound { 122 return nil, ErrNotFound 123 } 124 return nil, errors.Wrap(err, "could not get all registration statuses") 125 } 126 127 result := make([]StoredRegistrationStatus, len(list)) 128 for i, l := range list { 129 result[i] = l.StoredRegistrationStatus 130 } 131 return result, nil 132 } 133 134 func (rss *RegistrationStatusStorage) makeKey(identity identity.Identity, chainID int64) string { 135 return fmt.Sprintf("%s|%d", identity.Address, chainID) 136 }