github.com/annchain/OG@v0.0.9/og/syncer/sync_buffer.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 syncer
    15  
    16  import (
    17  	"errors"
    18  	"fmt"
    19  	types2 "github.com/annchain/OG/arefactor/og/types"
    20  	"github.com/annchain/OG/og/types"
    21  	"github.com/annchain/OG/ogcore/pool"
    22  
    23  	"github.com/annchain/OG/protocol"
    24  	"github.com/sirupsen/logrus"
    25  	"sync"
    26  	"sync/atomic"
    27  
    28  	"github.com/annchain/OG/og"
    29  )
    30  
    31  var MaxBufferSiza = 4096 * 16
    32  
    33  type SyncBuffer struct {
    34  	Txs        map[types2.Hash]types.Txi
    35  	TxsList    types2.Hashes
    36  	Seq        *types.Sequencer
    37  	mu         sync.RWMutex
    38  	txPool     pool.ITxPool
    39  	dag        og.IDag
    40  	acceptTxs  uint32
    41  	quitHandel bool
    42  	Verifiers  []protocol.Verifier
    43  }
    44  
    45  type SyncBufferConfig struct {
    46  	TxPool    pool.ITxPool
    47  	Verifiers []protocol.Verifier
    48  	Dag       og.IDag
    49  }
    50  
    51  func DefaultSyncBufferConfig(txPool pool.ITxPool, dag og.IDag, Verifiers []protocol.Verifier) SyncBufferConfig {
    52  	config := SyncBufferConfig{
    53  		TxPool:    txPool,
    54  		Dag:       dag,
    55  		Verifiers: Verifiers,
    56  	}
    57  	return config
    58  }
    59  
    60  func (s *SyncBuffer) Name() string {
    61  	return "SyncBuffer"
    62  }
    63  
    64  func NewSyncBuffer(config SyncBufferConfig) *SyncBuffer {
    65  	s := &SyncBuffer{
    66  		Txs:       make(map[types2.Hash]types.Txi),
    67  		txPool:    config.TxPool,
    68  		dag:       config.Dag,
    69  		Verifiers: config.Verifiers,
    70  	}
    71  	return s
    72  }
    73  
    74  func (s *SyncBuffer) Start() {
    75  	log.Info("Syncbuffer started")
    76  }
    77  
    78  func (s *SyncBuffer) Stop() {
    79  	log.Info("Syncbuffer will stop")
    80  	s.quitHandel = true
    81  }
    82  
    83  // range map is random value ,so store hashs using slice
    84  func (s *SyncBuffer) addTxs(txs types.Txis, seq *types.Sequencer) error {
    85  	s.mu.Lock()
    86  	defer s.mu.Unlock()
    87  	s.Seq = seq
    88  	for _, tx := range txs {
    89  		if len(s.Txs) > MaxBufferSiza {
    90  			return fmt.Errorf("too much txs")
    91  		}
    92  		if tx == nil {
    93  			log.Debug("nil tx")
    94  			continue
    95  		}
    96  		if _, ok := s.Txs[tx.GetHash()]; !ok {
    97  
    98  			s.Txs[tx.GetHash()] = tx
    99  		}
   100  		s.TxsList = append(s.TxsList, tx.GetHash())
   101  	}
   102  	return nil
   103  
   104  }
   105  
   106  func (s *SyncBuffer) AddTxs(seq *types.Sequencer, txs types.Txis) error {
   107  	if atomic.LoadUint32(&s.acceptTxs) == 0 {
   108  		atomic.StoreUint32(&s.acceptTxs, 1)
   109  		defer atomic.StoreUint32(&s.acceptTxs, 0)
   110  		s.clean()
   111  		if seq == nil {
   112  			err := fmt.Errorf("nil sequencer")
   113  			log.WithError(err).Debug("add txs error")
   114  			return err
   115  		}
   116  		if seq.Height != s.dag.LatestSequencer().Height+1 {
   117  			log.WithField("latests seq height ", s.dag.LatestSequencer().Height).WithField(
   118  				"seq height", seq.Height).Warn("id mismatch")
   119  			return nil
   120  		}
   121  		err := s.addTxs(txs, seq)
   122  		if err != nil {
   123  			log.WithError(err).Debug("add txs error")
   124  			return err
   125  		}
   126  		err = s.Handle()
   127  		if err != nil {
   128  			logrus.WithError(err).WithField("txs ", txs).WithField("seq ", seq).Warn("handle tx error")
   129  		}
   130  		return err
   131  
   132  	} else {
   133  		err := fmt.Errorf("addtx busy")
   134  		return err
   135  	}
   136  }
   137  
   138  func (s *SyncBuffer) Count() int {
   139  	s.mu.RLock()
   140  	defer s.mu.RUnlock()
   141  
   142  	return len(s.Txs)
   143  }
   144  
   145  func (s *SyncBuffer) Get(hash types2.Hash) types.Txi {
   146  	s.mu.RLock()
   147  	defer s.mu.RUnlock()
   148  	return s.Txs[hash]
   149  
   150  }
   151  
   152  func (s *SyncBuffer) GetAllKeys() types2.Hashes {
   153  	s.mu.RLock()
   154  	defer s.mu.RUnlock()
   155  	var keys types2.Hashes
   156  	for k := range s.Txs {
   157  		keys = append(keys, k)
   158  	}
   159  	return keys
   160  }
   161  
   162  func (s *SyncBuffer) clean() {
   163  	s.mu.Lock()
   164  	defer s.mu.Unlock()
   165  	for k := range s.Txs {
   166  		delete(s.Txs, k)
   167  	}
   168  	s.TxsList = nil
   169  }
   170  
   171  func (s *SyncBuffer) Handle() error {
   172  	if s.quitHandel {
   173  		return nil
   174  	}
   175  	count := s.Count()
   176  	log.WithField("txs len", count).WithField("seq", s.Seq).Trace("handle txs start")
   177  	err := s.verifyElders(s.Seq)
   178  	if err != nil {
   179  		log.WithField("txlist ", s.TxsList).WithField("seq ", s.Seq).WithError(err).Warn("handle fail")
   180  		return err
   181  	}
   182  	log.WithField("len ", len(s.Verifiers)).Debug("len sync buffer verifier")
   183  	for _, hash := range s.TxsList {
   184  		tx := s.Get(hash)
   185  		if tx == nil {
   186  			panic("never come here")
   187  		}
   188  		//if tx is already in txbool ,no need to verify again
   189  		if s.txPool.IsLocalHash(hash) {
   190  			continue
   191  		}
   192  		for _, verifier := range s.Verifiers {
   193  			if !verifier.Verify(tx) {
   194  				log.WithField("tx", tx).Warn("bad tx")
   195  				err = errors.New("bad tx format")
   196  				goto out
   197  			}
   198  		}
   199  		//need to feedback to buffer
   200  		err = s.txPool.AddRemoteTx(tx, false)
   201  		if err != nil {
   202  			//this transaction received by broadcast ,so don't return err
   203  			if err == types.ErrDuplicateTx {
   204  				err = nil
   205  				continue
   206  			} else {
   207  				goto out
   208  			}
   209  		}
   210  	}
   211  
   212  out:
   213  	if err == nil {
   214  		log.WithField("id", s.Seq).Trace("before add seq")
   215  		for _, verifier := range s.Verifiers {
   216  			if !verifier.Verify(s.Seq) {
   217  				log.WithField("tx", s.Seq).Warn("bad seq")
   218  				err = errors.New("bad seq format")
   219  			}
   220  		}
   221  		if err == nil {
   222  			err = s.txPool.AddRemoteTx(s.Seq, false)
   223  			log.WithField("id", s.Seq).Trace("after add seq")
   224  		}
   225  	}
   226  	if err != nil {
   227  		log.WithField("seq ", s.Seq).WithError(err).Warn("handel fail")
   228  		//panic("handle fail for test")
   229  	} else {
   230  		log.WithField("txs len", count).WithField("seq ", s.Seq).Debug("handle txs done")
   231  
   232  	}
   233  	return err
   234  }
   235  
   236  func (s *SyncBuffer) verifyElders(seq types.Txi) error {
   237  
   238  	allKeys := s.GetAllKeys()
   239  	keysMap := make(map[types2.Hash]int)
   240  	for _, k := range allKeys {
   241  		keysMap[k] = 1
   242  	}
   243  
   244  	inSeekingPool := map[types2.Hash]int{}
   245  	seekingPool := types2.Hashes{}
   246  	for _, parentHash := range seq.GetParents() {
   247  		seekingPool = append(seekingPool, parentHash)
   248  		// seekingPool.PushBack(parentHash)
   249  	}
   250  	for len(seekingPool) > 0 {
   251  		elderHash := seekingPool[0]
   252  		seekingPool = seekingPool[1:]
   253  		// elderHash := seekingPool.Remove(seekingPool.Front()).(common.Hash)
   254  
   255  		elder := s.Get(elderHash)
   256  		if elder == nil {
   257  			if s.txPool.IsLocalHash(elderHash) {
   258  				continue
   259  			}
   260  			err := fmt.Errorf("parent not found")
   261  			log.WithField("hash", elderHash.String()).Warn("parent not found")
   262  			return err
   263  		}
   264  		delete(keysMap, elderHash)
   265  		for _, elderParentHash := range elder.GetParents() {
   266  			if _, in := inSeekingPool[elderParentHash]; !in {
   267  				seekingPool = append(seekingPool, elderParentHash)
   268  				// seekingPool.PushBack(elderParentHash)
   269  				inSeekingPool[elderParentHash] = 0
   270  			}
   271  		}
   272  	}
   273  	if len(keysMap) != 0 {
   274  		err := fmt.Errorf("txs number mismatch,redundent txs  %d", len(allKeys))
   275  		return err
   276  	}
   277  	return nil
   278  }