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  }