scan.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. package blockchain
  2. import (
  3. "context"
  4. "encoding/hex"
  5. "fmt"
  6. "ktogame/contractgo/Collect"
  7. "ktogame/controller"
  8. "ktogame/dbUtil"
  9. "ktogame/models"
  10. "os"
  11. "strings"
  12. "time"
  13. "github.com/astaxie/beego"
  14. "github.com/astaxie/beego/logs"
  15. "github.com/ethereum/go-ethereum/accounts/abi"
  16. utilAddress "github.com/korthochain/korthochain/pkg/address"
  17. "github.com/korthochain/korthochain/pkg/block"
  18. pb "github.com/korthochain/korthochain/pkg/server/grpcserver/message"
  19. "github.com/korthochain/korthochain/pkg/transaction"
  20. "google.golang.org/grpc"
  21. )
  22. var ktoClient pb.GreeterClient
  23. var ktoRpc = beego.AppConfig.String("miner_node")
  24. var currentBlock uint64
  25. var TopsMap map[string]string
  26. func init() {
  27. kc, err := grpc.Dial(ktoRpc, grpc.WithInsecure(), grpc.WithBlock())
  28. if err != nil {
  29. logs.Error(err)
  30. os.Exit(1)
  31. }
  32. ktoClient = pb.NewGreeterClient(kc)
  33. utilAddress.SetNetWork("mainnet")
  34. tm := make(map[string]string, 0)
  35. tm[TOPIC_PARTICIPATE] = COLLECT_PARTICIPATE
  36. tm[TOPIC_CLAIM] = COLLECT_CLAIMREWARDS
  37. TopsMap = tm
  38. go scanBlock()
  39. go confirmClaimedTxs()
  40. }
  41. func scanBlock() {
  42. logs.Info("scanBlock...")
  43. var bi models.BlockInfo
  44. ok, err := dbUtil.Engine.Id(1).Get(&bi)
  45. if err != nil {
  46. fmt.Println("获取最新快高错误=", err)
  47. return
  48. }
  49. if !ok {
  50. fmt.Println("获取最新快高失败!")
  51. return
  52. }
  53. currentBlock = uint64(bi.BlockNumber) + 1
  54. logs.Info("currentBlock===", currentBlock)
  55. for {
  56. time.Sleep(time.Second * 3)
  57. res, err := ktoClient.GetMaxBlockHeight(context.Background(), &pb.ReqMaxBlockHeight{})
  58. if err != nil {
  59. logs.Error("获取交易block number错误=", err)
  60. continue
  61. }
  62. logs.Info("currentBlock:", currentBlock, "chainblock:", res.MaxHeight)
  63. if res.MaxHeight+1 == currentBlock {
  64. continue
  65. }
  66. if res.MaxHeight+1 < currentBlock {
  67. currentBlock = res.MaxHeight
  68. }
  69. bl, err := ktoClient.GetBlockByNum(context.Background(), &pb.ReqBlockByNumber{Height: currentBlock})
  70. if err != nil || bl.Code != 0 {
  71. logs.Error("获取交易block错误=", err)
  72. continue
  73. }
  74. blc, errs := block.Deserialize(bl.Data)
  75. if errs != nil {
  76. logs.Error("解析blcock错误=", errs)
  77. continue
  78. }
  79. var ERR error
  80. for _, v := range blc.Transactions {
  81. if len(v.Input) == 0 {
  82. continue
  83. }
  84. evm, err := transaction.DecodeEvmData(v.Input)
  85. if err != nil {
  86. logs.Error(err)
  87. ERR = err
  88. break
  89. }
  90. if len(evm.Logs) == 0 {
  91. continue
  92. }
  93. for _, l := range evm.Logs {
  94. th := l.Topics[0].Hex()
  95. method := TopsMap[th]
  96. contract := l.Address.String()
  97. if contract == COLLECTCONTRACT {
  98. if method == COLLECT_PARTICIPATE {
  99. var ev EventParticipate
  100. abi, err := abi.JSON(strings.NewReader(Collect.CollectMetaData.ABI))
  101. if err != nil {
  102. logs.Error(err)
  103. ERR = err
  104. break
  105. }
  106. err = abi.UnpackIntoInterface(&ev, method, l.Data)
  107. if err != nil {
  108. logs.Error(err)
  109. ERR = err
  110. break
  111. }
  112. logs.Info("participate data:", ev.Participant.String(), ev.Inviter.String(), v.HashToString(), float64(ev.Amount.Uint64()/controller.Decimals))
  113. //handle user participate
  114. err = participate(ev.Participant.String(), ev.Inviter.String(), v.HashToString(), float64(ev.Amount.Uint64()/controller.Decimals))
  115. if err != nil {
  116. logs.Error(err)
  117. ERR = err
  118. break
  119. }
  120. } else if method == COLLECT_CLAIMREWARDS {
  121. var evt EventClaim
  122. abi, err := abi.JSON(strings.NewReader(Collect.CollectMetaData.ABI))
  123. if err != nil {
  124. logs.Error(err)
  125. ERR = err
  126. break
  127. }
  128. err = abi.UnpackIntoInterface(&evt, method, l.Data)
  129. if err != nil {
  130. logs.Error(err)
  131. ERR = err
  132. break
  133. }
  134. fmt.Printf("claim event data=%+v\n ", evt)
  135. var bts []byte
  136. for _, b := range evt.Signature {
  137. bts = append(bts, b)
  138. }
  139. err = checkClaim(dbUtil.Engine, evt.User.String(), "0x"+v.HashToString(), int64(v.BlockNum),
  140. float64(evt.Amount.Uint64())/controller.Decimals, hex.EncodeToString(bts))
  141. if err != nil {
  142. logs.Error(err)
  143. ERR = err
  144. break
  145. }
  146. }
  147. }
  148. }
  149. if ERR != nil {
  150. logs.Error(err)
  151. break
  152. }
  153. }
  154. if ERR != nil {
  155. logs.Error("处理错误=", ERR)
  156. continue
  157. }
  158. bi.BlockNumber = int64(currentBlock)
  159. _, err = dbUtil.Engine.ID(1).Update(&bi)
  160. if err != nil {
  161. logs.Error("更新最新快高错误=", err)
  162. return
  163. }
  164. currentBlock++
  165. }
  166. }
  167. func confirmClaimedTxs() {
  168. for {
  169. time.Sleep(time.Second * 5)
  170. var txs []models.ClaimedTxs
  171. err := dbUtil.Engine.Where("state = ?", 0).Where("droped = ?", 0).Find(&txs)
  172. if err != nil {
  173. logs.Error(err)
  174. continue
  175. }
  176. logs.Info("confirmClaimedTxs get unconfirmed tx num: %v", len(txs))
  177. for _, tx := range txs {
  178. loc, _ := time.LoadLocation("Local")
  179. formatTime, err := time.ParseInLocation(TimeLayout, tx.CreateTime, loc)
  180. if err != nil {
  181. logs.Error("confirmClaimedTxs:", err)
  182. }
  183. if formatTime.Unix()+CONFIRMINTERVAL < time.Now().Unix() {
  184. var ui models.UserInfo
  185. _, err := dbUtil.Engine.Id(tx.Hash).Get(&ui)
  186. if err != nil {
  187. logs.Error("confirmClaimedTxs:", err)
  188. continue
  189. }
  190. logs.Info("confirmClaimedTxs mark claimed tx droped,addr:%v,hash:%v,amount:%v", tx.Addr, tx.Hash, tx.Amount)
  191. ui.AvailableClaim += tx.Amount
  192. ui.TotalClaimed -= tx.Amount
  193. _, err = dbUtil.Engine.ID(tx.Addr).Cols("available_claim,total_claimed").Update(&ui)
  194. if err != nil {
  195. logs.Error("confirmClaimedTxs:", err)
  196. continue
  197. }
  198. tx.Droped = 1
  199. _, err = dbUtil.Engine.ID(tx.Hash).Cols("droped").Update(&tx)
  200. if err != nil {
  201. logs.Error("confirmClaimedTxs:", err)
  202. continue
  203. }
  204. }
  205. }
  206. }
  207. }