// gbt.go package gbt /* #cgo LDFLAGS: -lzmq #include void set_max_msg_size(void *ctx, int size) { zmq_ctx_set(ctx, ZMQ_MAXMSGSIZE, size); } */ import "C" import ( "encoding/json" "fmt" "log" "io/ioutil" "pool/internal/db" "sync/atomic" //"pool/internal/cache" "pool/internal/gbt/alph" "pool/internal/gbt/alph/http" "pool/internal/gbt/coin" "pool/internal/gbt/dgb" "pool/internal/gbt/enx" "pool/internal/gbt/grs" "pool/internal/gbt/mona" "pool/internal/gbt/nexa" "pool/internal/utility" "os" "os/signal" "syscall" "time" "github.com/btcsuite/btcd/rpcclient" kaspad "github.com/kaspanet/kaspad/infrastructure/network/rpcclient" "github.com/redis/go-redis/v9" "go.uber.org/zap" ) var logg *zap.Logger var GbtCtx coin.GbtContext func InitConfig(config *coin.GbtConfig) { data, err := ioutil.ReadFile("gbt.conf") if err != nil { panic(err.Error()) } if err = json.Unmarshal(data, &config); err != nil { panic(err.Error()) } } func InitClient(gbt *coin.GbtContext) error { switch gbt.Coin { case "alph": // alph初始化逻辑 host := gbt.Config.Rpc.Host port := gbt.Config.Rpc.Port apiHost := gbt.Config.Rpc.ApiHost apiPort := gbt.Config.Rpc.ApiPort apiKey := gbt.Config.Rpc.ApiKey client, err := alph.NewAlphPool(host, port) apiClient := http.NewHttpClient(apiHost, apiPort, apiKey) if err != nil { logg.Info("[gbt]", zap.String("rpcclient new ", err.Error())) return err } gbt.ClientAlph = client gbt.ClientAlphApi = apiClient // blockCount := apiClient.GetBlockCount() return nil case "enx": host := gbt.Config.Rpc.Host port := gbt.Config.Rpc.Port client, err := kaspad.NewRPCClient(host + ":" + port) if err != nil { logg.Info("[gbt]", zap.String("rpcclient new ", err.Error())) return err } gbt.ClientEnx = client dagInfoMsg, err := client.GetBlockDAGInfo() if err != nil { logg.Info("[gbt]", zap.String("GetBlockDAGInfo ", err.Error())) return err } blockCount := dagInfoMsg.VirtualDAAScore logg.Info("[gbt]", zap.Int64("Block count ", int64(blockCount))) return nil default: var config rpcclient.ConnConfig if gbt.Config.Rpc.Type == "testnet" { config.Host = gbt.Config.Rpc.Testnet } else { config.Host = gbt.Config.Rpc.Host } config.User = gbt.Config.Rpc.User config.Pass = gbt.Config.Rpc.Pass config.HTTPPostMode = true config.DisableTLS = true client, err := rpcclient.New(&config, nil) if err != nil { logg.Info("[gbt]", zap.String("rpcclient new ", err.Error())) return err } gbt.Client = client blockCount, err := client.GetBlockCount() if err != nil { logg.Info("[gbt]", zap.String("GetBlockCount ", err.Error())) return err } logg.Info("[gbt]", zap.Int64("Block count ", blockCount)) return nil } } /*func GbtLivingHandler(gbt *coin.GbtContext) { timer := time.NewTimer(time.Duration(600) * time.Second) for { select { case aliving := <-gbt.AlivingChan: if !aliving { timer.Stop() //log.Println("gbt aliving", aliving) return } else { timer.Reset(time.Duration(600) * time.Second) } case <-time.After(time.Duration(600) * time.Second): gbt.ExitGbtChan <- true return } } }*/ func GbtLivingHandler(gbt *coin.GbtContext) { var to_cnt int = 0 for { flagAliving := atomic.LoadInt32(&(gbt.FlagAliving)) flagExit := atomic.LoadInt32(&(gbt.FlagAlivingExit)) if flagExit == 1 { logg.Error("[server]", zap.String("GbtLivingHandler exited", "exit")) break } if flagAliving == 0 { //if to_cnt > 240 { if to_cnt > gbt.Config.Rpc.Timeout*3/1000 { logg.Error("[server]", zap.String("GbtLivingHandler exited", "timer expired")) cmd := "killall gbt_" + gbt.Coin + " &" utility.ExecShellCmd(cmd) gbt.ExitGbtChan <- true break } to_cnt++ } else { to_cnt = 0 atomic.StoreInt32(&(gbt.FlagAliving), 0) } time.Sleep(time.Second) } } type coinobj struct { Coin string Init func(GbtCtx *coin.GbtContext, DbCtx *db.DbContext) Start func() Stop func() } var coinobjs = []coinobj{ {Coin: "nexa", Init: nexa.Init, Start: nexa.Start, Stop: nexa.Stop}, {Coin: "grs", Init: grs.Init, Start: grs.Start, Stop: grs.Stop}, {Coin: "mona", Init: mona.Init, Start: mona.Start, Stop: mona.Stop}, {Coin: "dgbo", Init: dgb.Init, Start: dgb.Start, Stop: dgb.Stop}, {Coin: "dgbq", Init: dgb.Init, Start: dgb.Start, Stop: dgb.Stop}, {Coin: "dgbs", Init: dgb.Init, Start: dgb.Start, Stop: dgb.Stop}, {Coin: "alph", Init: alph.Init, Start: alph.Start, Stop: alph.Stop}, {Coin: "enx", Init: enx.Init, Start: enx.Start, Stop: enx.Stop}, } func register_signal(dbctx *db.DbContext) { signal_ch := make(chan os.Signal, 1) signal.Notify(signal_ch, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) go signal_handle(signal_ch, dbctx) } func signal_handle(signal_ch chan os.Signal, dbctx *db.DbContext) { for s := range signal_ch { switch s { case syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT: log.Println("stop!") dbctx.AppExit <- true default: //fmt.Println("other signal", s) } } } /*func LoadCache(gbt *coin.GbtContext) { val := cache.LoadPoolCache(gbt.RedisClient, gbt.Coin, "blocks") if val != nil { if intVal, ok := val.(int64); ok { gbt.Blocks = intVal } } val_f := cache.LoadPoolCache(gbt.RedisClient, gbt.Coin, "rewards") if val_f != nil { if fVal, ok := val_f.(float64); ok { gbt.Reward = fVal } } val_f = cache.LoadPoolCache(gbt.RedisClient, gbt.Coin, "fee") if val_f != nil { if fVal, ok := val_f.(float64); ok { gbt.Fee = fVal } } }*/ func Start(Coin string, DbCtx *db.DbContext) { /*zmqctx := C.zmq_ctx_new() defer C.zmq_ctx_term(zmqctx) C.set_max_msg_size(zmqctx, 1024*1024*8)*/ GbtCtx.DbCtx = DbCtx GbtCtx.Coin = Coin atomic.StoreInt32(&(GbtCtx.FlagAliving), 0) atomic.StoreInt32(&(GbtCtx.FlagAlivingExit), 0) InitConfig(&GbtCtx.Config) l, lr, err := utility.InitLogg(&(GbtCtx.Config.Zaplog), &(GbtCtx.Config.Logrotae), Coin, "gbt") logg = l //defer logg.Sync() GbtCtx.Log = l GbtCtx.LogR = lr GbtCtx.RedisClient = redis.NewClient(&redis.Options{ Addr: GbtCtx.Config.Redis.Addr, Password: GbtCtx.Config.Redis.Password, DB: GbtCtx.Config.Redis.DB, }) register_signal(DbCtx) GbtCtx.PubCh = utility.InitZmqPub(GbtCtx.Config.Zmq.Pub) GbtCtx.SubCh = utility.InitZmqSub(GbtCtx.Config.Zmq.Sub, "blk"+Coin) //GbtCtx.PushCh = utility.InitZmqPush(GbtCtx.Config.Profit.Push) for { err = InitClient(&GbtCtx) if err != nil { logg.Error("[gbt]", zap.String("InitClient", err.Error())) time.Sleep(time.Duration(5) * time.Second) continue } break } // if len(GbtCtx.Config.Rpc.ZmqSub) > 0 { // GbtCtx.NodeSubCh = utility.InitZmqSub(GbtCtx.Config.Rpc.ZmqSub, utility.BITCOIND_ZMQ_HASHBLOCK) // } GbtCtx.Started = true GbtCtx.ExitGbtChan = make(chan bool, 256) //GbtCtx.AlivingChan = make(chan bool, 256) GbtCtx.MinerAddrs = db.GetAddressFromTable(DbCtx) // GbtCtx.MinerAddrs = make([]string, 4) // GbtCtx.MinerAddrs[0] = "1EjmgB5GzbvVpu63a3GxLPjk4DNedhpjNZvVz5oCMpHg5" // GbtCtx.MinerAddrs[1] = "1BHkVwr7VNW2ViqphAR2wy3QdmAm29jYaTVt4w62kH9V1" // GbtCtx.MinerAddrs[2] = "15aeh8ugDpDjWRWhVHeLhyz3KTKSqKaoydTdMFxjD99BJ" // GbtCtx.MinerAddrs[3] = "17sEVHyyfHiwFXDH3onX9MxsbP6kh2B8hrtPd7mk3Qa6r" // GbtCtx.MinerAddrIndex = 0 //LoadCache(&GbtCtx) for _, coinobj := range coinobjs { if coinobj.Coin == Coin { coinobj.Init(&GbtCtx, DbCtx) go coinobj.Start() break } } go GbtLivingHandler(&GbtCtx) <-DbCtx.AppExit } func Stop(Coin string) { fmt.Println("gbt退出了") GbtCtx.Started = false GbtCtx.ExitGbtChan <- true //GbtCtx.AlivingChan <- false atomic.StoreInt32(&(GbtCtx.FlagAlivingExit), 1) for _, coinobj := range coinobjs { if coinobj.Coin == Coin { coinobj.Stop() break } } //time.Sleep(1 * time.Second) defer close(GbtCtx.ExitGbtChan) //defer close(GbtCtx.AlivingChan) if GbtCtx.NodeSubCh != nil { defer GbtCtx.NodeSubCh.Destroy() } if GbtCtx.PubCh != nil { defer GbtCtx.PubCh.Destroy() } if GbtCtx.SubCh != nil { defer GbtCtx.SubCh.Destroy() } /*if GbtCtx.PushCh != nil { defer GbtCtx.PushCh.Destroy() }*/ defer GbtCtx.RedisClient.Close() defer logg.Sync() }