From 4e4028523f9fbe25c739b28f3403e05bdbedc023 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 1 Feb 2024 18:42:49 +0530 Subject: [PATCH] provide central init function, global config, global container --- zchain/init.go | 231 +++++++++++++++++++++++++++++++++++++++++ zcncore/init.go | 16 +++ zcncore/wallet_base.go | 14 +-- 3 files changed, 251 insertions(+), 10 deletions(-) create mode 100644 zchain/init.go create mode 100644 zcncore/init.go diff --git a/zchain/init.go b/zchain/init.go new file mode 100644 index 000000000..eb1edb4f6 --- /dev/null +++ b/zchain/init.go @@ -0,0 +1,231 @@ +package zchain + +import ( + "context" + "encoding/json" + "errors" + "math" + "net/http" + "sync" + "time" + + "github.com/0chain/gosdk/core/logger" + "github.com/0chain/gosdk/core/node" + "github.com/0chain/gosdk/core/util" + "go.uber.org/zap" +) + +type ChainConfig struct { + ChainID string + BlockWorker string + Miners []string + Sharders []string + SignatureScheme string + MinSubmit int + MinConfirmation int + ConfirmationChainLength int + EthNode string + SharderConsensous int + MaxTxnQuery int + QuerySleepTime int +} + +// Maintains SDK configuration. +// Initialized through [InitZChain] function. +type Config struct { + chain *ChainConfig + logLvl int +} + +func (c *Config) getMinMinersSubmit() int { + return util.MaxInt(1, int(math.Ceil(float64(c.chain.MinSubmit) * float64(len(c.chain.Miners)) / 100))) +} + +// Container to hold global data. +// Initialized through [InitZChain] function. +type GlobalContainer struct { + stableMiners []string + sharders *node.NodeHolder + config *Config + + mguard sync.RWMutex +} + +func (gc *GlobalContainer) GetStableMiners() []string { + gc.mguard.RLock() + defer gc.mguard.Unlock() + return gc.stableMiners +} + +func (gc *GlobalContainer) ResetStableMiners() { + gc.mguard.Lock() + defer gc.mguard.Unlock() + gc.stableMiners = util.GetRandom(gc.config.chain.Miners, gc.config.getMinMinersSubmit()) +} + +var ( + Gcontainer *GlobalContainer + logging logger.Logger +) + +type SignScheme string + +const ( + ED25519 SignScheme = "ed25519" + BLS0CHAIN SignScheme = "bls0chain" +) + +type OptionKey int + +const ( + ChainId OptionKey = iota + MinSubmit + MinConfirmation + ConfirmationChainLength + EthNode + SharderConsensous + + LoggingLevel +) + +// default options value +const ( + defaultMinSubmit = int(10) + defaultMinConfirmation = int(10) + defaultConfirmationChainLength = int(3) + defaultMaxTxnQuery = int(5) + defaultQuerySleepTime = int(5) + defaultSharderConsensous = int(3) + defaultLogLevel = logger.DEBUG +) + +func init() { + logging.Init(logger.DEBUG, "0chain-config") +} + +func InitZChain(ctx context.Context, blockWorker string, signscheme SignScheme, options map[OptionKey]interface{}) error { + // get miners, sharders + miners, sharders, err := getNetworkDetails(ctx, blockWorker) + if err != nil { + logging.Error("Failed to get network details ", zap.Error(err)) + return err + } + + // init config + config := &Config{ + chain: &ChainConfig{ + BlockWorker: blockWorker, + SignatureScheme: string(signscheme), + Miners: miners, + Sharders: sharders, + MinSubmit: defaultMinSubmit, + MinConfirmation: defaultMinConfirmation, + ConfirmationChainLength: defaultConfirmationChainLength, + MaxTxnQuery: defaultMaxTxnQuery, + QuerySleepTime: defaultQuerySleepTime, + SharderConsensous: util.MinInt(defaultSharderConsensous, len(sharders)), + }, + logLvl: defaultLogLevel, + } + + // override default values + for optionKey, optionValue := range options { + switch optionKey { + case ChainId: + chainId, isTypeString := optionValue.(string) + if !isTypeString { + return errors.New("option ChainId is not of string type") + } + config.chain.ChainID = chainId + case MinSubmit: + minSubmit, isTypeInt := optionValue.(int) + if !isTypeInt { + return errors.New("option MinSubmit is not of int type") + } + config.chain.MinSubmit = minSubmit + case MinConfirmation: + minConfirmation, isTypeInt := optionValue.(int) + if !isTypeInt { + return errors.New("option MinConfirmation is not of int type") + } + config.chain.MinConfirmation = minConfirmation + case ConfirmationChainLength: + confirmationChainLength, isTypeInt := optionValue.(int) + if !isTypeInt { + return errors.New("option ConfirmationChainLength is not of int type") + } + config.chain.ConfirmationChainLength = confirmationChainLength + case EthNode: + ethNode, isTypeString := optionValue.(string) + if !isTypeString { + return errors.New("option EthNode is not of string type") + } + config.chain.EthNode = ethNode + case SharderConsensous: + sharderConsensous, isTypeInt := optionValue.(int) + if !isTypeInt { + return errors.New("option SharderConsensous is not of int type") + } + config.chain.SharderConsensous = sharderConsensous + case LoggingLevel: + loggingLevel, isTypeInt := optionValue.(int) + if !isTypeInt { + return errors.New("option LoggingLevel is not of int type") + } + logging.SetLevel(loggingLevel) + } + } + + // init GlobalContainer + Gcontainer = &GlobalContainer { + stableMiners: util.GetRandom(miners, config.getMinMinersSubmit()), + sharders: node.NewHolder(config.chain.Sharders, config.chain.SharderConsensous), + config: config, + } + + // update miners, sharders periodically + go func() { + ticker := time.NewTicker(time.Duration(1) * time.Hour) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + + } + } + }() + + // init modules + node.InitCache(Gcontainer.sharders) + return nil +} + +func getNetworkDetails(ctx context.Context, blockWorker string) ([]string, []string, error) { + networkUrl := blockWorker + "/network" + networkGetCtx, networkGetCancelCtx := context.WithTimeoutCause(ctx, 60 * time.Second, errors.New("timeout connecting network: " + networkUrl)) + defer networkGetCancelCtx() + req, err := util.NewHTTPGetRequestContext(networkGetCtx, networkUrl) + if err != nil { + return nil, nil, errors.New("Unable to create new http request with error: " + err.Error()) + } + res, err := req.Get() + if err != nil { + return nil, nil, errors.New("Unable to get http request with error: " + err.Error()) + } + if res.StatusCode != http.StatusOK { + return nil, nil, errors.New("Unable to get http request with status Ok: " + res.Status) + } + type responseBody struct { + Miners []string `json:"miners"` + Sharders []string `json:"sharders"` + } + var respBody responseBody + err = json.Unmarshal([]byte(res.Body), &respBody) + if err != nil { + return nil, nil, errors.New("Error unmarshaling response :" + res.Body) + } + return respBody.Miners, respBody.Sharders, nil + +} \ No newline at end of file diff --git a/zcncore/init.go b/zcncore/init.go new file mode 100644 index 000000000..081c0779e --- /dev/null +++ b/zcncore/init.go @@ -0,0 +1,16 @@ +package zcncore + +import ( + "sync" + + "github.com/0chain/gosdk/core/logger" +) + +// Singleton +// TODO: Remove these variable and Use zchain.Gcontainer +var ( + _config localConfig + logging logger.Logger + stableMiners []string + mGuard sync.Mutex +) \ No newline at end of file diff --git a/zcncore/wallet_base.go b/zcncore/wallet_base.go index afb85aa98..aa6423a5e 100644 --- a/zcncore/wallet_base.go +++ b/zcncore/wallet_base.go @@ -132,7 +132,6 @@ const ( ) var defaultLogLevel = logger.DEBUG -var logging logger.Logger func GetLogger() *logger.Logger { return &logging @@ -222,11 +221,6 @@ type AuthCallback interface { OnSetupComplete(status int, err string) } -// Singleton -var _config localConfig -var miners []string -var mGuard sync.Mutex - func init() { logging.Init(defaultLogLevel, "0chain-core-sdk") } @@ -234,16 +228,16 @@ func init() { func GetStableMiners() []string { mGuard.Lock() defer mGuard.Unlock() - if len(miners) == 0 { - miners = util.GetRandom(_config.chain.Miners, getMinMinersSubmit()) + if len(stableMiners) == 0 { + stableMiners = util.GetRandom(_config.chain.Miners, getMinMinersSubmit()) } - return miners + return stableMiners } func ResetStableMiners() { mGuard.Lock() defer mGuard.Unlock() - miners = util.GetRandom(_config.chain.Miners, getMinMinersSubmit()) + stableMiners = util.GetRandom(_config.chain.Miners, getMinMinersSubmit()) } func checkSdkInit() error {