diff --git a/hermes/cmd/app.go b/hermes/cmd/app.go index 8efadcf60..0fa520aad 100644 --- a/hermes/cmd/app.go +++ b/hermes/cmd/app.go @@ -125,6 +125,10 @@ func runApp(ctx context.Context, conf *config.Config) error { // entities pastelClient := pastel.NewClient(conf.Pastel, conf.Pastel.BurnAddress()) + if conf.PassPhrase == "" { + return errors.New("passphrase is empty, please provide passphrase in config file") + } + // Try to get PastelID from cnode API MasterNodeStatus extKey, err := mixins.GetPastelIDfromMNConfig(ctx, pastelClient, conf.PastelID) if err != nil { @@ -132,6 +136,11 @@ func runApp(ctx context.Context, conf *config.Config) error { } conf.PastelID = extKey + // Validate PastelID and passphrase + if !mixins.ValidateUser(ctx, pastelClient, conf.PastelID, conf.PassPhrase) { + return errors.New("invalid pastelID or passphrase") + } + secInfo := &alts.SecInfo{ PastelID: conf.PastelID, PassPhrase: conf.PassPhrase, diff --git a/mixins/common.go b/mixins/common.go index 04a2cddd3..c8170b0b6 100644 --- a/mixins/common.go +++ b/mixins/common.go @@ -3,6 +3,7 @@ package mixins import ( "context" "fmt" + "strings" "time" "github.com/pastelnetwork/gonode/common/log" @@ -23,11 +24,13 @@ func GetPastelIDfromMNConfig(ctx context.Context, pastelClient pastel.Client, co if err != nil { log.Warnf("Error getting master-node status: %v", err) // Updated log message } else { - if mnStatus.ExtKey == "" { + if strings.TrimSpace(mnStatus.ExtKey) == "" { log.Warn("extKey is empty") } else { - if mnStatus.ExtKey != confKey { - log.Warnf("Warning! pastel IDs do not match - ID in config: %s - ID from cnode API( this will be used ): %s\n", confKey, extKey) + if strings.TrimSpace(confKey) == "" { + log.Warn("no pastelID in config file, override with the one from cnode API") + } else if mnStatus.ExtKey != confKey { + log.Warnf("Warning! pastel IDs do not match - ID in config: %s - ID from cnode API( this will be used ): %s\n", confKey, mnStatus.ExtKey) } extKey = mnStatus.ExtKey // Save the extKey return extKey, nil // Successfully found a matching extKey, return it @@ -43,3 +46,9 @@ func GetPastelIDfromMNConfig(ctx context.Context, pastelClient pastel.Client, co log.Warnf("Unable to get pastelID from mn config API - error after retries.") return "", fmt.Errorf("failed to get pastelID after %d retries", maxRetries) } + +// ValidateUser validates user by id and password. +func ValidateUser(ctx context.Context, pc pastel.Client, id string, pass string) bool { + _, err := pc.Sign(ctx, []byte("data"), id, pass, pastel.SignAlgorithmED448) + return err == nil +} diff --git a/supernode/cmd/app.go b/supernode/cmd/app.go index 3928449fc..cd9d0d02f 100644 --- a/supernode/cmd/app.go +++ b/supernode/cmd/app.go @@ -186,12 +186,22 @@ func runApp(ctx context.Context, config *configs.Config) error { // entities pastelClient := pastel.NewClient(config.Pastel, config.Pastel.BurnAddress()) + + if config.PassPhrase == "" { + return errors.New("passphrase is empty, please provide passphrase in config file") + } + // Try to get PastelID from cnode API MasterNodeStatus extKey, err := mixins.GetPastelIDfromMNConfig(ctx, pastelClient, config.PastelID) if err != nil { return fmt.Errorf("get pastelID from mn config: %w", err) } - config.PastelID = extKey + config.OverridePastelIDAndPass(extKey, config.PassPhrase) + + // Validate PastelID and passphrase + if !mixins.ValidateUser(ctx, pastelClient, config.PastelID, config.PassPhrase) { + return errors.New("invalid pastelID or passphrase") + } secInfo := &alts.SecInfo{ PastelID: config.PastelID, @@ -209,15 +219,6 @@ func runApp(ctx context.Context, config *configs.Config) error { return errors.Errorf("could not create p2p service, %w", err) } - // Because of rqlite failures, we're going to disable metadb for now, this consequently disables user data processing until we - // either fix rqlite or develop a workaround. - // NB: Removed protobuf and grpc comms files as well to prevent malicious behavior. - - // new metadb service - // config.MetaDB.SetWorkDir(config.WorkDir) - // metadb := metadb.New(config.MetaDB, config.Node.PastelID, pastelClient) - // database := database.NewDatabaseOps(metadb, config.UserDB) - rqAddr := fmt.Sprint(config.RaptorQ.Host, ":", config.RaptorQ.Port) // raptorq client config.NftRegister.RaptorQServiceAddress = rqAddr diff --git a/supernode/configs/config.go b/supernode/configs/config.go index 1bba763cb..c659d6b55 100644 --- a/supernode/configs/config.go +++ b/supernode/configs/config.go @@ -92,3 +92,26 @@ func New() *Config { DebugService: debug.NewConfig(), } } + +// OverridePastelIDAndPass overrides pastel id and pass phrase for all components +func (config *Config) OverridePastelIDAndPass(id, pass string) { + // Override pastel id + config.PastelID = id + config.CascadeRegister.PastelID = id + config.CollectionRegister.PastelID = id + config.NftRegister.PastelID = id + config.SenseRegister.PastelID = id + config.NftDownload.PastelID = id + config.StorageChallenge.PastelID = id + config.SelfHealingChallenge.PastelID = id + + // Override pass phrase + config.PassPhrase = pass + config.CascadeRegister.PassPhrase = pass + config.CollectionRegister.PassPhrase = pass + config.NftRegister.PassPhrase = pass + config.SenseRegister.PassPhrase = pass + config.NftDownload.PassPhrase = pass + config.StorageChallenge.PassPhrase = pass + config.SelfHealingChallenge.PassPhrase = pass +} diff --git a/testing/bulk-reg-nft/main.go b/testing/bulk-reg-nft/main.go index 0278d61c9..3b4a8cf9f 100644 --- a/testing/bulk-reg-nft/main.go +++ b/testing/bulk-reg-nft/main.go @@ -23,9 +23,11 @@ import ( ) const ( - initialDelay = 1 * time.Second - maxRetries = 5 - timeoutAfter = 1000 + initialDelay = 1 * time.Second + maxRetries = 5 + timeoutAfter = 1000 + pastelID = "jXZMSxS5w9UakpVMAs2vihcCVQ4fBrPsSriXmNqTq2nvK4awXvaP9hZJYL1eJ4o9y3jpvoGghVUQyvsU7Q64Jp" + spendableAddress = "tPfpGZd8QG6A7mQJRKVHs9cDRrQUUaeeiQP" ) type result struct { @@ -268,7 +270,7 @@ func main() { req := payload{ CreatorName: "Jawad", - CreatorPastelid: "jXa6QiopivJLer8G65QsxwQmGELi1w6mbNXvrrYTvsddVE5BT57LtNCZ2SCmWStvLwWWTkuAFPsRREytgG62YX", + CreatorPastelid: pastelID, CreatorWebsiteUrl: "www.testnft.net", Description: "test-" + uploadImageRes.ImageID, ImageId: uploadImageRes.ImageID, @@ -277,7 +279,7 @@ func main() { MaximumFee: 5000, Name: fileName, SeriesName: "Test Series", - SpendableAddress: "tPoVwtTmLvJTV5XCaFqUM6cobZkbu4Uyg9J", + SpendableAddress: spendableAddress, ThumbnailCoordinate: ThumbnailCoordinate{ BottomRightX: 640, BottomRightY: 480, @@ -288,13 +290,13 @@ func main() { MakePubliclyAccessible: true, } - logger.Printf("payload for image-id:%s, request:%d, payload:%s", uploadImageRes.ImageID, count, req) + logger.Printf("payload for image-id:%s, request:%d, payload:%v", uploadImageRes.ImageID, count, req) taskID, err := doNFTRequest(req) if err != nil { - logger.Printf("Request to sense registration failed:%v\n", err) + logger.Printf("Request to nft registration failed:%v\n", err) } - logger.Printf("sense task initiated:%s, request-count:%d\n", taskID, count) + logger.Printf("nft task initiated:%s, request-count:%d\n", taskID, count) taskIDs[taskID] = startReq count++ @@ -314,7 +316,7 @@ func main() { logger.Printf("Request to task state has been failed:%v\n", err) } - results = appendResults(mu, results, result{ + results = appendResults(&mu, results, result{ ID: fmt.Sprintf("request%d", count), Elapsed: time.Since(startReq), Error: err, @@ -348,7 +350,7 @@ func main() { logger.Printf("Total failures: %d\n", failures) } -func appendResults(mu sync.Mutex, results []result, result result) (res []result) { +func appendResults(mu *sync.Mutex, results []result, result result) (res []result) { mu.Lock() defer mu.Unlock() diff --git a/walletnode/services/common/mesh_handler.go b/walletnode/services/common/mesh_handler.go index 8c9a3a9ce..e78709aff 100644 --- a/walletnode/services/common/mesh_handler.go +++ b/walletnode/services/common/mesh_handler.go @@ -177,9 +177,11 @@ func (m *MeshHandler) findNValidTopSuperNodes(ctx context.Context, n int, skipNo } if len(candidateNodes) < n { - err := errors.New("not enough candidate nodes found with required parameters") + if err == nil { + err = errors.New("not enough candidate nodes found with required parameters") + } log.WithContext(ctx).WithField("count", len(candidateNodes)).WithError(err) - return nil, err + return nil, fmt.Errorf("unable to find enough Supernodes: required: %d - found: %d - err: %w", n, len(candidateNodes), err) } if len(sortKey) > 0 { @@ -236,7 +238,7 @@ func (m *MeshHandler) GetCandidateNodes(ctx context.Context, candidatesNodes Sup } if len(WNTopNodesList) < n { - return nil, errors.New("failed to get required data from all candidate nodes") + return WNTopNodesList, errors.New("failed to get required data from enough candidate nodes") } if m.requireSNAgreementOnMNTopList { @@ -251,7 +253,7 @@ func (m *MeshHandler) GetCandidateNodes(ctx context.Context, candidatesNodes Sup } if len(WNTopNodesList) < n { - return nil, errors.New("failed to get enough nodes with matching top 10 list") + return WNTopNodesList, errors.New("failed to get enough nodes with matching top 10 list") } if m.checkDDDatabaseHashes { @@ -261,7 +263,7 @@ func (m *MeshHandler) GetCandidateNodes(ctx context.Context, candidatesNodes Sup } if len(WNTopNodesList) < n { - return nil, errors.New("failed to get enough nodes with matching fingerprints database hash") + return WNTopNodesList, errors.New("failed to get enough nodes with matching fingerprints database hash") } WNTopNodesList, err = m.filterDDServerRequestsInWaitingQueue(ctx, WNTopNodesList, dataMap) @@ -269,6 +271,10 @@ func (m *MeshHandler) GetCandidateNodes(ctx context.Context, candidatesNodes Sup return nil, fmt.Errorf("filter by dd-service stats: %w", err) } + if len(WNTopNodesList) < n { + return WNTopNodesList, errors.New("failed to get required number of nodes with available dd-service") + } + } return WNTopNodesList, nil