scan.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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. for {
  55. time.Sleep(time.Second * 3)
  56. res, err := ktoClient.GetMaxBlockHeight(context.Background(), &pb.ReqMaxBlockHeight{})
  57. if err != nil {
  58. logs.Error("获取交易block number错误=", err)
  59. continue
  60. }
  61. logs.Info("currentBlock:", currentBlock, "chainblock:", res.MaxHeight)
  62. if res.MaxHeight+1 == currentBlock {
  63. continue
  64. }
  65. if res.MaxHeight+1 < currentBlock {
  66. currentBlock = res.MaxHeight
  67. }
  68. bl, err := ktoClient.GetBlockByNum(context.Background(), &pb.ReqBlockByNumber{Height: currentBlock})
  69. if err != nil || bl.Code != 0 {
  70. logs.Error("获取交易block错误=", err)
  71. continue
  72. }
  73. blc, errs := block.Deserialize(bl.Data)
  74. if errs != nil {
  75. logs.Error("解析blcock错误=", errs)
  76. continue
  77. }
  78. var ERR error
  79. for _, v := range blc.Transactions {
  80. if len(v.Input) == 0 {
  81. continue
  82. }
  83. evm, err := transaction.DecodeEvmData(v.Input)
  84. if err != nil {
  85. logs.Error(err)
  86. ERR = err
  87. break
  88. }
  89. if len(evm.Logs) == 0 {
  90. continue
  91. }
  92. for _, l := range evm.Logs {
  93. th := l.Topics[0].Hex()
  94. method := TopsMap[th]
  95. contract := l.Address.String()
  96. if contract == COLLECTCONTRACT {
  97. if method == COLLECT_PARTICIPATE {
  98. var ev EventParticipate
  99. abi, err := abi.JSON(strings.NewReader(Collect.CollectMetaData.ABI))
  100. if err != nil {
  101. logs.Error(err)
  102. ERR = err
  103. break
  104. }
  105. err = abi.UnpackIntoInterface(&ev, method, l.Data)
  106. if err != nil {
  107. logs.Error(err)
  108. ERR = err
  109. break
  110. }
  111. logs.Info("participate data:", ev.Participant.String(), ev.Inviter.String(), v.HashToString(), float64(ev.Amount.Uint64()/controller.Decimals))
  112. //handle user participate
  113. err = participate(dbUtil.Engine, ev.Participant.String(), ev.Inviter.String(), v.HashToString(), float64(ev.Amount.Uint64()/controller.Decimals))
  114. if err != nil {
  115. logs.Error(err)
  116. ERR = err
  117. break
  118. }
  119. } else if method == COLLECT_CLAIMREWARDS {
  120. var evt EventClaim
  121. abi, err := abi.JSON(strings.NewReader(Collect.CollectMetaData.ABI))
  122. if err != nil {
  123. logs.Error(err)
  124. ERR = err
  125. break
  126. }
  127. err = abi.UnpackIntoInterface(&evt, method, l.Data)
  128. if err != nil {
  129. logs.Error(err)
  130. ERR = err
  131. break
  132. }
  133. fmt.Printf("claim event data=%+v\n ", evt)
  134. var bts []byte
  135. for _, b := range evt.Signature {
  136. bts = append(bts, b)
  137. }
  138. err = checkClaim(dbUtil.Engine, evt.User.String(), "0x"+v.HashToString(), int64(v.BlockNum),
  139. float64(evt.Amount.Uint64())/controller.Decimals, hex.EncodeToString(bts))
  140. if err != nil {
  141. logs.Error(err)
  142. ERR = err
  143. break
  144. }
  145. }
  146. }
  147. }
  148. if ERR != nil {
  149. logs.Error(err)
  150. break
  151. }
  152. }
  153. if ERR != nil {
  154. logs.Error("处理错误=", ERR)
  155. continue
  156. }
  157. bi.BlockNumber = int64(currentBlock)
  158. _, err = dbUtil.Engine.ID(1).Update(&bi)
  159. if err != nil {
  160. logs.Error("更新最新快高错误=", err)
  161. return
  162. }
  163. currentBlock++
  164. }
  165. }
  166. func confirmClaimedTxs() {
  167. var mark int64 = 0
  168. for {
  169. time.Sleep(time.Second * 5)
  170. logs.Info("confirmClaimedTxs mark= %v\n", mark)
  171. var txs []models.ClaimedTxs
  172. err := dbUtil.Engine.Where("state = ?", 0).Where("droped = ?", 0).Where("id > ?", mark).Find(&txs)
  173. if err != nil {
  174. logs.Error(err)
  175. continue
  176. }
  177. if len(txs) > 0 {
  178. mark = txs[len(txs)-1].Id
  179. logs.Info("confirmClaimedTxs2 mark= %v\n", mark)
  180. }
  181. for _, t := range txs {
  182. go func(tx models.ClaimedTxs) {
  183. interval := 0
  184. for {
  185. time.Sleep(time.Second * 5)
  186. if interval > (CONFIRMINTERVAL / 5) {
  187. var ui models.UserInfo
  188. _, err := dbUtil.Engine.Id(tx.Hash).Get(&ui)
  189. if err != nil {
  190. mark = tx.Id - 1
  191. return
  192. }
  193. ui.AvailableClaim += tx.Amount
  194. ui.TotalClaimed -= tx.Amount
  195. _, err = dbUtil.Engine.ID(tx.Addr).Cols("total_claimed,available_claim").Update(&ui)
  196. if err != nil {
  197. mark = tx.Id - 1
  198. return
  199. }
  200. tx.Droped = 1
  201. _, err = dbUtil.Engine.ID(tx.Hash).Cols("droped").Update(&tx)
  202. if err != nil {
  203. mark = tx.Id - 1
  204. return
  205. }
  206. return
  207. }
  208. ptx, err := ktoClient.GetTxByHash(context.Background(), &pb.ReqTxByHash{Hash: tx.Hash})
  209. if err != nil {
  210. interval++
  211. continue
  212. }
  213. if ptx.Code != 0 {
  214. interval++
  215. continue
  216. }
  217. ftx, err := transaction.DeserializeFinishedTransaction(ptx.Data)
  218. if err != nil {
  219. interval++
  220. continue
  221. }
  222. //pending tx
  223. if ftx.BlockNum == 0 {
  224. interval++
  225. continue
  226. }
  227. tx.State = 1
  228. _, err = dbUtil.Engine.ID(tx.Hash).Cols("state").Update(&tx)
  229. if err != nil {
  230. mark = tx.Id - 1
  231. }
  232. return
  233. }
  234. }(t)
  235. }
  236. }
  237. }