github.com/annchain/OG@v0.0.9/arefactor_core/core/tx_pool.go (about) 1 // Copyright © 2019 Annchain Authors <EMAIL ADDRESS> 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 package core 15 16 import ( 17 "fmt" 18 ogTypes "github.com/annchain/OG/arefactor/og_interface" 19 "github.com/annchain/OG/status" 20 "math/rand" 21 "sort" 22 "sync" 23 "sync/atomic" 24 25 "github.com/annchain/OG/arefactor/types" 26 "github.com/annchain/OG/common/math" 27 log "github.com/sirupsen/logrus" 28 ) 29 30 type TxType uint8 31 32 const ( 33 TxTypeGenesis TxType = iota 34 TxTypeLocal 35 TxTypeRemote 36 TxTypeRejudge 37 ) 38 39 const ( 40 PoolRejudgeThreshold int = 10 41 ) 42 43 type TxPool struct { 44 conf TxPoolConfig 45 46 queue chan *txEvent // queue stores txs that need to validate later 47 48 storage *txPoolStorage 49 cachedSets *cachedAccDetailSets 50 dag *Dag 51 52 close chan struct{} 53 54 mu sync.RWMutex 55 //wg sync.WaitGroup // for TxPool Stop() 56 57 onNewTxReceived map[channelName]chan types.Txi // for notifications of new txs. 58 OnBatchConfirmed []chan map[ogTypes.HashKey]types.Txi // for notifications of confirmation. 59 OnNewLatestSequencer []chan bool // for broadcasting new latest sequencer to record height 60 61 maxWeight uint64 62 //confirmStatus *ConfirmStatus 63 } 64 65 func (pool *TxPool) GetBenchmarks() map[string]interface{} { 66 tipsNum, badNum, pendingNum := pool.storage.txLookup.Stats() 67 return map[string]interface{}{ 68 "queue": len(pool.queue), 69 "event": len(pool.onNewTxReceived), 70 "txlookup": len(pool.storage.txLookup.txs), 71 "tips": tipsNum, 72 "badtxs": badNum, 73 "pendings": pendingNum, 74 "latest_seq": int(pool.dag.latestSequencer.Number()), 75 "flows": len(pool.storage.flows.afs), 76 "hashordr": len(pool.storage.getTxHashesInOrder()), 77 } 78 } 79 80 func NewTxPool(conf TxPoolConfig, dag *Dag) *TxPool { 81 if conf.ConfirmStatusRefreshTime == 0 { 82 conf.ConfirmStatusRefreshTime = 30 83 } 84 85 pool := &TxPool{} 86 87 pool.conf = conf 88 pool.dag = dag 89 pool.queue = make(chan *txEvent, conf.QueueSize) 90 pool.storage = newTxPoolStorage(dag) 91 pool.cachedSets = newCachedAccDetailSets() 92 pool.close = make(chan struct{}) 93 94 pool.onNewTxReceived = make(map[channelName]chan types.Txi) 95 pool.OnBatchConfirmed = []chan map[ogTypes.HashKey]types.Txi{} 96 97 return pool 98 } 99 100 type TxPoolConfig struct { 101 QueueSize int `mapstructure:"queue_size"` 102 TipsSize int `mapstructure:"tips_size"` 103 ResetDuration int `mapstructure:"reset_duration"` 104 TxVerifyTime int `mapstructure:"tx_verify_time"` 105 TxValidTime int `mapstructure:"tx_valid_time"` 106 TimeOutPoolQueue int `mapstructure:"timeout_pool_queue_ms"` 107 TimeoutSubscriber int `mapstructure:"timeout_subscriber_ms"` 108 TimeoutConfirmation int `mapstructure:"timeout_confirmation_ms"` 109 TimeoutLatestSequencer int `mapstructure:"timeout_latest_seq_ms"` 110 ConfirmStatusRefreshTime int //minute 111 } 112 113 func DefaultTxPoolConfig() TxPoolConfig { 114 config := TxPoolConfig{ 115 QueueSize: 100, 116 TipsSize: 1000, 117 ResetDuration: 10, 118 TxVerifyTime: 2, 119 TxValidTime: 100, 120 TimeOutPoolQueue: 10000, 121 TimeoutSubscriber: 10000, 122 TimeoutConfirmation: 10000, 123 TimeoutLatestSequencer: 10000, 124 } 125 return config 126 } 127 128 type txEvent struct { 129 txEnv *txEnvelope 130 callbackChan chan error 131 } 132 type txEnvelope struct { 133 tx types.Txi 134 txType TxType 135 status TxStatus 136 judgeNum int 137 } 138 139 func newTxEnvelope(t TxType, status TxStatus, tx types.Txi, judgeNum int) *txEnvelope { 140 te := &txEnvelope{} 141 te.txType = t 142 te.status = status 143 te.tx = tx 144 te.judgeNum = judgeNum 145 146 return te 147 } 148 149 func (t *txEnvelope) String() string { 150 return fmt.Sprintf("{ judgeNum: %d, tx: %s }", t.judgeNum, t.tx.String()) 151 } 152 153 // Start begin the txpool sevices 154 func (pool *TxPool) Start() { 155 log.Infof("TxPool Start") 156 //go pool.loop() 157 } 158 159 // Stop stops all the txpool sevices 160 func (pool *TxPool) Stop() { 161 close(pool.close) 162 //pool.wg.Wait() 163 164 log.Infof("TxPool Stopped") 165 } 166 167 func (pool *TxPool) Init(genesis *types.Sequencer) { 168 pool.mu.Lock() 169 defer pool.mu.Unlock() 170 171 pool.storage.init(genesis) 172 173 log.Infof("TxPool finish init") 174 } 175 176 func (pool *TxPool) Name() string { 177 return "TxPool" 178 } 179 180 // PoolStatus returns the current number of 181 // tips, bad txs and pending txs stored in pool. 182 func (pool *TxPool) PoolStatus() (int, int, int) { 183 pool.mu.RLock() 184 defer pool.mu.RUnlock() 185 186 return pool.poolStatus() 187 } 188 func (pool *TxPool) poolStatus() (int, int, int) { 189 return pool.storage.stats() 190 } 191 192 // Get get a transaction or sequencer according to input hash, 193 // if tx not exists return nil 194 func (pool *TxPool) Get(hash ogTypes.Hash) types.Txi { 195 pool.mu.RLock() 196 defer pool.mu.RUnlock() 197 198 return pool.get(hash) 199 } 200 201 func (pool *TxPool) GetTxNum() int { 202 pool.mu.RLock() 203 defer pool.mu.RUnlock() 204 205 return pool.storage.getTxNum() 206 } 207 208 func (pool *TxPool) GetMaxWeight() uint64 { 209 return atomic.LoadUint64(&pool.maxWeight) 210 } 211 212 func (pool *TxPool) get(hash ogTypes.Hash) types.Txi { 213 return pool.storage.getTxByHash(hash) 214 } 215 216 func (pool *TxPool) Has(hash ogTypes.Hash) bool { 217 return pool.Get(hash) != nil 218 } 219 220 func (pool *TxPool) IsLocalHash(hash ogTypes.Hash) bool { 221 if pool.Has(hash) { 222 return true 223 } 224 if pool.dag.ExistTx(pool.dag.LatestSequencerHash(), hash) { 225 return true 226 } 227 return false 228 } 229 230 // GetHashOrder returns a hash list of txs in pool, ordered by the 231 // time that txs added into pool. 232 func (pool *TxPool) GetHashOrder() []ogTypes.Hash { 233 pool.mu.RLock() 234 defer pool.mu.RUnlock() 235 236 return pool.getHashOrder() 237 } 238 239 func (pool *TxPool) getHashOrder() []ogTypes.Hash { 240 return pool.storage.getTxHashesInOrder() 241 } 242 243 //func (pool *TxPool) GetOrder() []ogTypes.Hash { 244 // return pool.GetHashOrder() 245 //} 246 247 // GetByNonce get a tx or sequencer from account flows by sender's address and tx's nonce. 248 func (pool *TxPool) GetByNonce(addr ogTypes.Address, nonce uint64) types.Txi { 249 pool.mu.RLock() 250 defer pool.mu.RUnlock() 251 252 return pool.getByNonce(addr, nonce) 253 } 254 func (pool *TxPool) getByNonce(addr ogTypes.Address, nonce uint64) types.Txi { 255 return pool.storage.getTxByNonce(addr, nonce) 256 } 257 258 // GetLatestNonce get the latest nonce of an address 259 func (pool *TxPool) GetLatestNonce(addr ogTypes.Address) (uint64, error) { 260 pool.mu.RLock() 261 defer pool.mu.RUnlock() 262 263 return pool.storage.getLatestNonce(addr) 264 } 265 266 // GetStatus gets the current status of a tx 267 func (pool *TxPool) GetStatus(hash ogTypes.Hash) TxStatus { 268 pool.mu.RLock() 269 defer pool.mu.RUnlock() 270 271 return pool.getStatus(hash) 272 } 273 274 func (pool *TxPool) getStatus(hash ogTypes.Hash) TxStatus { 275 return pool.storage.getTxStatusInPool(hash) 276 } 277 278 type channelName struct { 279 name string 280 allMsg bool 281 } 282 283 func (c channelName) String() string { 284 return c.name 285 } 286 287 func (pool *TxPool) RegisterOnNewTxReceived(c chan types.Txi, chanName string, allTx bool) { 288 log.Tracef("RegisterOnNewTxReceived with chan: %s ,all %v", chanName, allTx) 289 chName := channelName{chanName, allTx} 290 pool.onNewTxReceived[chName] = c 291 } 292 293 // GetRandomTips returns n tips randomly. 294 func (pool *TxPool) GetRandomTips(n int) (v []types.Txi) { 295 pool.mu.RLock() 296 defer pool.mu.RUnlock() 297 298 // select n random hashes 299 values := pool.storage.getTipsInList() 300 indices := generateRandomIndices(n, len(values)) 301 302 for _, i := range indices { 303 v = append(v, values[i]) 304 } 305 return v 306 } 307 308 // generate [count] unique random numbers within range [0, upper) 309 // if count > upper, use all available indices 310 func generateRandomIndices(count int, upper int) []int { 311 if count > upper { 312 count = upper 313 } 314 // avoid dup 315 generated := make(map[int]struct{}) 316 for count > len(generated) { 317 i := rand.Intn(upper) 318 generated[i] = struct{}{} 319 } 320 arr := make([]int, 0, len(generated)) 321 for k := range generated { 322 arr = append(arr, k) 323 } 324 return arr 325 } 326 327 // GetAllTips returns all the tips in TxPool. 328 func (pool *TxPool) GetAllTips() map[ogTypes.HashKey]types.Txi { 329 pool.mu.RLock() 330 defer pool.mu.RUnlock() 331 332 return pool.storage.getTipsInMap() 333 } 334 335 //// AddLocalTx adds a tx to txpool if it is valid, note that if success it returns nil. 336 //// AddLocalTx only process tx that sent by local node. 337 //func (pool *TxPool) AddLocalTx(tx types.Txi, noFeedBack bool) error { 338 // return pool.addTx(tx, TxTypeLocal, noFeedBack) 339 //} 340 // 341 //// AddLocalTxs adds a list of txs to txpool if they are valid. It returns 342 //// the process result of each tx with an error list. AddLocalTxs only process 343 //// txs that sent by local node. 344 //func (pool *TxPool) AddLocalTxs(txs []types.Txi, noFeedBack bool) []error { 345 // result := make([]error, len(txs)) 346 // for _, tx := range txs { 347 // result = append(result, pool.addTx(tx, TxTypeLocal, noFeedBack)) 348 // } 349 // return result 350 //} 351 // 352 //// AddRemoteTx adds a tx to txpool if it is valid. AddRemoteTx only process tx 353 //// sent by remote nodes, and will hold extra functions to prevent from ddos 354 //// (large amount of invalid tx sent from one node in a short time) attack. 355 //func (pool *TxPool) AddRemoteTx(tx types.Txi, noFeedBack bool) error { 356 // return pool.addTx(tx, TxTypeRemote, noFeedBack) 357 //} 358 // 359 //// AddRemoteTxs works as same as AddRemoteTx but processes a list of txs 360 //func (pool *TxPool) AddRemoteTxs(txs []types.Txi, noFeedBack bool) []error { 361 // result := make([]error, len(txs)) 362 // for _, tx := range txs { 363 // result = append(result, pool.addTx(tx, TxTypeRemote, noFeedBack)) 364 // } 365 // return result 366 //} 367 368 // Remove totally removes a tx from pool, it checks badtxs, tips, 369 // pendings and txlookup. 370 func (pool *TxPool) Remove(tx types.Txi, removeType hashOrderRemoveType) { 371 pool.mu.Lock() 372 defer pool.mu.Unlock() 373 374 pool.remove(tx, removeType) 375 } 376 377 func (pool *TxPool) remove(tx types.Txi, removeType hashOrderRemoveType) { 378 pool.storage.remove(tx, removeType) 379 } 380 381 // ClearAll removes all the txs in the pool. 382 // 383 // Note that ClearAll should only be called when solving conflicts 384 // during a sequencer confirmation time. 385 func (pool *TxPool) ClearAll() { 386 pool.mu.Lock() 387 defer pool.mu.Unlock() 388 389 pool.clearAll() 390 } 391 392 func (pool *TxPool) clearAll() { 393 pool.storage.removeAll() 394 } 395 396 //func (pool *TxPool) loop() { 397 // defer log.Tracef("TxPool.loop() terminates") 398 // 399 // //pool.wg.Add(1) 400 // //defer pool.wg.Done() 401 // 402 // //resetTimer := time.NewTicker(time.Duration(pool.conf.ResetDuration) * time.Second) 403 // 404 // for { 405 // select { 406 // case <-pool.close: 407 // log.Info("pool got quit signal quiting...") 408 // return 409 // 410 // case txEvent := <-pool.queue: 411 // log.WithField("tx", txEvent.txEnv.tx).Trace("get tx from queue") 412 // 413 // var err error 414 // tx := txEvent.txEnv.tx 415 // // check if tx is duplicate 416 // txStatus := pool.getStatus(tx.GetTxHash()) 417 // if txStatus == TxStatusNotExist { 418 // log.WithField("tx", tx).Warn("tx not exists") 419 // txEvent.callbackChan <- types.ErrTxNotExist 420 // continue 421 // } 422 // if txStatus != TxStatusQueue { 423 // log.WithField("tx", tx).Warn("Duplicate tx found in txlookup") 424 // txEvent.callbackChan <- types.ErrDuplicateTx 425 // continue 426 // } 427 // 428 // pool.mu.Lock() 429 // 430 // switch tx := tx.(type) { 431 // case *types.Sequencer: 432 // err = pool.preConfirm(tx) 433 // if err != nil { 434 // break 435 // } 436 // maxWeight := atomic.LoadUint64(&pool.maxWeight) 437 // if maxWeight < tx.GetWeight() { 438 // atomic.StoreUint64(&pool.maxWeight, tx.GetWeight()) 439 // } 440 // default: 441 // err = pool.commit(tx) 442 // if err != nil { 443 // break 444 // } 445 // maxWeight := atomic.LoadUint64(&pool.maxWeight) 446 // if maxWeight < tx.GetWeight() { 447 // atomic.StoreUint64(&pool.maxWeight, tx.GetWeight()) 448 // } 449 // tx.GetBase().Height = pool.dag.LatestSequencer().Height + 1 //temporary height ,will be re write after confirm 450 // } 451 // 452 // pool.mu.Unlock() 453 // 454 // txEvent.callbackChan <- err 455 // } 456 // } 457 //} 458 // 459 //// addMember adds tx to the pool queue and wait to become tip after validation. 460 //func (pool *TxPool) addTx(tx types.Txi, senderType TxType, noFeedBack bool) error { 461 // log.WithField("noFeedBack", noFeedBack).WithField("tx", tx).Tracef("start addMember, tx parents: %v", tx.Parents()) 462 // 463 // // check if tx is duplicate 464 // if pool.get(tx.GetTxHash()) != nil { 465 // log.WithField("tx", tx).Warn("Duplicate tx found in txpool") 466 // return fmt.Errorf("duplicate tx found in txpool: %s", tx.GetTxHash().Hex()) 467 // } 468 // 469 // //if normalTx, ok := tx.(*tx_types.Tx); ok { 470 // // normalTx.Setconfirm() 471 // // pool.confirmStatus.AddTxNum() 472 // //} 473 // 474 // te := &txEvent{ 475 // callbackChan: make(chan error), 476 // txEnv: newTxEnvelope(senderType, TxStatusQueue, tx, 1), 477 // } 478 // pool.storage.addTxEnv(te.txEnv) 479 // pool.queue <- te 480 // 481 // // waiting for callback 482 // select { 483 // case err := <-te.callbackChan: 484 // if err != nil { 485 // pool.remove(tx, removeFromEnd) 486 // return err 487 // } 488 // 489 // } 490 // // notify all subscribers of newTxEvent 491 // for name, subscriber := range pool.onNewTxReceived { 492 // log.WithField("tx", tx).Trace("notify subscriber: ", name) 493 // if !noFeedBack || name.allMsg { 494 // subscriber <- tx 495 // } 496 // } 497 // log.WithField("tx", tx).Trace("successfully added tx to txPool") 498 // return nil 499 //} 500 501 // commit commits tx to tips pool. commit() checks if this tx is bad tx and moves 502 // bad tx to badtx list other than tips list. If this tx proves any txs in the 503 // tip pool, those tips will be removed from tips but stored in pending. 504 func (pool *TxPool) commit(tx types.Txi) error { 505 log.WithField("tx", tx).Trace("start commit tx") 506 507 // check tx's quality. 508 txquality := pool.isBadTx(tx) 509 if txquality == TxQualityIsFatal { 510 pool.remove(tx, removeFromEnd) 511 tx.SetInValid(true) 512 log.WithField("tx ", tx).Debug("set invalid ") 513 return fmt.Errorf("tx is surely incorrect to commit, hash: %s", tx.GetTxHash()) 514 } 515 if txquality == TxQualityIsBad { 516 log.Tracef("bad tx: %s", tx) 517 pool.storage.switchTxStatus(tx.GetTxHash(), TxStatusBadTx) 518 return nil 519 } 520 521 // move parents to pending 522 for _, pHash := range tx.Parents() { 523 status := pool.getStatus(pHash) 524 if status != TxStatusTip { 525 log.WithField("parent", pHash).WithField("tx", tx). 526 Tracef("parent is not a tip") 527 continue 528 } 529 parent := pool.get(pHash) 530 if parent == nil { 531 log.WithField("parent", pHash).WithField("tx", tx). 532 Warn("parent status is tip but can not find in tips") 533 continue 534 } 535 536 // move parent to pending 537 pool.storage.switchTxStatus(parent.GetTxHash(), TxStatusPending) 538 } 539 540 pool.storage.flowProcess(tx) 541 pool.storage.switchTxStatus(tx.GetTxHash(), TxStatusTip) 542 543 // TODO delete this line later. 544 if log.GetLevel() >= log.TraceLevel { 545 log.WithField("tx", tx).WithField("status", pool.getStatus(tx.GetTxHash())).Tracef("finished commit tx") 546 } 547 return nil 548 } 549 550 type TxQuality uint8 551 552 const ( 553 TxQualityIsBad TxQuality = iota 554 TxQualityIsGood 555 TxQualityIsFatal 556 TxQualityIgnore 557 ) 558 559 func (pool *TxPool) isBadTx(tx types.Txi) TxQuality { 560 // check if the tx's parents exists and if is badtx 561 for _, parentHash := range tx.Parents() { 562 // check if tx in pool 563 if pool.get(parentHash) != nil { 564 if pool.getStatus(parentHash) == TxStatusBadTx { 565 log.WithField("tx", tx).Tracef("bad tx, parent %s is bad tx", parentHash) 566 return TxQualityIsBad 567 } 568 continue 569 } 570 // check if tx in dag 571 if pool.dag.GetConfirmedTx(parentHash) == nil { 572 log.WithField("tx", tx).Tracef("fatal tx, parent %s is not exist", parentHash) 573 return TxQualityIsFatal 574 } 575 } 576 577 if tx.GetType() == types.TxBaseTypeArchive { 578 return TxQualityIsGood 579 } 580 581 // check if nonce is duplicate 582 txinpool := pool.storage.getTxByNonce(tx.Sender(), tx.GetNonce()) 583 if txinpool != nil { 584 if txinpool.GetTxHash() == tx.GetTxHash() { 585 log.WithField("tx", tx).Error("duplicated tx in pool. Why received many times") 586 return TxQualityIsFatal 587 } 588 log.WithField("tx", tx).WithField("existing", txinpool).Trace("bad tx, duplicate nonce found in pool") 589 return TxQualityIsBad 590 } 591 txindag := pool.dag.GetTxByNonce(pool.dag.ConfirmedSequencerHash(), tx.Sender(), tx.GetNonce()) 592 if txindag != nil { 593 if txindag.GetTxHash() == tx.GetTxHash() { 594 log.WithField("tx", tx).Error("duplicated tx in dag. Why received many times") 595 } 596 log.WithField("tx", tx).WithField("existing", txindag).Trace("bad tx, duplicate nonce found in dag") 597 return TxQualityIsFatal 598 } 599 600 latestNonce, err := pool.storage.getLatestNonce(tx.Sender()) 601 if err != nil { 602 latestNonce, err = pool.dag.GetLatestNonce(pool.dag.ConfirmedSequencerHash(), tx.Sender()) 603 if err != nil { 604 log.Errorf("get latest nonce err: %v", err) 605 return TxQualityIsFatal 606 } 607 } 608 if tx.GetNonce() != latestNonce+1 { 609 log.WithField("should be ", latestNonce+1).WithField("tx", tx).Error("nonce err") 610 return TxQualityIsFatal 611 } 612 613 switch tx := tx.(type) { 614 case *types.Tx: 615 quality := pool.storage.tryProcessTx(tx) 616 if quality != TxQualityIsGood { 617 return quality 618 } 619 case *types.ActionTx: 620 if tx.Action == types.ActionTxActionIPO { 621 //actionData := tx.ActionData.(*tx_types.InitialOffering) 622 //actionData.TokenId = pool.dag.GetLatestTokenId() 623 } 624 if tx.Action == types.ActionTxActionSPO { 625 actionData := tx.ActionData.(*types.SecondaryOffering) 626 if actionData.TokenId == 0 { 627 log.WithField("tx ", tx).Warn("og token is disabled for publishing") 628 return TxQualityIsFatal 629 } 630 token := pool.dag.GetToken(pool.dag.LatestSequencerHash(), actionData.TokenId) 631 if token == nil { 632 log.WithField("tx ", tx).Warn("token not found") 633 return TxQualityIsFatal 634 } 635 if !token.ReIssuable { 636 log.WithField("tx ", tx).Warn("token is disabled for second publishing") 637 return TxQualityIsFatal 638 } 639 if token.Destroyed { 640 log.WithField("tx ", tx).Warn("token is destroyed already") 641 return TxQualityIsFatal 642 } 643 if token.Issuer != tx.Sender() { 644 log.WithField("token ", token).WithField("you address", tx.Sender()).Warn("you have no authority to second publishing for this token") 645 return TxQualityIsFatal 646 } 647 } 648 if tx.Action == types.ActionTxActionDestroy { 649 actionData := tx.ActionData.(*types.DestroyOffering) 650 if actionData.TokenId == 0 { 651 log.WithField("tx ", tx).Warn("og token is disabled for withdraw") 652 return TxQualityIsFatal 653 } 654 token := pool.dag.GetToken(pool.dag.LatestSequencerHash(), actionData.TokenId) 655 if token == nil { 656 log.WithField("tx ", tx).Warn("token not found") 657 return TxQualityIsFatal 658 } 659 if token.Destroyed { 660 log.WithField("tx ", tx).Warn("token is destroyed already") 661 return TxQualityIsFatal 662 } 663 if token.Issuer != tx.Sender() { 664 log.WithField("tx ", tx).WithField("token ", token).WithField("you address", tx.Sender()).Warn("you have no authority to second publishing for this token") 665 return TxQualityIsFatal 666 } 667 } 668 default: 669 // TODO 670 } 671 672 return TxQualityIsGood 673 } 674 675 //func (pool *TxPool) processSequencer(seq *types.Sequencer) error { 676 // if err := pool.isBadSeq(seq); err != nil { 677 // return err 678 // } 679 // 680 // confirmSeqHash := seq.GetConfirmSeqHash() 681 // cBatch := pool.cachedBatches.getConfirmBatch(confirmSeqHash) 682 // if cBatch == nil { 683 // return fmt.Errorf("can't find ") 684 // } 685 // 686 // return nil 687 //} 688 689 func (pool *TxPool) PreConfirm(seq *types.Sequencer) ([]types.Txi, error) { 690 pool.mu.Lock() 691 defer pool.mu.Unlock() 692 693 return pool.preConfirm(seq) 694 } 695 696 // preConfirm try to confirm sequencer and store the related data into pool.cachedSets. 697 // Once a sequencer is hardly confirmed after 3 later preConfirms, the function confirm() 698 // will be dialed. 699 func (pool *TxPool) preConfirm(seq *types.Sequencer) ([]types.Txi, error) { 700 if seq.GetHeight() <= pool.dag.latestSequencer.GetHeight() { 701 return nil, fmt.Errorf("the height of seq to pre-confirm is lower than "+ 702 "the latest seq in dag. get height: %d, latest: %d", seq.GetHeight(), pool.dag.latestSequencer.GetHeight()) 703 } 704 705 err := pool.isBadSeq(seq) 706 if err != nil { 707 return nil, err 708 } 709 _, eldersMap, err := pool.seekElders(seq) 710 if err != nil { 711 return nil, err 712 } 713 accountDetailSet := newAccountDetailSet(seq, pool.dag) 714 err = accountDetailSet.construct(eldersMap) 715 if err != nil { 716 return nil, err 717 } 718 err = accountDetailSet.isValid(pool.dag) 719 if err != nil { 720 return nil, err 721 } 722 err = pool.cachedSets.addSet(accountDetailSet) 723 if err != nil { 724 return nil, err 725 } 726 727 pool.storage.switchTxStatus(seq.GetTxHash(), TxStatusSeqPreConfirm) 728 return accountDetailSet.eldersList, nil 729 } 730 731 func (pool *TxPool) Confirm(seqHash ogTypes.Hash) error { 732 pool.mu.Lock() 733 defer pool.mu.Unlock() 734 735 return pool.confirm(seqHash) 736 } 737 738 // confirm pushes a batch of txs that confirmed by a sequencer to the dag. 739 func (pool *TxPool) confirm(seqHash ogTypes.Hash) error { 740 741 accSet := pool.cachedSets.getSet(seqHash) 742 743 // push pushBatch to dag 744 pushBatch := &PushBatch{ 745 Seq: accSet.seq, 746 Txs: accSet.eldersList, 747 } 748 if err := pool.dag.Push(pushBatch); err != nil { 749 log.WithField("error", err).Errorf("dag Push error: %v", err) 750 return err 751 } 752 753 // solve conflicts of txs in pool 754 pool.solveConflicts(accSet) 755 756 // notification 757 for _, c := range pool.OnBatchConfirmed { 758 if status.NodeStopped { 759 break 760 } 761 c <- accSet.eldersMap 762 } 763 for _, c := range pool.OnNewLatestSequencer { 764 if status.NodeStopped { 765 break 766 } 767 c <- true 768 } 769 770 log.WithField("seq height", accSet.seq.Height).WithField("seq", accSet.seq).Trace("finished confirm seq") 771 return nil 772 } 773 774 // isBadSeq checks if a sequencer is correct. 775 func (pool *TxPool) isBadSeq(seq *types.Sequencer) error { 776 // check if the nonce is duplicate 777 seqindag := pool.dag.GetTxByNonce(seq.GetConfirmSeqHash(), seq.Sender(), seq.GetNonce()) 778 if seqindag != nil { 779 return fmt.Errorf("bad seq,duplicate nonce %d found in dag, existing %s ", seq.GetNonce(), seqindag) 780 } 781 782 if pool.dag.LatestSequencer().Height+1 != seq.Height { 783 return fmt.Errorf("bad seq hieght mismatch height %d old_height %d", seq.Height, pool.dag.latestSequencer.Height) 784 } 785 return nil 786 } 787 788 func (pool *TxPool) IsBadSeq(seq *types.Sequencer) error { 789 // check if the nonce is duplicate 790 pool.mu.RLock() 791 defer pool.mu.RUnlock() 792 793 return pool.isBadSeq(seq) 794 } 795 796 func (pool *TxPool) SeekElders(seq *types.Sequencer) ([]types.Txi, map[ogTypes.HashKey]types.Txi, error) { 797 pool.mu.RLock() 798 defer pool.mu.RUnlock() 799 800 return pool.seekElders(seq) 801 } 802 803 // seekElders finds all the unconfirmed elders of baseTx. 804 func (pool *TxPool) seekElders(seq *types.Sequencer) ([]types.Txi, map[ogTypes.HashKey]types.Txi, error) { 805 eldersList := make([]types.Txi, 0) 806 eldersMap := make(map[ogTypes.HashKey]types.Txi) 807 808 inSeekingPool := map[ogTypes.HashKey]int{} 809 var seekingPool []ogTypes.Hash 810 for _, parentHash := range seq.Parents() { 811 seekingPool = append(seekingPool, parentHash) 812 } 813 for len(seekingPool) > 0 { 814 elderHash := seekingPool[0] 815 seekingPool = seekingPool[1:] 816 817 elder := pool.get(elderHash) 818 if elder == nil { 819 // check if elder has been preConfirmed or confirmed. 820 if pool.dag.ExistTx(seq.GetParentSeqHash(), elderHash) { 821 continue 822 } 823 return nil, nil, fmt.Errorf("can't find elder %s", elderHash) 824 } 825 826 if eldersMap[elder.GetTxHash().HashKey()] == nil { 827 eldersList = append(eldersList, elder) 828 eldersMap[elder.GetTxHash().HashKey()] = elder 829 } 830 for _, elderParentHash := range elder.Parents() { 831 if _, in := inSeekingPool[elderParentHash.HashKey()]; !in { 832 seekingPool = append(seekingPool, elderParentHash) 833 inSeekingPool[elderParentHash.HashKey()] = 0 834 } 835 } 836 } 837 return eldersList, eldersMap, nil 838 } 839 840 // solveConflicts remove elders from txpool and reprocess 841 // all txs in the pool in order to make sure all txs are 842 // correct after seq confirmation. 843 func (pool *TxPool) solveConflicts(accSet *accDetailSet) { 844 // TODO check if there is any bugs here 845 txToRejudge := pool.storage.switchToConfirmBatch(accSet) 846 for _, txEnv := range txToRejudge { 847 if txEnv.judgeNum >= PoolRejudgeThreshold { 848 log.WithField("txEnvelope", txEnv.String()).Infof("exceed rejudge time, throw away") 849 continue 850 } 851 852 log.WithField("txEnvelope", txEnv).Tracef("start rejudge") 853 txEnv.txType = TxTypeRejudge 854 txEnv.status = TxStatusQueue 855 txEnv.judgeNum += 1 856 pool.storage.addTxEnv(txEnv) 857 e := pool.commit(txEnv.tx) 858 if e != nil { 859 log.WithField("txEnvelope ", txEnv).WithError(e).Debug("rejudge error") 860 } 861 } 862 } 863 864 type Ledger interface { 865 LatestSequencerHash() ogTypes.Hash 866 ConfirmedSequencerHash() ogTypes.Hash 867 GetBalance(baseSeqHash ogTypes.Hash, addr ogTypes.Address, tokenID int32) *math.BigInt 868 GetLatestNonce(baseSeqHash ogTypes.Hash, addr ogTypes.Address) (uint64, error) 869 } 870 871 type cachedAccDetailSets struct { 872 heights []uint64 873 sets map[uint64][]*accDetailSet 874 setsMap map[ogTypes.HashKey]*accDetailSet 875 } 876 877 func newCachedAccDetailSets() *cachedAccDetailSets { 878 return &cachedAccDetailSets{ 879 heights: make([]uint64, 0), 880 sets: make(map[uint64][]*accDetailSet), 881 setsMap: make(map[ogTypes.HashKey]*accDetailSet), 882 } 883 } 884 885 func (ca *cachedAccDetailSets) getSet(seqHash ogTypes.Hash) *accDetailSet { 886 return ca.setsMap[seqHash.HashKey()] 887 } 888 889 func (ca *cachedAccDetailSets) addSet(as *accDetailSet) error { 890 height := as.seq.GetHeight() 891 if len(ca.heights) == 0 { 892 return ca.addSetHelper(as) 893 } 894 if height < ca.heights[0] { 895 return fmt.Errorf("height incorrect, should no less than minimun %d", ca.heights[0]) 896 } 897 return ca.addSetHelper(as) 898 } 899 900 func (ca *cachedAccDetailSets) addSetHelper(as *accDetailSet) error { 901 height := as.seq.GetHeight() 902 if len(ca.heights) == 0 || height == ca.heights[len(ca.heights)-1]+1 { 903 ca.heights = append(ca.heights, height) 904 ca.sets[height] = make([]*accDetailSet, 0) 905 } 906 907 arr, exists := ca.sets[height] 908 if !exists { 909 return fmt.Errorf("height not exists: %d, current highest: %d", height, ca.heights[len(ca.heights)-1]) 910 } 911 arr = append(arr, as) 912 913 ca.sets[height] = arr 914 ca.setsMap[as.seq.GetTxHash().HashKey()] = as 915 return nil 916 } 917 918 func (ca *cachedAccDetailSets) confirmSet(seqHash ogTypes.Hash) error { 919 as, exists := ca.setsMap[seqHash.HashKey()] 920 if !exists { 921 return fmt.Errorf("can't find cached detailSet: %s", seqHash.HashKey()) 922 } 923 924 //height := as.seq.GetHeight() 925 var breakIndex int 926 for i, height := range ca.heights { 927 if height >= as.seq.GetHeight() { 928 breakIndex = i 929 break 930 } 931 arr := ca.sets[height] 932 for _, accSet := range arr { 933 delete(ca.setsMap, accSet.seq.GetTxHash().HashKey()) 934 } 935 delete(ca.sets, height) 936 } 937 ca.heights = ca.heights[breakIndex:] 938 return nil 939 } 940 941 type accDetailSet struct { 942 seq *types.Sequencer 943 eldersList []types.Txi 944 eldersMap map[ogTypes.HashKey]types.Txi 945 ledger Ledger 946 details map[ogTypes.AddressKey]*accountDetail 947 } 948 949 func newAccountDetailSet(seq *types.Sequencer, ledger Ledger) *accDetailSet { 950 return &accDetailSet{ 951 seq: seq, 952 eldersList: make([]types.Txi, 0), 953 eldersMap: make(map[ogTypes.HashKey]types.Txi), 954 ledger: ledger, 955 details: make(map[ogTypes.AddressKey]*accountDetail), 956 } 957 } 958 959 func (as *accDetailSet) construct(elders map[ogTypes.HashKey]types.Txi) error { 960 for _, txi := range elders { 961 // return error if a sequencer confirm a tx that has same nonce as itself. 962 if txi.Sender() == as.seq.Sender() && txi.GetNonce() == as.seq.GetNonce() { 963 return fmt.Errorf("seq's nonce is the same as a tx it confirmed, nonce: %d, tx hash: %s", 964 as.seq.GetNonce(), txi.GetTxHash()) 965 } 966 967 switch tx := txi.(type) { 968 case *types.Sequencer: 969 break 970 //case *types.Tx: 971 default: 972 as.processTx(tx) 973 } 974 } 975 return nil 976 } 977 978 func (as *accDetailSet) processTx(tx types.Txi) { 979 switch tx := tx.(type) { 980 case *types.Tx: 981 detailCost := as.getOrCreateDetail(tx.From) 982 detailCost.addCost(as.ledger, as.seq.GetParentSeqHash(), tx.TokenId, tx.Value) 983 detailCost.addTx(tx) 984 as.setDetail(detailCost) 985 986 detailEarn := as.getOrCreateDetail(tx.To) 987 detailEarn.addEarn(as.ledger, as.seq.GetParentSeqHash(), tx.TokenId, tx.Value) 988 as.setDetail(detailEarn) 989 default: 990 detailSender := as.getOrCreateDetail(tx.Sender()) 991 detailSender.addTx(tx) 992 } 993 as.eldersList = append(as.eldersList, tx) 994 as.eldersMap[tx.GetTxHash().HashKey()] = tx 995 } 996 997 func (as *accDetailSet) isValid(ledger Ledger) error { 998 // verify balance and nonce 999 for _, accountDetail := range as.getDetails() { 1000 err := accountDetail.isValid(ledger, as.seq.GetParentSeqHash(), as.seq) 1001 if err != nil { 1002 return err 1003 } 1004 } 1005 return nil 1006 } 1007 1008 func (as *accDetailSet) getDetail(addr ogTypes.Address) *accountDetail { 1009 return as.details[addr.AddressKey()] 1010 } 1011 1012 func (as *accDetailSet) getDetails() map[ogTypes.AddressKey]*accountDetail { 1013 return as.details 1014 } 1015 1016 func (as *accDetailSet) createDetail(addr ogTypes.Address) *accountDetail { 1017 as.details[addr.AddressKey()] = newAccountDetail(addr) 1018 return as.details[addr.AddressKey()] 1019 } 1020 1021 func (as *accDetailSet) setDetail(detail *accountDetail) { 1022 as.details[detail.address.AddressKey()] = detail 1023 } 1024 1025 func (as *accDetailSet) getOrCreateDetail(addr ogTypes.Address) *accountDetail { 1026 detailCost := as.getDetail(addr) 1027 if detailCost == nil { 1028 detailCost = as.createDetail(addr) 1029 } 1030 return detailCost 1031 } 1032 1033 func (as *accDetailSet) existTx(hash ogTypes.Hash) bool { 1034 _, exist := as.eldersMap[hash.HashKey()] 1035 return exist 1036 } 1037 1038 func (as *accDetailSet) existSeq(hash ogTypes.Hash) bool { 1039 txi, exist := as.eldersMap[hash.HashKey()] 1040 if !exist { 1041 return false 1042 } 1043 if txi.GetType() != types.TxBaseTypeSequencer { 1044 return false 1045 } 1046 return true 1047 } 1048 1049 // accountDetail describes all the db of a specific address within a 1050 // sequencer confirmation term. 1051 // 1052 // - txList - represents the txs sent by this addrs, ordered by nonce. 1053 // - earn - the amount this address have earned. 1054 // - cost - the amount this address should spent out. 1055 // - resultBalance - balance of this address after the batch is confirmed. 1056 type accountDetail struct { 1057 //ledger LedgerEngine 1058 1059 address ogTypes.Address 1060 txList *TxList 1061 earn map[int32]*math.BigInt 1062 cost map[int32]*math.BigInt 1063 resultBalance map[int32]*math.BigInt 1064 } 1065 1066 func newAccountDetail(addr ogTypes.Address) *accountDetail { 1067 bd := &accountDetail{ 1068 //ledger: ledger, 1069 address: addr, 1070 txList: NewTxList(), 1071 earn: make(map[int32]*math.BigInt), 1072 cost: make(map[int32]*math.BigInt), 1073 resultBalance: make(map[int32]*math.BigInt), 1074 } 1075 return bd 1076 } 1077 1078 func (bd *accountDetail) getBalance(tokenID int32) *math.BigInt { 1079 return bd.resultBalance[tokenID] 1080 } 1081 1082 func (bd *accountDetail) getNonce() (uint64, error) { 1083 if bd.txList == nil { 1084 return 0, fmt.Errorf("txlist is nil") 1085 } 1086 if !(bd.txList.Len() > 0) { 1087 return 0, fmt.Errorf("txlist is empty") 1088 } 1089 return bd.txList.keys.Tail(), nil 1090 } 1091 1092 func (bd *accountDetail) existTx(tx types.Txi) bool { 1093 return bd.txList.Get(tx.GetNonce()) != nil 1094 } 1095 1096 func (bd *accountDetail) addTx(tx types.Txi) { 1097 bd.txList.Put(tx) 1098 } 1099 1100 func (bd *accountDetail) addCost(ledger Ledger, baseHash ogTypes.Hash, tokenID int32, amount *math.BigInt) { 1101 v, ok := bd.cost[tokenID] 1102 if !ok { 1103 v = math.NewBigInt(0) 1104 } 1105 bd.cost[tokenID] = v.Add(amount) 1106 1107 blc, ok := bd.resultBalance[tokenID] 1108 if !ok { 1109 blc = ledger.GetBalance(baseHash, bd.address, tokenID) 1110 } 1111 bd.resultBalance[tokenID] = blc.Sub(amount) 1112 } 1113 1114 func (bd *accountDetail) addEarn(ledger Ledger, baseHash ogTypes.Hash, tokenID int32, amount *math.BigInt) { 1115 v, ok := bd.earn[tokenID] 1116 if !ok { 1117 v = math.NewBigInt(0) 1118 } 1119 bd.earn[tokenID] = v.Add(amount) 1120 1121 blc, ok := bd.resultBalance[tokenID] 1122 if !ok { 1123 blc = ledger.GetBalance(baseHash, bd.address, tokenID) 1124 } 1125 bd.resultBalance[tokenID] = blc.Add(amount) 1126 } 1127 1128 func (bd *accountDetail) isValid(ledger Ledger, baseHash ogTypes.Hash, seq *types.Sequencer) error { 1129 // check balance 1130 // for every token, if balance < cost, verify failed 1131 for tokenID, cost := range bd.cost { 1132 confirmedBalance := ledger.GetBalance(baseHash, bd.address, tokenID) 1133 if confirmedBalance.Value.Cmp(cost.Value) < 0 { 1134 return fmt.Errorf("the balance of addr %s is not enough", bd.address.AddressString()) 1135 } 1136 } 1137 1138 // check nonce order 1139 nonces := bd.txList.keys 1140 if !(nonces.Len() > 0) { 1141 return nil 1142 } 1143 if nErr := bd.verifyNonce(ledger, baseHash, seq, *nonces); nErr != nil { 1144 return nErr 1145 } 1146 return nil 1147 } 1148 1149 func (bd *accountDetail) verifyNonce(ledger Ledger, baseHash ogTypes.Hash, seq *types.Sequencer, nonces nonceHeap) error { 1150 sort.Sort(nonces) 1151 addr := bd.address 1152 1153 latestNonce, err := ledger.GetLatestNonce(baseHash, bd.address) 1154 if err != nil { 1155 return fmt.Errorf("get latest nonce err: %v", err) 1156 } 1157 if nonces[0] != latestNonce+1 { 1158 return fmt.Errorf("nonce %d is not the next one of latest nonce %d, addr: %s", nonces[0], latestNonce, addr.AddressString()) 1159 } 1160 for i := 1; i < nonces.Len(); i++ { 1161 if nonces[i] != nonces[i-1]+1 { 1162 return fmt.Errorf("nonce order mismatch, addr: %s, preNonce: %d, curNonce: %d", addr.AddressString(), nonces[i-1], nonces[i]) 1163 } 1164 } 1165 if seq.Sender().Hex() == addr.Hex() { 1166 if seq.GetNonce() != nonces[len(nonces)-1]+1 { 1167 return fmt.Errorf("seq's nonce is not the next nonce of confirm list, seq nonce: %d, latest nonce in confirm list: %d", seq.GetNonce(), nonces[len(nonces)-1]) 1168 } 1169 } 1170 return nil 1171 }