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 tm[TOPIC_CLAIM] = COLLECT_CLAIMREWARDS 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 logs.Info("currentBlock===", currentBlock) 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+1 == currentBlock { continue } if res.MaxHeight+1 < 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(ev.Participant.String(), ev.Inviter.String(), v.HashToString(), float64(PARTICIPATEVALUE)) 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) var bts []byte for _, b := range evt.Signature { bts = append(bts, b) } err = checkClaim(dbUtil.Engine, evt.User.String(), "0x"+v.HashToString(), int64(v.BlockNum), float64(evt.Amount.Uint64())/controller.Decimals, hex.EncodeToString(bts)) 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() { for { time.Sleep(time.Second * 5) var txs []models.ClaimedTxs err := dbUtil.Engine.Where("state = ?", 0).Where("droped = ?", 0).Find(&txs) if err != nil { logs.Error(err) continue } logs.Info("confirmClaimedTxs get unconfirmed tx num: %v", len(txs)) for _, tx := range txs { loc, _ := time.LoadLocation("Local") formatTime, err := time.ParseInLocation(TimeLayout, tx.CreateTime, loc) if err != nil { logs.Error("confirmClaimedTxs:", err) } if formatTime.Unix()+CONFIRMINTERVAL < time.Now().Unix() { var ui models.UserInfo _, err := dbUtil.Engine.Id(tx.Hash).Get(&ui) if err != nil { logs.Error("confirmClaimedTxs:", err) continue } logs.Info("confirmClaimedTxs mark claimed tx droped,addr:%v,hash:%v,amount:%v", tx.Addr, tx.Hash, tx.Amount) ui.AvailableClaim += tx.Amount ui.TotalClaimed -= tx.Amount _, err = dbUtil.Engine.ID(tx.Addr).Cols("available_claim,total_claimed").Update(&ui) if err != nil { logs.Error("confirmClaimedTxs:", err) continue } tx.Droped = 1 _, err = dbUtil.Engine.ID(tx.Hash).Cols("droped").Update(&tx) if err != nil { logs.Error("confirmClaimedTxs:", err) continue } } } } }