github.com/turingchain2020/turingchain@v1.1.21/util/exec.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package util 6 7 import ( 8 "errors" 9 10 clientApi "github.com/turingchain2020/turingchain/client" 11 "github.com/turingchain2020/turingchain/common" 12 log "github.com/turingchain2020/turingchain/common/log/log15" 13 "github.com/turingchain2020/turingchain/queue" 14 "github.com/turingchain2020/turingchain/types" 15 ) 16 17 //CheckBlock : To check the block's validaty 18 func CheckBlock(client queue.Client, block *types.BlockDetail) error { 19 req := block 20 msg := client.NewMessage("consensus", types.EventCheckBlock, req) 21 err := client.Send(msg, true) 22 if err != nil { 23 return err 24 } 25 resp, err := client.Wait(msg) 26 if err != nil { 27 return err 28 } 29 reply := resp.GetData().(*types.Reply) 30 if reply.IsOk { 31 return nil 32 } 33 return errors.New(string(reply.GetMsg())) 34 } 35 36 //ExecTx : To send lists of txs within a block to exector for execution 37 func ExecTx(client queue.Client, prevStateRoot []byte, block *types.Block) (*types.Receipts, error) { 38 list := &types.ExecTxList{ 39 StateHash: prevStateRoot, 40 ParentHash: block.ParentHash, 41 MainHash: block.MainHash, 42 MainHeight: block.MainHeight, 43 Txs: block.Txs, 44 BlockTime: block.BlockTime, 45 Height: block.Height, 46 Difficulty: uint64(block.Difficulty), 47 IsMempool: false, 48 } 49 msg := client.NewMessage("execs", types.EventExecTxList, list) 50 err := client.Send(msg, true) 51 if err != nil { 52 return nil, err 53 } 54 resp, err := client.Wait(msg) 55 if err != nil { 56 return nil, err 57 } 58 receipts := resp.GetData().(*types.Receipts) 59 return receipts, nil 60 } 61 62 //ExecKVMemSet : send kv values to memory store and set it in db 63 func ExecKVMemSet(client queue.Client, prevStateRoot []byte, height int64, kvset []*types.KeyValue, sync bool, upgrade bool) ([]byte, error) { 64 set := &types.StoreSet{StateHash: prevStateRoot, KV: kvset, Height: height} 65 setwithsync := &types.StoreSetWithSync{Storeset: set, Sync: sync, Upgrade: upgrade} 66 67 msg := client.NewMessage("store", types.EventStoreMemSet, setwithsync) 68 err := client.Send(msg, true) 69 if err != nil { 70 return nil, err 71 } 72 resp, err := client.Wait(msg) 73 if err != nil { 74 return nil, err 75 } 76 hash := resp.GetData().(*types.ReplyHash) 77 return hash.GetHash(), nil 78 } 79 80 //ExecKVSetCommit : commit the data set opetation to db 81 func ExecKVSetCommit(client queue.Client, hash []byte, upgrade bool) error { 82 req := &types.ReqHash{Hash: hash, Upgrade: upgrade} 83 msg := client.NewMessage("store", types.EventStoreCommit, req) 84 err := client.Send(msg, true) 85 if err != nil { 86 return err 87 } 88 msg, err = client.Wait(msg) 89 if err != nil { 90 return err 91 } 92 hash = msg.GetData().(*types.ReplyHash).GetHash() 93 _ = hash 94 return nil 95 } 96 97 //ExecKVSetRollback : do the db's roll back operation 98 func ExecKVSetRollback(client queue.Client, hash []byte) error { 99 req := &types.ReqHash{Hash: hash} 100 msg := client.NewMessage("store", types.EventStoreRollback, req) 101 err := client.Send(msg, true) 102 if err != nil { 103 return err 104 } 105 msg, err = client.Wait(msg) 106 if err != nil { 107 return err 108 } 109 hash = msg.GetData().(*types.ReplyHash).GetHash() 110 _ = hash 111 return nil 112 } 113 114 //DelDupTx 删除重复的交易 115 func DelDupTx(txs []*types.TransactionCache) (ret []*types.TransactionCache) { 116 dupindex := make(map[string]int) 117 hasdup := false 118 for i, tx := range txs { 119 if _, ok := dupindex[string(tx.Hash())]; ok { 120 hasdup = true 121 } 122 dupindex[string(tx.Hash())] = i 123 } 124 //没有重复的情况下,不需要重新处理 125 if !hasdup { 126 return txs 127 } 128 index := 0 129 for i, tx := range txs { 130 lastindex := dupindex[string(tx.Hash())] 131 if i == lastindex { 132 txs[index] = tx 133 index++ 134 } 135 } 136 return txs[0:index] 137 } 138 139 //CheckDupTx : check use txs []*types.Transaction and not []*types.TransactionCache 140 func CheckDupTx(client queue.Client, txs []*types.Transaction, height int64) (transactions []*types.Transaction, err error) { 141 txcache := make([]*types.TransactionCache, len(txs)) 142 for i := 0; i < len(txcache); i++ { 143 txcache[i] = &types.TransactionCache{Transaction: txs[i]} 144 } 145 cache, err := CheckTxDup(client, txcache, height) 146 if err != nil { 147 return nil, err 148 } 149 for i := 0; i < len(cache); i++ { 150 transactions = append(transactions, cache[i].Transaction) 151 } 152 return transactions, nil 153 } 154 155 //CheckTxDup : check whether the tx is duplicated within the while chain 156 func CheckTxDup(client queue.Client, txs []*types.TransactionCache, height int64) (transactions []*types.TransactionCache, err error) { 157 var checkHashList types.TxHashList 158 types.AssertConfig(client) 159 cfg := client.GetConfig() 160 if cfg.IsFork(height, "ForkCheckTxDup") { 161 txs = DelDupTx(txs) 162 } 163 for _, tx := range txs { 164 checkHashList.Hashes = append(checkHashList.Hashes, tx.Hash()) 165 checkHashList.Expire = append(checkHashList.Expire, tx.GetExpire()) 166 } 167 checkHashList.Count = height 168 hashList := client.NewMessage("blockchain", types.EventTxHashList, &checkHashList) 169 err = client.Send(hashList, true) 170 if err != nil { 171 log.Error("send", "to blockchain EventTxHashList msg err", err) 172 return nil, err 173 } 174 dupTxList, err := client.Wait(hashList) 175 176 if err != nil { 177 return nil, err 178 } 179 dupTxs := dupTxList.GetData().(*types.TxHashList).Hashes 180 dupMap := make(map[string]bool) 181 for _, hash := range dupTxs { 182 dupMap[string(hash)] = true 183 } 184 185 for _, tx := range txs { 186 hash := tx.Hash() 187 if dupMap[string(hash)] { 188 continue 189 } 190 transactions = append(transactions, tx) 191 } 192 client.FreeMessage(hashList, dupTxList) 193 return transactions, nil 194 } 195 196 //ReportErrEventToFront 上报指定错误信息到指定模块,目前只支持从store,blockchain,wallet写数据库失败时上报错误信息到wallet模块, 197 //然后由钱包模块前端定时调用显示给客户 198 func ReportErrEventToFront(logger log.Logger, client queue.Client, frommodule string, tomodule string, err error) { 199 if client == nil || len(tomodule) == 0 || len(frommodule) == 0 || err == nil { 200 logger.Error("SendErrEventToFront input para err .") 201 return 202 } 203 204 logger.Debug("SendErrEventToFront", "frommodule", frommodule, "tomodule", tomodule, "err", err) 205 206 var reportErrEvent types.ReportErrEvent 207 reportErrEvent.Frommodule = frommodule 208 reportErrEvent.Tomodule = tomodule 209 reportErrEvent.Error = err.Error() 210 211 api, err := clientApi.New(client, nil) 212 if err != nil { 213 log.Error("client", "new err", err) 214 } 215 216 _, err = api.ExecWalletFunc(tomodule, "ErrToFront", &reportErrEvent) 217 if err != nil { 218 log.Error("send", "ErrToFront msg err", err) 219 } 220 } 221 222 //DelDupKey 删除重复的key 223 func DelDupKey(kvs []*types.KeyValue) []*types.KeyValue { 224 dupindex := make(map[string]int) 225 n := 0 226 for _, kv := range kvs { 227 skey := string(kv.Key) 228 if index, ok := dupindex[skey]; ok { 229 //重复的key 替换老的key 230 kvs[index] = kv 231 } else { 232 dupindex[skey] = n 233 kvs[n] = kv 234 n++ 235 } 236 } 237 return kvs[0:n] 238 } 239 240 //CmpBestBlock : 选择最优区块,通知共识模块newblock是否是最优区块 241 // height,time,parentHash一致时根据共识各自规则判断 242 func CmpBestBlock(client queue.Client, newBlock *types.Block, cmpHash []byte) bool { 243 cfg := client.GetConfig() 244 req := types.CmpBlock{Block: newBlock, CmpHash: cmpHash} 245 msg := client.NewMessage("consensus", types.EventCmpBestBlock, &req) 246 err := client.Send(msg, true) 247 if err != nil { 248 log.Error("CmpBestBlock:Send", "cmpHash", common.ToHex(cmpHash), "newBlockHash", common.ToHex(newBlock.Hash(cfg)), "err", err) 249 return false 250 } 251 resp, err := client.Wait(msg) 252 if err != nil { 253 log.Error("CmpBestBlock:Wait", "cmpHash", common.ToHex(cmpHash), "newBlockHash", common.ToHex(newBlock.Hash(cfg)), "err", err) 254 return false 255 } 256 reply := resp.GetData().(*types.Reply) 257 258 log.Debug("CmpBestBlock", "newBlockHash", common.ToHex(newBlock.Hash(cfg)), "cmpHash", common.ToHex(cmpHash), "isBestBlock", reply.IsOk) 259 return reply.IsOk 260 }