github.com/turingchain2020/turingchain@v1.1.21/system/mempool/check.go (about) 1 package mempool 2 3 import ( 4 "errors" 5 "time" 6 7 "github.com/turingchain2020/turingchain/common" 8 9 "github.com/turingchain2020/turingchain/util" 10 11 "github.com/turingchain2020/turingchain/common/address" 12 "github.com/turingchain2020/turingchain/queue" 13 "github.com/turingchain2020/turingchain/types" 14 ) 15 16 // CheckExpireValid 检查交易过期有效性,过期返回false,未过期返回true 17 func (mem *Mempool) CheckExpireValid(msg *queue.Message) (bool, error) { 18 mem.proxyMtx.Lock() 19 defer mem.proxyMtx.Unlock() 20 if mem.header == nil { 21 return false, types.ErrHeaderNotSet 22 } 23 tx := msg.GetData().(types.TxGroup).Tx() 24 ok := mem.checkExpireValid(tx) 25 if !ok { 26 return ok, types.ErrTxExpire 27 } 28 return ok, nil 29 } 30 31 // checkTxListRemote 发送消息给执行模块检查交易 32 func (mem *Mempool) checkTxListRemote(txlist *types.ExecTxList) (*types.ReceiptCheckTxList, error) { 33 if mem.client == nil { 34 panic("client not bind message queue.") 35 } 36 msg := mem.client.NewMessage("execs", types.EventCheckTx, txlist) 37 err := mem.client.Send(msg, true) 38 if err != nil { 39 mlog.Error("execs closed", "err", err.Error()) 40 return nil, err 41 } 42 reply, err := mem.client.Wait(msg) 43 if err != nil { 44 return nil, err 45 } 46 txList := reply.GetData().(*types.ReceiptCheckTxList) 47 mem.client.FreeMessage(msg, reply) 48 return txList, nil 49 } 50 51 func (mem *Mempool) checkExpireValid(tx *types.Transaction) bool { 52 types.AssertConfig(mem.client) 53 //进入mempool中的交易可能被下一个区块打包,这里用下一个区块的高度和时间作为交易过期判定 54 if tx.IsExpire(mem.client.GetConfig(), mem.header.GetHeight()+1, mem.header.GetBlockTime()) { 55 return false 56 } 57 if tx.Expire > 1000000000 && tx.Expire < types.Now().Unix()+int64(time.Minute/time.Second) { 58 return false 59 } 60 return true 61 } 62 63 // CheckTx 初步检查并筛选交易消息 64 func (mem *Mempool) checkTx(msg *queue.Message) *queue.Message { 65 tx := msg.GetData().(types.TxGroup).Tx() 66 // 检查接收地址是否合法 67 if err := address.CheckAddress(tx.To); err != nil { 68 msg.Data = types.ErrInvalidAddress 69 return msg 70 } 71 // 检查交易账户在mempool中是否存在过多交易 72 from := tx.From() 73 if mem.TxNumOfAccount(from) >= mem.cfg.MaxTxNumPerAccount { 74 msg.Data = types.ErrManyTx 75 return msg 76 } 77 // 检查交易是否过期 78 valid, err := mem.CheckExpireValid(msg) 79 if !valid { 80 msg.Data = err 81 return msg 82 } 83 return msg 84 } 85 86 // CheckTxs 初步检查并筛选交易消息 87 func (mem *Mempool) checkTxs(msg *queue.Message) *queue.Message { 88 // 判断消息是否含有nil交易 89 if msg.GetData() == nil { 90 msg.Data = types.ErrEmptyTx 91 return msg 92 } 93 header := mem.GetHeader() 94 txmsg := msg.GetData().(*types.Transaction) 95 //普通的交易 96 tx := types.NewTransactionCache(txmsg) 97 types.AssertConfig(mem.client) 98 err := tx.Check(mem.client.GetConfig(), header.GetHeight(), mem.cfg.MinTxFeeRate, mem.cfg.MaxTxFee) 99 if err != nil { 100 msg.Data = err 101 return msg 102 } 103 if mem.cfg.IsLevelFee { 104 err = mem.checkLevelFee(tx) 105 if err != nil { 106 msg.Data = err 107 return msg 108 } 109 } 110 //放在交易费检查后面进行 哈希缓存设置,避免哈希缓存改变原始交易size 111 //txmsg.ReCalcCacheHash() 112 //检查txgroup 中的每个交易 113 txs, err := tx.GetTxGroup() 114 if err != nil { 115 msg.Data = err 116 return msg 117 } 118 msg.Data = tx 119 //普通交易 120 if txs == nil { 121 return mem.checkTx(msg) 122 } 123 //txgroup 的交易 124 for i := 0; i < len(txs.Txs); i++ { 125 msgitem := mem.checkTx(&queue.Message{Data: txs.Txs[i]}) 126 if msgitem.Err() != nil { 127 msg.Data = msgitem.Err() 128 return msg 129 } 130 } 131 return msg 132 } 133 134 // checkLevelFee 检查阶梯手续费 135 func (mem *Mempool) checkLevelFee(tx *types.TransactionCache) error { 136 //获取mempool里所有交易手续费总和 137 feeRate := mem.getLevelFeeRate(mem.cfg.MinTxFeeRate, 0, 0) 138 totalfee, err := tx.GetTotalFee(feeRate) 139 if err != nil { 140 return err 141 } 142 if tx.Fee < totalfee { 143 return types.ErrTxFeeTooLow 144 } 145 return nil 146 } 147 148 //checkTxRemote 检查账户余额是否足够,并加入到Mempool,成功则传入goodChan,若加入Mempool失败则传入badChan 149 func (mem *Mempool) checkTxRemote(msg *queue.Message) *queue.Message { 150 tx := msg.GetData().(types.TxGroup) 151 lastheader := mem.GetHeader() 152 153 //add check dup tx需要区分单笔交易/交易组 154 temtxlist := &types.ExecTxList{} 155 txGroup, err := tx.GetTxGroup() 156 if err != nil { 157 msg.Data = err 158 return msg 159 } 160 if txGroup == nil { 161 temtxlist.Txs = append(temtxlist.Txs, tx.Tx()) 162 } else { 163 temtxlist.Txs = append(temtxlist.Txs, txGroup.GetTxs()...) 164 } 165 temtxlist.Height = lastheader.Height 166 newtxs, err := util.CheckDupTx(mem.client, temtxlist.Txs, temtxlist.Height) 167 if err != nil { 168 msg.Data = err 169 return msg 170 } 171 if len(newtxs) != len(temtxlist.Txs) { 172 msg.Data = types.ErrDupTx 173 return msg 174 } 175 176 //exec模块检查效率影响系统性能, 支持关闭 177 if !mem.cfg.DisableExecCheck { 178 txlist := &types.ExecTxList{} 179 txlist.Txs = append(txlist.Txs, tx.Tx()) 180 txlist.BlockTime = lastheader.BlockTime 181 txlist.Height = lastheader.Height 182 txlist.StateHash = lastheader.StateHash 183 // 增加这个属性,在执行器中会使用到 184 txlist.Difficulty = uint64(lastheader.Difficulty) 185 txlist.IsMempool = true 186 187 result, err := mem.checkTxListRemote(txlist) 188 189 if err == nil && result.Errs[0] != "" { 190 err = errors.New(result.Errs[0]) 191 } 192 if err != nil { 193 mlog.Error("checkTxRemote", "txHash", common.ToHex(tx.Tx().Hash()), "checkTxListRemoteErr", err) 194 msg.Data = err 195 return msg 196 } 197 } 198 199 err = mem.PushTx(tx.Tx()) 200 if err != nil { 201 mlog.Error("checkTxRemote", "push err", err) 202 msg.Data = err 203 } 204 return msg 205 }