github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/txpool/orgchain/subtx_pool_collector.go (about) 1 package orgchain 2 3 import ( 4 "fmt" 5 "sort" 6 "sync" 7 "time" 8 9 "github.com/sixexorg/magnetic-ring/bactor" 10 orgcommon "github.com/sixexorg/magnetic-ring/p2pserver/common" 11 12 "github.com/ontio/ontology-eventbus/actor" 13 "github.com/sixexorg/magnetic-ring/log" 14 15 "github.com/sixexorg/magnetic-ring/config" 16 "github.com/sixexorg/magnetic-ring/store/orgchain/storages" 17 18 "github.com/sixexorg/magnetic-ring/common" 19 "github.com/sixexorg/magnetic-ring/core/orgchain/types" 20 "github.com/sixexorg/magnetic-ring/errors" 21 "github.com/sixexorg/magnetic-ring/store/orgchain/states" 22 "github.com/sixexorg/magnetic-ring/store/orgchain/validation" 23 "github.com/sixexorg/magnetic-ring/store/storelaw" 24 ) 25 26 type SubPool struct { 27 pdmgr *PendingMgr //Maintain a collection of transactions that can be packaged 28 //queue *SubTxQueue //Maintain a collection of transactions transmitted over the network 29 txChan chan *types.Transaction 30 maxPending uint32 31 maxInPending uint32 32 maxInQueue uint32 33 leagueId common.Address 34 35 waitTxNum map[common.Hash]uint8 36 waitPool types.Transactions 37 38 stateValidator *validation.StateValidate 39 40 txpoolPid *actor.PID 41 mustPackTxs []*types.Transaction 42 } 43 44 func (pool *SubPool) Start() { 45 go func() { 46 for { 47 select { 48 case tx := <-pool.txChan: 49 fmt.Println("♦️ subTxpool add") 50 err := pool.AddTx(pool.leagueId, tx) 51 if err != nil { 52 log.Error("addtx error", "tx_pool", err) 53 } 54 } 55 } 56 }() 57 } 58 59 func startActor(obj interface{}, id string) (*actor.PID, error) { 60 props := actor.FromProducer(func() actor.Actor { 61 return obj.(actor.Actor) 62 }) 63 64 pid, _ := actor.SpawnNamed(props, id) 65 if pid == nil { 66 return nil, fmt.Errorf("fail to start actor at props:%v id:%s", props, id) 67 } 68 return pid, nil 69 } 70 71 func NewSubPool(ledger *storages.LedgerStoreImp, leadgeId common.Address) *SubPool { 72 pool := new(SubPool) 73 pool.pdmgr = NewPendingMgr() 74 //pool.queue = NewSubTxQueue() 75 pool.maxPending = config.GlobalConfig.TxPoolCfg.MaxPending 76 pool.maxInPending = config.GlobalConfig.TxPoolCfg.MaxInPending 77 pool.maxInQueue = config.GlobalConfig.TxPoolCfg.MaxInQueue 78 pool.txChan = make(chan *types.Transaction, pool.maxInQueue) 79 pool.leagueId = leadgeId 80 81 pool.waitPool = make(types.Transactions, 0, 10000) 82 pool.waitTxNum = make(map[common.Hash]uint8, 10000) 83 84 pool.RefreshValidator(ledger, leadgeId) 85 pool.mustPackTxs = make([]*types.Transaction, 0) 86 poolActor := NewTxActor(pool) 87 88 pid, err := startActor(poolActor, "subtxpoolAcotor") 89 if err != nil { 90 return nil 91 } 92 93 pool.txpoolPid = pid 94 95 pool.Start() 96 return pool 97 } 98 99 func (pool *SubPool) AppendMustPackTx(txs ...*types.Transaction) { 100 101 for _, tx := range txs { 102 pool.mustPackTxs = append(pool.mustPackTxs, tx) 103 } 104 105 } 106 107 func (pool *SubPool) refreshWaitPool() { 108 if pool.waitPool.Len() > 0 { 109 for wp := range pool.waitPool { 110 pool.TxEnqueue(pool.waitPool[wp]) 111 } 112 } 113 pool.waitPool = make(types.Transactions, 0, 10000) 114 pool.waitTxNum = make(map[common.Hash]uint8, 10000) 115 } 116 117 func (pool *SubPool) RefreshValidator(ledger *storages.LedgerStoreImp, leadgeId common.Address) { 118 if pool.stateValidator != nil { 119 fmt.Println("🚰 refreshValidator txlen", pool.stateValidator.GetTxLen()) 120 } 121 oldSV := pool.stateValidator 122 pool.stateValidator = validation.NewStateValidate(ledger, leadgeId) 123 if oldSV != nil { 124 txch := oldSV.TxInheritance() 125 for ch := range txch { 126 pool.TxEnqueue(ch) 127 } 128 } 129 pool.refreshWaitPool() 130 //log.Info("func txpool RefreshValidator 02", "newTargetHeight", pool.stateValidator.TargetHeight, "txlen", pool.stateValidator.GetTxLen()) 131 fmt.Println("func txpool RefreshValidator 02 ", "newTargetHeight=", pool.stateValidator.TargetHeight, " txlen=", pool.stateValidator.GetTxLen()) 132 } 133 134 func (pool *SubPool) AddTx(leagueId common.Address, tx *types.Transaction) error { 135 fmt.Println("⭕️ txpool addtx 1 type:", tx.TxType) 136 result, err := pool.stateValidator.VerifyTx(tx) 137 txHash := tx.Hash() 138 fmt.Println("⭕️ txpool addtx 2", result, err) 139 if result == 1 || result == 0 { 140 orgTx := orgcommon.OrgTx{ 141 OrgId: pool.leagueId, 142 Tx: tx, 143 } 144 P2PPid, err := bactor.GetActorPid(bactor.P2PACTOR) 145 if err != nil { 146 log.Error("tx_pool.go get p2ppid error", "error", err) 147 } else { 148 P2PPid.Tell(orgTx) 149 } 150 } 151 fmt.Println("⭕️ txpool addtx 3", result, err) 152 switch result { 153 case -1: 154 return err 155 case 0: 156 if uint32(len(pool.txChan)) < pool.maxInQueue { 157 158 pool.waitTxNum[txHash]++ 159 if uint32(pool.waitTxNum[txHash]) == config.GlobalConfig.TxPoolCfg.MaxTxInPool { 160 pool.waitPool = append(pool.waitPool, tx) 161 } else if uint32(pool.waitTxNum[txHash]) < config.GlobalConfig.TxPoolCfg.MaxTxInPool { 162 pool.TxEnqueue(tx) 163 } 164 165 } else { 166 return errors.ERR_TXPOOL_OUTOFMAX 167 } 168 return nil 169 case 1: 170 pool.pdmgr.addTx(tx, pool.maxPending) 171 return nil 172 } 173 174 return nil 175 } 176 177 /** 178 generate block 179 */ 180 func (pool *SubPool) GenerateBlock(leagueId common.Address, height uint64, packtx bool) *types.Block { 181 182 sts := states.AccountStates{} 183 var txs *types.Transactions 184 if packtx { 185 txs = pool.pdmgr.getTxs(pool.maxPending) 186 sort.Sort(txs) 187 } 188 189 block := &types.Block{ 190 Header: &types.Header{ 191 Height: pool.stateValidator.TargetHeight, 192 Version: types.TxVersion, 193 PrevBlockHash: common.Hash{}, 194 ReceiptsRoot: common.Hash{}, 195 StateRoot: sts.GetHashRoot(), 196 TxRoot: txs.GetHashRoot(), 197 Timestamp: uint64(time.Now().Unix()), 198 }, 199 Transactions: *txs, 200 } 201 202 //reset validator 203 //pool.RefreshValidator() 204 return block 205 } 206 207 /** 208 func (pool *SubPool) ValidateSyncTxs(leagueId common.Address, txhashes []*common.Hash) error { 209 210 if pool.pdmgr.pendingTxs == nil || len(pool.pdmgr.pendingTxs) < 1 { 211 return errors.ERR_TXPOOL_TXNOTFOUND 212 } 213 214 for _, v := range txhashes { 215 vtx := pool.queue.Remove(*v) 216 217 if vtx == nil { 218 return errors.ERR_TXPOOL_TXNOTFOUND 219 } 220 221 result, err := pool.stateValidator.VerifyTx(vtx) 222 switch result { 223 case -1: 224 return err 225 case 0: 226 if uint32(pool.queue.Size()) < pool.maxInQueue { 227 pool.queue.Enqueue(vtx) 228 } else { 229 return errors.ERR_TXPOOL_OUTOFMAX 230 } 231 return nil 232 case 1: 233 pool.pdmgr.addTx(vtx, pool.maxPending) 234 return nil 235 } 236 } 237 return nil 238 } 239 **/ 240 func (pool *SubPool) Execute() (blkInfo *storelaw.OrgBlockInfo) { 241 //fmt.Println("⭕️ subtxpool execute txlen", pool.stateValidator.GetTxLen()) 242 243 for _, tx := range pool.mustPackTxs { 244 ret, err := pool.stateValidator.VerifyTx(tx) 245 if err != nil { 246 log.Error("range pool.mustPackTxs verifyTx error", "ret", ret, "error", err) 247 } 248 } 249 250 return pool.stateValidator.ExecuteOplogs() 251 } 252 253 type PendingMgr struct { 254 sync.RWMutex 255 pendingTxs map[common.Hash]*types.Transaction 256 } 257 258 func NewPendingMgr() *PendingMgr { 259 mgr := new(PendingMgr) 260 mgr.pendingTxs = make(map[common.Hash]*types.Transaction) 261 return mgr 262 } 263 264 /* 265 get txs from pending transaction list 266 */ 267 func (pm *PendingMgr) getTxs(maxInblock uint32) *types.Transactions { 268 269 pm.Lock() 270 defer pm.Unlock() 271 if len(pm.pendingTxs) < 1 { 272 return nil 273 } 274 275 txs := make(types.Transactions, 0) 276 277 for _, v := range pm.pendingTxs { 278 txs = append(txs, v) 279 } 280 281 sort.Sort(txs) 282 283 le := uint32(len(txs)) 284 if le > maxInblock { 285 le = maxInblock 286 } 287 288 ret := txs[0:le] 289 290 return &ret 291 } 292 293 func (pool *SubPool) RemovePendingTxs(hashes []common.Hash) { 294 pool.pdmgr.removePendingTxs(hashes) 295 } 296 297 /* 298 get txs from pending transaction list 299 */ 300 func (pm *PendingMgr) removePendingTxs(txhashes []common.Hash) { 301 302 pm.Lock() 303 defer pm.Unlock() 304 305 if pm.pendingTxs == nil || len(pm.pendingTxs) < 1 { 306 return 307 } 308 309 for _, v := range txhashes { 310 delete(pm.pendingTxs, v) 311 } 312 313 } 314 315 /* 316 add tx to pending transaction list 317 */ 318 func (pm *PendingMgr) addTx(tx *types.Transaction, maxPending uint32) error { 319 320 pm.Lock() 321 defer pm.Unlock() 322 323 if uint32(len(pm.pendingTxs)) > maxPending { 324 return errors.ERR_TXPOOL_OUTOFMAX 325 } 326 327 pm.pendingTxs[tx.Hash()] = tx 328 return nil 329 } 330 331 func (pool *SubPool) TxEnqueue(tx *types.Transaction) error { 332 333 if uint32(len(pool.txChan)) >= pool.maxInQueue { 334 return errors.ERR_TXPOOL_OUTOFMAX 335 } 336 fmt.Println("🌈 🌈 insert tx into subTxpool") 337 pool.txChan <- tx 338 339 return nil 340 } 341 342 func (pool *SubPool) GetTxpoolPID() *actor.PID { 343 return pool.txpoolPid 344 }