package blockchain import ( "context" "encoding/hex" "fmt" "ktogame/contractgo/Collect" "ktogame/controller" "ktogame/dbUtil" "ktogame/models" "os" "strings" "time" "github.com/astaxie/beego" "github.com/astaxie/beego/logs" "github.com/ethereum/go-ethereum/accounts/abi" utilAddress "github.com/korthochain/korthochain/pkg/address" "github.com/korthochain/korthochain/pkg/block" pb "github.com/korthochain/korthochain/pkg/server/grpcserver/message" "github.com/korthochain/korthochain/pkg/transaction" "google.golang.org/grpc" ) var ktoClient pb.GreeterClient var ktoRpc = beego.AppConfig.String("miner_node") var currentBlock uint64 var TopsMap map[string]string func init() { kc, err := grpc.Dial(ktoRpc, grpc.WithInsecure(), grpc.WithBlock()) if err != nil { logs.Error(err) os.Exit(1) } ktoClient = pb.NewGreeterClient(kc) utilAddress.SetNetWork("mainnet") tm := make(map[string]string, 0) tm[TOPIC_PARTICIPATE] = COLLECT_PARTICIPATE TopsMap = tm go scanBlock() go confirmClaimedTxs() } func scanBlock() { logs.Info("scanBlock...") var bi models.BlockInfo ok, err := dbUtil.Engine.Id(1).Get(&bi) if err != nil { fmt.Println("获取最新快高错误=", err) return } if !ok { fmt.Println("获取最新快高失败!") return } currentBlock = uint64(bi.BlockNumber) + 1 //currentBlock =62203394 for { time.Sleep(time.Second * 3) res, err := ktoClient.GetMaxBlockHeight(context.Background(), &pb.ReqMaxBlockHeight{}) if err != nil { logs.Error("获取交易block number错误=", err) continue } logs.Info("currentBlock:", currentBlock, "chainblock:", res.MaxHeight) if res.MaxHeight < currentBlock { currentBlock = res.MaxHeight } bl, err := ktoClient.GetBlockByNum(context.Background(), &pb.ReqBlockByNumber{Height: currentBlock}) if err != nil || bl.Code != 0 { logs.Error("获取交易block错误=", err) continue } blc, errs := block.Deserialize(bl.Data) if errs != nil { logs.Error("解析blcock错误=", errs) continue } var ERR error for _, v := range blc.Transactions { if len(v.Input) == 0 { continue } evm, err := transaction.DecodeEvmData(v.Input) if err != nil { logs.Error(err) ERR = err break } if len(evm.Logs) == 0 { continue } for _, l := range evm.Logs { th := l.Topics[0].Hex() method := TopsMap[th] contract := l.Address.String() if contract == COLLECTCONTRACT { if method == COLLECT_PARTICIPATE { var ev EventParticipate abi, err := abi.JSON(strings.NewReader(Collect.CollectMetaData.ABI)) if err != nil { logs.Error(err) ERR = err break } err = abi.UnpackIntoInterface(&ev, method, l.Data) if err != nil { logs.Error(err) ERR = err break } logs.Info("participate data:", ev.Participant.String(), ev.Inviter.String(), v.HashToString(), float64(ev.Amount.Uint64()/controller.Decimals)) //handle user participate err = participate(dbUtil.Engine, ev.Participant.String(), ev.Inviter.String(), v.HashToString(), float64(ev.Amount.Uint64()/controller.Decimals)) if err != nil { logs.Error(err) ERR = err break } } else if method == COLLECT_CLAIMREWARDS { var evt EventClaim abi, err := abi.JSON(strings.NewReader(Collect.CollectMetaData.ABI)) if err != nil { logs.Error(err) ERR = err break } err = abi.UnpackIntoInterface(&evt, method, l.Data) if err != nil { logs.Error(err) ERR = err break } fmt.Printf("claim event data=%+v\n ", evt) err = checkClaim(dbUtil.Engine, evt.User.String(), v.HashToString(), hex.EncodeToString(evt.Signature), float64(evt.Amount.Uint64()/controller.Decimals)) if err != nil { logs.Error(err) ERR = err break } } } } if ERR != nil { logs.Error(err) break } } if ERR != nil { logs.Error("处理错误=", ERR) continue } bi.BlockNumber = int64(currentBlock) _, err = dbUtil.Engine.ID(1).Update(&bi) if err != nil { logs.Error("更新最新快高错误=", err) return } currentBlock++ } } func confirmClaimedTxs() { var mark int64 = 0 for { time.Sleep(time.Second * 5) logs.Info("confirmClaimedTxs mark= %v\n", mark) var txs []models.ClaimedTxs err := dbUtil.Engine.Where("state = ?", 0).Where("droped = ?", 0).Where("id > ?", mark).Find(&txs) if err != nil { logs.Error(err) continue } if len(txs) > 0 { mark = txs[len(txs)-1].Id } for _, t := range txs { go func(tx models.ClaimedTxs) { interval := 0 for { time.Sleep(time.Second * 5) if interval > (CONFIRMINTERVAL / 5) { var ui models.UserInfo _, err := dbUtil.Engine.Id(tx.Hash).Get(&ui) if err != nil { mark = tx.Id - 1 return } ui.AvailableClaim += tx.Amount ui.TotalClaimed -= tx.Amount _, err = dbUtil.Engine.ID(tx.Addr).Cols("total_claimed,available_claim").Update(&ui) if err != nil { mark = tx.Id - 1 return } tx.Droped = 1 _, err = dbUtil.Engine.ID(tx.Hash).Cols("droped").Update(&tx) if err != nil { mark = tx.Id - 1 return } return } ptx, err := ktoClient.GetTxByHash(context.Background(), &pb.ReqTxByHash{Hash: tx.Hash}) if err != nil { interval++ continue } if ptx.Code != 0 { interval++ continue } ftx, err := transaction.DeserializeFinishedTransaction(ptx.Data) if err != nil { interval++ continue } //pending tx if ftx.BlockNum == 0 { interval++ continue } tx.State = 1 _, err = dbUtil.Engine.ID(tx.Hash).Cols("state").Update(&tx) if err != nil { mark = tx.Id - 1 } return } }(t) } } }