From 3003de35ba3cc4268cb44ab2f05648e2b886999e Mon Sep 17 00:00:00 2001 From: dephizee Date: Fri, 18 Oct 2024 09:07:55 +0100 Subject: [PATCH] feat: ping liveliness --- configs/config.go | 132 +++++++++++++++----------------- go.mod | 3 +- pkg/node/node.go | 191 ++++++++++++++++++++++------------------------ pkg/node/ping.go | 104 +++++++++++++++++++++++++ 4 files changed, 258 insertions(+), 172 deletions(-) create mode 100644 pkg/node/ping.go diff --git a/configs/config.go b/configs/config.go index 6e01dee..1cf46f9 100644 --- a/configs/config.go +++ b/configs/config.go @@ -15,15 +15,12 @@ import ( "github.com/spf13/viper" ) - - type IpfsConfig struct { Host string `toml:"ipfs_url"` ProjectId string `toml:"ipfs_username"` ProjectSecret string `toml:"ipfs_password"` } - func copyStructValues(src, dst interface{}) error { srcVal := reflect.ValueOf(src) dstVal := reflect.ValueOf(dst).Elem() @@ -31,7 +28,7 @@ func copyStructValues(src, dst interface{}) error { if srcVal.Kind() != reflect.Struct || dstVal.Kind() != reflect.Struct { return fmt.Errorf("input types must be structs") } - + for i := 0; i < srcVal.NumField(); i++ { fieldName := srcVal.Type().Field(i).Name srcField := srcVal.Field(i) @@ -44,21 +41,21 @@ func copyStructValues(src, dst interface{}) error { return nil } + type EthConfig struct { - Name string `toml:"name"` - Http string `toml:"http"` - Wss string `toml:"wss"` - TokenContract string `toml:"token_contract"` - XTokenContract string `toml:"x_token_contract"` - ChainInfoContract string `toml:"chain_info_contract"` - SentryNodeContract string `toml:"sentry_node_contract"` - ValidatorNodeContract string `toml:"validator_node_contract"` - SubnetContract string `toml:"subnet_contract"` - RegistryContract string `toml:"registry_contract"` + Name string `toml:"name"` + Http string `toml:"http"` + Wss string `toml:"wss"` + TokenContract string `toml:"token_contract"` + XTokenContract string `toml:"x_token_contract"` + ChainInfoContract string `toml:"chain_info_contract"` + SentryNodeContract string `toml:"sentry_node_contract"` + ValidatorNodeContract string `toml:"validator_node_contract"` + SubnetContract string `toml:"subnet_contract"` + RegistryContract string `toml:"registry_contract"` } type SqlConfig struct { - DbDialect string `toml:"db_dialect"` DbHost string `toml:"db_host"` DbStoragePath string `toml:"db_storage_dir"` @@ -71,10 +68,8 @@ type SqlConfig struct { DbMaxOpenConns int `toml:"db_max_open_conns"` DbMaxIdleConns int `toml:"db_max_idle_conns"` DbMaxConnLifetime int `toml:"db_max_conn_lifetime_seconds"` - } - type ChainId string func (n *ChainId) Bytes() []byte { @@ -91,56 +86,55 @@ func (n *ChainId) Equals(s ChainId) bool { } type MainConfiguration struct { - AddressPrefix string `toml:"network_address_prefix"` + AddressPrefix string `toml:"network_address_prefix"` // StakeContract string `toml:"stake_contract"` - ChainId ChainId `toml:"chain_id"` + ChainId ChainId `toml:"chain_id"` // Token string `toml:"token_address"` // EVMRPCUrl string `toml:"evm_rpc_url"` // deprecated // EVMRPCHttp string `toml:"evm_rpc_http"` // EVMRPCWss string `toml:"evm_rpc_wss"` - ProtocolVersion string `toml:"protocol_version"` - ChannelMessageBufferSize uint `toml:"channel_message_buffer_size"` - Ipfs IpfsConfig `toml:"ipfs"` - LogLevel string `toml:"log_level"` - BootstrapPeers []string `toml:"bootstrap_peers"` - ListenerAdresses []string `toml:"listener_addresses"` - RPCHost string `toml:"rpc_host"` - WSAddress string `toml:"ws_address"` - RestAddress string `toml:"rest_address"` - RPCPort string `toml:"rpc_port"` - RPCHttpPort string `toml:"rpc_http_port"` - Validator bool `toml:"validator"` - BootstrapNode bool `toml:"bootstrap_node"` - DataDir string `toml:"data_dir"` - KeyStoreDir string `toml:"keystore_dir"` - SQLDB SqlConfig `toml:"sql"` - MLBlockchainAPIUrl string `toml:"mlayer_api_url"` - PrivateKey string `toml:"private_key"` - EvmRpcConfig map[string]EthConfig `toml:"evm_rpc"` - QuicHost string `toml:"quic_host"` + ProtocolVersion string `toml:"protocol_version"` + ChannelMessageBufferSize uint `toml:"channel_message_buffer_size"` + Ipfs IpfsConfig `toml:"ipfs"` + LogLevel string `toml:"log_level"` + BootstrapPeers []string `toml:"bootstrap_peers"` + ListenerAdresses []string `toml:"listener_addresses"` + RPCHost string `toml:"rpc_host"` + WSAddress string `toml:"ws_address"` + RestAddress string `toml:"rest_address"` + RPCPort string `toml:"rpc_port"` + RPCHttpPort string `toml:"rpc_http_port"` + Validator bool `toml:"validator"` + BootstrapNode bool `toml:"bootstrap_node"` + DataDir string `toml:"data_dir"` + KeyStoreDir string `toml:"keystore_dir"` + SQLDB SqlConfig `toml:"sql"` + MLBlockchainAPIUrl string `toml:"mlayer_api_url"` + PrivateKey string `toml:"private_key"` + EvmRpcConfig map[string]EthConfig `toml:"evm_rpc"` + QuicHost string `toml:"quic_host"` + PingUrl string `toml:"ping_url"` // PublicKey string - OperatorAddress string - - PrivateKeyEDD []byte - PublicKeyEDD []byte - PublicKeyEDDHex string - PrivateKeySECP []byte - PublicKeySECP []byte + OperatorAddress string + + PrivateKeyEDD []byte + PublicKeyEDD []byte + PublicKeyEDDHex string + PrivateKeySECP []byte + PublicKeySECP []byte PublicKeySECPHex string - OwnerAddress common.Address - NoSync bool - Context *context.Context + OwnerAddress common.Address + NoSync bool + Context *context.Context SyncBatchSize uint - TestMode bool - + TestMode bool } type MLChainAPI struct { url string `mapstructure:"ml_api_url"` } - var ( Config MainConfiguration ) @@ -151,8 +145,7 @@ var possiblePaths = []string{ } func initViper() *viper.Viper { - - + v := viper.New() v.AutomaticEnv() v.SetEnvPrefix("ml") @@ -164,7 +157,7 @@ func initViper() *viper.Viper { err := v.ReadInConfig() // Find and read the config file if err != nil { // Handle errors reading the config file - // panic( err) + // panic( err) } v.SetDefault("log_level", "info") v.SetDefault("channel_message_buffer_size", 128) @@ -173,20 +166,21 @@ func initViper() *viper.Viper { v.SetDefault("db_max_conn_lifetime_seconds", 120) return v } + // func init() { // c := LoadMainConfig(true) - -// Config = *c -// } + +// Config = *c +// } func LoadConfig(testnet bool) (*MainConfiguration, error) { var config MainConfiguration if testnet { - config = TestNetConfig + config = TestNetConfig } else { config = MainNetConfig } - + // Try loading the configuration file from the possible paths for _, path := range possiblePaths { if _, err := os.Stat(path); err == nil { @@ -196,14 +190,14 @@ func LoadConfig(testnet bool) (*MainConfiguration, error) { panic(err) //return nil, fmt.Errorf("failed to decode config file %s: %w", path, err) } - fmt.Printf("\nLoaded configuration from: %s",path) + fmt.Printf("\nLoaded configuration from: %s", path) // Override with environment variables // kong.Parse(&config) - + if err = copyStructValues(configData, &config); err != nil { panic(err) } - + } } return &config, nil @@ -216,23 +210,19 @@ func Init(testnet bool) *MainConfiguration { d := make(map[string]interface{}) json.Unmarshal(m, &d) v.MergeConfigMap(d) - if err != nil { // Handle errors reading the config file - panic( err) - } - + if err != nil { // Handle errors reading the config file + panic(err) + } + if err := v.Unmarshal(&c); err != nil { fmt.Printf("Fatal: Couldn't read config: %s \n", err.Error()) } - c.PrivateKey = v.GetString("private_key") // needed to load from environment var if len(v.GetString("private_key")) > 0 { c.PrivateKey = v.GetString("private_key") // needed to load from environment var } - - - if len(v.GetString("data_dir")) > 0 { c.DataDir = v.GetString("data_dir") // needed to load from environment var or flag } diff --git a/go.mod b/go.mod index 3d2ca64..3fbf93e 100755 --- a/go.mod +++ b/go.mod @@ -43,6 +43,7 @@ require ( github.com/charmbracelet/x/input v0.1.0 // indirect github.com/charmbracelet/x/term v0.1.1 // indirect github.com/charmbracelet/x/windows v0.1.0 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-localereader v0.0.1 // indirect @@ -195,7 +196,7 @@ require ( github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/spaolacci/murmur3 v1.1.0 github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect diff --git a/pkg/node/node.go b/pkg/node/node.go index ceab560..18a2617 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -55,42 +55,40 @@ var logger = &log.Logger // var subscribedWsClientIndex = make(map[string]map[*websocket.Conn][]int) // var wsClients = make(map[string][]*websocket.Conn) - var wsClients = entities.NewWsClientLog() func Start(mainCtx *context.Context) { - time.Sleep(1*time.Second) + time.Sleep(1 * time.Second) logger.Println("Starting network...") _, cancel := context.WithCancel(context.Background()) defer cancel() - + cfg, ok := (*mainCtx).Value(constants.ConfigKey).(*configs.MainConfiguration) if !ok { panic(apperror.Internal("Unable to load main config")) } - + connectedSubscribers := make(map[string]map[string][]interface{}) // incomingEventsC := make(chan types.Log) var wg sync.WaitGroup - systemStore := ds.New(mainCtx, string(constants.SystemStore)) - defer systemStore.Close() + systemStore := ds.New(mainCtx, string(constants.SystemStore)) + defer systemStore.Close() ctx := context.WithValue(*mainCtx, constants.SystemStore, systemStore) - - eventCountStore := ds.New(&ctx, string(constants.EventCountStore)) + eventCountStore := ds.New(&ctx, string(constants.EventCountStore)) defer eventCountStore.Close() ctx = context.WithValue(ctx, constants.EventCountStore, eventCountStore) - claimedRewardStore := ds.New(&ctx, string(constants.ClaimedRewardStore)) + claimedRewardStore := ds.New(&ctx, string(constants.ClaimedRewardStore)) defer claimedRewardStore.Close() ctx = context.WithValue(ctx, constants.ClaimedRewardStore, claimedRewardStore) // ctx = context.WithValue(ctx, constants.NewTopicSubscriptionStore, newTopicSubscriptionStore) // ctx = context.WithValue(ctx, constants.UnprocessedClientPayloadStore, unProcessedClientPayloadStore) ctx = context.WithValue(ctx, constants.ConnectedSubscribersMap, connectedSubscribers) - p2pDhtStore := ds.New(&ctx, string(constants.P2PDhtStore)) + p2pDhtStore := ds.New(&ctx, string(constants.P2PDhtStore)) defer p2pDhtStore.Close() ctx = context.WithValue(ctx, constants.P2PDhtStore, p2pDhtStore) @@ -102,12 +100,11 @@ func Start(mainCtx *context.Context) { // systemStore.Set(ctx, lastBlockKey, chain.NetworkInfo.CurrentBlock.Bytes(), true) // } // }() - if err := loadChainInfo(cfg); err != nil { logger.Fatal(err) } - + defer wg.Wait() // wg.Add(1) @@ -156,7 +153,6 @@ func Start(mainCtx *context.Context) { } }() - // load network params wg.Add(1) @@ -168,7 +164,7 @@ func Start(mainCtx *context.Context) { for { if err := loadChainInfo(cfg); err != nil { logger.Error(err) - time.Sleep(10*time.Second) + time.Sleep(10 * time.Second) continue } time.Sleep(30 * time.Second) @@ -193,7 +189,7 @@ func Start(mainCtx *context.Context) { if err != nil { logger.Error(err) } - certResponse, err := certPayload.SendRequestToAddress(cfg.PrivateKeyEDD, addr, p2p.DataRequest ) + certResponse, err := certPayload.SendRequestToAddress(cfg.PrivateKeyEDD, addr, p2p.DataRequest) if err != nil { logger.Error(err) } @@ -204,21 +200,19 @@ func Start(mainCtx *context.Context) { } wg.Add(1) - // start the REST server - go func() { - for { - subscription, ok := <-channelpool.ClientWsSubscriptionChannel - if !ok { - logger.Errorf("Client WS subscription channel closed") - continue - } - - wsClients.RegisterClient(subscription) + // start the REST server + go func() { + for { + subscription, ok := <-channelpool.ClientWsSubscriptionChannel + if !ok { + logger.Errorf("Client WS subscription channel closed") + continue } - - }() - + wsClients.RegisterClient(subscription) + } + + }() wg.Add(1) go func() { @@ -229,14 +223,13 @@ func Start(mainCtx *context.Context) { // errc <- fmt.Errorf("P2P error: %g", err) // } // }() - + go p2p.ProcessEventsReceivedFromOtherNodes(entities.AuthModel, &entities.AuthorizationPubSub, &ctx, service.HandleNewPubSubAuthEvent) go p2p.ProcessEventsReceivedFromOtherNodes(entities.TopicModel, &entities.TopicPubSub, &ctx, service.HandleNewPubSubTopicEvent) go p2p.ProcessEventsReceivedFromOtherNodes(entities.SubnetModel, &entities.SubnetPubSub, &ctx, service.HandleNewPubSubSubnetEvent) go p2p.ProcessEventsReceivedFromOtherNodes(entities.WalletModel, &entities.WalletPubSub, &ctx, service.HandleNewPubSubWalletEvent) go p2p.ProcessEventsReceivedFromOtherNodes(entities.SubscriptionModel, &entities.SubscriptionPubSub, &ctx, service.HandleNewPubSubSubscriptionEvent) go p2p.ProcessEventsReceivedFromOtherNodes(entities.MessageModel, &entities.MessagePubSub, &ctx, service.HandleNewPubSubMessageEvent) - p2p.Run(&ctx) // if err != nil { @@ -245,7 +238,6 @@ func Start(mainCtx *context.Context) { // } }() - if cfg.Validator { wg.Add(1) go func() { @@ -261,13 +253,15 @@ func Start(mainCtx *context.Context) { defer wg.Done() ProcessPendingClaims(&ctx) }() - } - - - - - + wg.Add(1) + go func() { + _, cancel := context.WithCancel(context.Background()) + defer cancel() + defer wg.Done() + LivelinessPing(&ctx) + }() + } // wg.Add(1) // go func() { @@ -321,7 +315,7 @@ func Start(mainCtx *context.Context) { defer wg.Done() rpc.Register(rpcServer.NewRpcService(&ctx)) rpc.HandleHTTP() - host := cfg.RPCHost + host := cfg.RPCHost if host == "" { host = "127.0.0.1" } @@ -332,14 +326,13 @@ func Start(mainCtx *context.Context) { defer listener.Close() logger.Debugf("RPC server runing on: %+s", host+":"+cfg.RPCPort) go http.Serve(listener, nil) - time.Sleep(time.Second) + time.Sleep(time.Second) sendHttp := rpcServer.NewHttpService(&ctx) err = sendHttp.Start(cfg.RPCPort) if err != nil { logger.Fatal("Http error: ", err) } }() - wg.Add(1) // starting quick server @@ -351,11 +344,11 @@ func Start(mainCtx *context.Context) { return } // get the certificate from store - + cd := crypto.GetOrGenerateCert(&ctx) keyByte, _ := hex.DecodeString(cd.Key) certByte, _ := hex.DecodeString(cd.Cert) - tlsConfig, err := crypto.GenerateTLSConfig(keyByte, certByte) + tlsConfig, err := crypto.GenerateTLSConfig(keyByte, certByte) if err != nil { logger.Fatal("QuicTLSError", err) } @@ -364,7 +357,6 @@ func Start(mainCtx *context.Context) { logger.Fatal(err) } defer listener.Close() - for { connection, err := listener.Accept(ctx) @@ -401,78 +393,77 @@ func Start(mainCtx *context.Context) { logger.Debugf("Starting REST api on: %s", cfg.RestAddress) err := router.Run(cfg.RestAddress) logger.Fatal(err) - + }() } } func loadChainInfo(cfg *configs.MainConfiguration) error { - + info, err := chain.Provider(cfg.ChainId).GetChainInfo() + if err != nil { + return fmt.Errorf("pkg/node/NodeInfo/GetChainInfo: %v", err) + } + if chain.NetworkInfo.ActiveValidatorLicenseCount != info.ValidatorActiveLicenseCount.Uint64() { + // if chain.NetworkInfo.Validators == nil { + chain.NetworkInfo.Validators = map[string]string{} + // } + page := big.NewInt(1) + perPage := big.NewInt(100) + for { + + validators, err := chain.Provider(cfg.ChainId).GetValidatorNodeOperators(page, perPage) if err != nil { - return fmt.Errorf("pkg/node/NodeInfo/GetChainInfo: %v", err) - } - if (chain.NetworkInfo.ActiveValidatorLicenseCount != info.ValidatorActiveLicenseCount.Uint64()) { - // if chain.NetworkInfo.Validators == nil { - chain.NetworkInfo.Validators = map[string]string{} - // } - page := big.NewInt(1) - perPage := big.NewInt(100) - for { - - validators, err := chain.Provider(cfg.ChainId).GetValidatorNodeOperators(page, perPage ) - if err != nil { - logger.Errorf("pkg/node/NodeInfo/GetValidatorNodeOperators: %v", err) - time.Sleep(10 * time.Second) - continue - } - - for _, val := range validators { - pubKey := hex.EncodeToString(val.PublicKey) - // chain.NetworkInfo.Validators[pubKey] = val.LicenseOwner - chain.NetworkInfo.Validators[val.LicenseOwner] = "true" - chain.NetworkInfo.Validators[fmt.Sprintf("secp/%s/edd", pubKey)] = hex.EncodeToString(val.EddKey[:]) - chain.NetworkInfo.Validators[fmt.Sprintf("secp/%s/addr", pubKey)] = val.LicenseOwner - chain.NetworkInfo.Validators[fmt.Sprintf("edd/%s/secp", hex.EncodeToString(val.EddKey[:]))] = pubKey - chain.NetworkInfo.Validators[fmt.Sprintf("edd/%s/addr", hex.EncodeToString(val.EddKey[:]))] = val.LicenseOwner - } - if len(validators) == 0 || big.NewInt(int64(len(validators))).Cmp(perPage) == -1 { - break - } - page = new(big.Int).Add(page, big.NewInt(1)) - } + logger.Errorf("pkg/node/NodeInfo/GetValidatorNodeOperators: %v", err) + time.Sleep(10 * time.Second) + continue } - ownerAddress := chain.NetworkInfo.Validators[fmt.Sprintf("secp/%s/addr", cfg.PublicKeySECPHex)] - if len(ownerAddress) > 0 { - cfg.Validator = true - cfg.OwnerAddress = common.HexToAddress(ownerAddress) - } else { - address, err := chain.Provider(cfg.ChainId).GetSentryLicenseOwnerAddress(cfg.PublicKeySECP) - if err != nil { - logger.Fatal(err) - } - cfg.OwnerAddress = common.BytesToAddress(address) + + for _, val := range validators { + pubKey := hex.EncodeToString(val.PublicKey) + // chain.NetworkInfo.Validators[pubKey] = val.LicenseOwner + chain.NetworkInfo.Validators[val.LicenseOwner] = "true" + chain.NetworkInfo.Validators[fmt.Sprintf("secp/%s/edd", pubKey)] = hex.EncodeToString(val.EddKey[:]) + chain.NetworkInfo.Validators[fmt.Sprintf("secp/%s/addr", pubKey)] = val.LicenseOwner + chain.NetworkInfo.Validators[fmt.Sprintf("edd/%s/secp", hex.EncodeToString(val.EddKey[:]))] = pubKey + chain.NetworkInfo.Validators[fmt.Sprintf("edd/%s/addr", hex.EncodeToString(val.EddKey[:]))] = val.LicenseOwner } - if cfg.NoSync { - chain.NetworkInfo.Synced = true + if len(validators) == 0 || big.NewInt(int64(len(validators))).Cmp(perPage) == -1 { + break } - chain.NetworkInfo.StartBlock = info.StartBlock - chain.NetworkInfo.StartTime = info.StartTime - chain.NetworkInfo.CurrentCycle = info.CurrentCycle - chain.NetworkInfo.CurrentBlock = info.CurrentBlock - // chain.NetworkInfo.CurrentEpoch = info.CurrentEpoch - chain.NetworkInfo.ActiveValidatorLicenseCount = info.ValidatorActiveLicenseCount.Uint64() - chain.NetworkInfo.ActiveSentryLicenseCount = info.SentryActiveLicenseCount.Uint64() - - return err + page = new(big.Int).Add(page, big.NewInt(1)) + } + } + ownerAddress := chain.NetworkInfo.Validators[fmt.Sprintf("secp/%s/addr", cfg.PublicKeySECPHex)] + if len(ownerAddress) > 0 { + cfg.Validator = true + cfg.OwnerAddress = common.HexToAddress(ownerAddress) + } else { + address, err := chain.Provider(cfg.ChainId).GetSentryLicenseOwnerAddress(cfg.PublicKeySECP) + if err != nil { + logger.Fatal(err) + } + cfg.OwnerAddress = common.BytesToAddress(address) + } + if cfg.NoSync { + chain.NetworkInfo.Synced = true + } + chain.NetworkInfo.StartBlock = info.StartBlock + chain.NetworkInfo.StartTime = info.StartTime + chain.NetworkInfo.CurrentCycle = info.CurrentCycle + chain.NetworkInfo.CurrentBlock = info.CurrentBlock + // chain.NetworkInfo.CurrentEpoch = info.CurrentEpoch + chain.NetworkInfo.ActiveValidatorLicenseCount = info.ValidatorActiveLicenseCount.Uint64() + chain.NetworkInfo.ActiveSentryLicenseCount = info.SentryActiveLicenseCount.Uint64() + + return err } - func waitToSync() { - for{ + for { if !chain.NetworkInfo.Synced { time.Sleep(2 * time.Second) } else { break } } -} \ No newline at end of file +} diff --git a/pkg/node/ping.go b/pkg/node/ping.go new file mode 100644 index 0000000..ad11643 --- /dev/null +++ b/pkg/node/ping.go @@ -0,0 +1,104 @@ +package node + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "io/ioutil" + "math/big" + "net/http" + "time" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/mlayerprotocol/go-mlayer/common/constants" + "github.com/mlayerprotocol/go-mlayer/configs" +) + +type Message struct { + Timestamp int64 `json:"timestamp"` + Data string `json:"data"` +} + +type Payload struct { + Signer string `json:"signer"` + Message Message `json:"message"` + Signature string `json:"signature"` +} + +func (msg *Message) EncodeBytes() []byte { + + // strData := ""; + timestamp := big.NewInt(int64(msg.Timestamp)).Bytes() + data := []byte(msg.Data) + + return append(timestamp, data...) +} + +func LivelinessPing(ctx *context.Context) { + ticker := time.NewTicker(2 * time.Minute) + defer ticker.Stop() // Stop the ticker when we're done + + // Infinite loop to keep printing messages + for { + select { + case <-ticker.C: + fmt.Println("This message Before every 30 seconds! ") + body, err := makeHTTPRequest(ctx) + fmt.Printf("This message prints every 30 seconds! %v %v\n", body, err) + } + } +} + +func makeHTTPRequest(ctx *context.Context) (string, error) { + cfg, _ := (*ctx).Value(constants.ConfigKey).(*configs.MainConfiguration) + fmt.Printf("makeHTTPRequest every 30 seconds! cfg.PingUrl: %s cfg.PublicKeySECPHex: %s \n", cfg.PingUrl, cfg.PublicKeySECPHex) + message := Message{ + Timestamp: time.Now().Unix(), + Data: "Hello word", + } + + privateKey, _ := btcec.PrivKeyFromBytes(cfg.PrivateKeySECP) + hash := sha256.Sum256(message.EncodeBytes()) + + // Sign the hashed message using the Schnorr signature scheme + signature, err := schnorr.Sign(privateKey, hash[:]) + if err != nil { + return "", fmt.Errorf("failed to sign message with Schnorr: %v", err) + } + + // Serialize the signature to hex + signatureHex := hex.EncodeToString(signature.Serialize()) + payload := Payload{ + Signer: cfg.PublicKeySECPHex, + Signature: signatureHex, + Message: message, + } + jsonData, err := json.Marshal(payload) + if err != nil { + return "", fmt.Errorf("failed to marshal payload: %v", err) + } + + resp, err := http.Post(cfg.PingUrl, "application/json", bytes.NewBuffer(jsonData)) + if err != nil { + return "", fmt.Errorf("failed to make GET request: %v", err) + } + defer resp.Body.Close() // Close the response body when the function exits + + // Check if the status code is not 200 (OK) + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("received non-200 response code: %d", resp.StatusCode) + } + + // Read the response body + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", fmt.Errorf("failed to read response body: %v", err) + } + + // Return the body as a string + return string(body), nil +}