scan.go 5.3 KB

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