github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/consense/dpoa/msgpool.go (about)

     1  package dpoa
     2  
     3  import (
     4  	"errors"
     5  	"sync"
     6  
     7  	"github.com/sixexorg/magnetic-ring/common"
     8  	"github.com/sixexorg/magnetic-ring/consense/dpoa/comm"
     9  	"github.com/sixexorg/magnetic-ring/log"
    10  )
    11  
    12  
    13  
    14  var errDropFarFutureMsg = errors.New("msg pool dropped msg for far future")
    15  
    16  type ConsensusRoundMsgs map[comm.MsgType][]comm.ConsensusMsg // indexed by MsgType (proposal, endorsement, ...)
    17  
    18  type ConsensusRound struct {
    19  	blockNum uint64
    20  	msgs     map[comm.MsgType][]interface{}
    21  	msgHashs map[common.Hash]interface{} // for msg-dup checking
    22  }
    23  
    24  func newConsensusRound(num uint64) *ConsensusRound {
    25  
    26  	r := &ConsensusRound{
    27  		blockNum: num,
    28  		msgs:     make(map[comm.MsgType][]interface{}),
    29  		msgHashs: make(map[common.Hash]interface{}),
    30  	}
    31  
    32  	r.msgs[comm.ConsensePrepare] = make([]interface{}, 0)
    33  	r.msgs[comm.ConsensePromise] = make([]interface{}, 0)
    34  	r.msgs[comm.ConsenseProposer] = make([]interface{}, 0)
    35  	r.msgs[comm.ConsenseAccept] = make([]interface{}, 0)
    36  	r.msgs[comm.EvilEvent] = make([]interface{}, 0)
    37  
    38  	return r
    39  }
    40  
    41  func (self *ConsensusRound) addMsg(msg comm.ConsensusMsg, msgHash common.Hash) error {
    42  	if _, present := self.msgHashs[msgHash]; present {
    43  		return nil
    44  	}
    45  
    46  	msgs := self.msgs[msg.Type()]
    47  	self.msgs[msg.Type()] = append(msgs, msg)
    48  	self.msgHashs[msgHash] = nil
    49  	return nil
    50  }
    51  
    52  func (self *ConsensusRound) hasMsg(msg comm.ConsensusMsg, msgHash common.Hash) (bool, error) {
    53  	if _, present := self.msgHashs[msgHash]; present {
    54  		return present, nil
    55  	}
    56  	return false, nil
    57  }
    58  
    59  type timeoutData struct {
    60  	tmSigs      map[string][]byte // pub sigs
    61  	established bool              //
    62  }
    63  
    64  type MsgPool struct {
    65  	lock        sync.RWMutex
    66  	cacheLen    uint64
    67  	rounds      map[uint64]*ConsensusRound         // indexed by BlockNum
    68  	earthSigs   map[common.Hash]map[string][]byte  // hash pub sigs
    69  	timeoutSigs map[uint64]map[uint32]*timeoutData // blknum view pub
    70  	msgHashs    map[common.Hash]interface{}        // for msg-dup checking
    71  }
    72  
    73  func newMsgPool(cacheLen uint64) *MsgPool {
    74  	// TODO
    75  	return &MsgPool{
    76  		lock:        sync.RWMutex{},
    77  		cacheLen:    cacheLen,
    78  		rounds:      make(map[uint64]*ConsensusRound),
    79  		msgHashs:    make(map[common.Hash]interface{}),
    80  		earthSigs:   make(map[common.Hash]map[string][]byte),
    81  		timeoutSigs: make(map[uint64]map[uint32]*timeoutData),
    82  	}
    83  }
    84  
    85  func (pool *MsgPool) clean() {
    86  	pool.lock.Lock()
    87  	defer pool.lock.Unlock()
    88  
    89  	pool.rounds = make(map[uint64]*ConsensusRound)
    90  }
    91  
    92  func (pool *MsgPool) MarkMsgs(msgHash common.Hash) {
    93  	pool.lock.Lock()
    94  	defer pool.lock.Unlock()
    95  	pool.msgHashs[msgHash] = nil
    96  }
    97  
    98  func (pool *MsgPool) CheckMsgs(msgHash common.Hash) bool {
    99  	pool.lock.RLock()
   100  	defer pool.lock.RUnlock()
   101  	if _, ok := pool.msgHashs[msgHash]; ok {
   102  		return true
   103  	}
   104  	return false
   105  }
   106  
   107  func (pool *MsgPool) AddMsg(msg comm.ConsensusMsg, msgHash common.Hash, argv ...interface{}) error {
   108  	pool.lock.Lock()
   109  	defer pool.lock.Unlock()
   110  
   111  	blkNum := msg.GetBlockNum()
   112  	//if blkNum > pool.server.GetCurrentBlockNo()+pool.cacheLen {
   113  	//	return errDropFarFutureMsg
   114  	//}
   115  
   116  	// TODO: limit #history rounds to cacheLen
   117  	// Note: we accept msg for future rounds
   118  	if msg.Type() == comm.EarthFetchRspSigs {
   119  		pMsg := msg.(*comm.EarthSigsFetchRspMsg)
   120  		if _, ok := pool.earthSigs[pMsg.BlkHash]; !ok {
   121  			pool.earthSigs[pMsg.BlkHash] = make(map[string][]byte)
   122  		}
   123  		pool.earthSigs[pMsg.BlkHash][pMsg.PubKey] = pMsg.Sigs
   124  		pool.msgHashs[msgHash] = nil
   125  		return nil
   126  	}
   127  
   128  	if msg.Type() == comm.ViewTimeout { // Msg type - []list(msglist)
   129  		var partiCfg *comm.ParticiConfig
   130  		if len(argv) == 1 {
   131  			partiCfg = argv[0].(*comm.ParticiConfig)
   132  		}
   133  		pMsg := msg.(*comm.ViewtimeoutMsg)
   134  		if _, ok := pool.timeoutSigs[blkNum]; !ok {
   135  			pool.timeoutSigs[blkNum] = make(map[uint32]*timeoutData)
   136  		}
   137  		if _, ok := pool.timeoutSigs[blkNum][pMsg.RawData.View]; !ok {
   138  			pool.timeoutSigs[blkNum][pMsg.RawData.View] = &timeoutData{tmSigs: make(map[string][]byte)}
   139  		}
   140  		//len(pool.server.dpoaMgr.partiCfg.obserNodes)
   141  		pool.timeoutSigs[blkNum][pMsg.RawData.View].tmSigs[pMsg.PubKey] = pMsg.Signature
   142  		if partiCfg.View == pMsg.RawData.View {
   143  			if len(pool.timeoutSigs[blkNum][pMsg.RawData.View].tmSigs[pMsg.PubKey]) > len(partiCfg.ObserNodes)/2 {
   144  				pool.timeoutSigs[blkNum][pMsg.RawData.View].established = true
   145  			}
   146  		}
   147  		pool.msgHashs[msgHash] = nil
   148  		return nil
   149  	}
   150  
   151  	if _, present := pool.rounds[blkNum]; !present {
   152  		pool.rounds[blkNum] = newConsensusRound(blkNum)
   153  	}
   154  
   155  	return pool.rounds[blkNum].addMsg(msg, msgHash)
   156  }
   157  
   158  func (pool *MsgPool) HasMsg(msg comm.ConsensusMsg, msgHash common.Hash) bool {
   159  	pool.lock.RLock()
   160  	defer pool.lock.RUnlock()
   161  
   162  	if roundMsgs, present := pool.rounds[msg.GetBlockNum()]; !present {
   163  		return false
   164  	} else {
   165  		if present, err := roundMsgs.hasMsg(msg, msgHash); err != nil {
   166  			log.Error("msgpool failed to check msg avail: %s", err)
   167  			return false
   168  		} else {
   169  			return present
   170  		}
   171  	}
   172  
   173  	return false
   174  }
   175  
   176  func (pool *MsgPool) Persist() error {
   177  	// TODO
   178  	return nil
   179  }
   180  
   181  func (pool *MsgPool) TimeoutCount(blocknum uint64) int {
   182  	pool.lock.RLock()
   183  	defer pool.lock.RUnlock()
   184  	//fmt.Println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!&&&&&&&&&&&&&^^^^^^^^^^^^TimeoutCount blocknum:", blocknum)
   185  	if _, ok := pool.timeoutSigs[blocknum]; !ok {
   186  		return 0
   187  	}
   188  
   189  	var count int = 0
   190  	for _, v := range pool.timeoutSigs[blocknum] { //view
   191  		if v.established {
   192  			/*for k1, _ := range v.tmSigs {
   193  				fmt.Println("!!!!!!!!!!!start&&&&&&&&&&&&&^^^^^^^^^^^^TimeoutCount blocknum:", "view", k, "pub", k1)
   194  			}*/
   195  			count++
   196  		}
   197  	}
   198  
   199  	//fmt.Println("&&&&&&&&&&&&&^^^^^^^^^^^^TimeoutCount blocknum:", blocknum, "count:", count)
   200  	return count
   201  }
   202  
   203  func (pool *MsgPool) GetTimeoutMsgs(blocknum uint64) map[uint32]*timeoutData {
   204  	pool.lock.RLock()
   205  	defer pool.lock.RUnlock()
   206  	if v, ok := pool.timeoutSigs[blocknum]; !ok {
   207  		return make(map[uint32]*timeoutData)
   208  	} else {
   209  		return v
   210  	}
   211  }
   212  
   213  func (pool *MsgPool) GetEvilMsgs(blocknum uint64) []interface{} {
   214  	pool.lock.RLock()
   215  	defer pool.lock.RUnlock()
   216  
   217  	roundMsgs, ok := pool.rounds[blocknum]
   218  	if !ok {
   219  		return nil
   220  	}
   221  	msgs, ok := roundMsgs.msgs[comm.EvilEvent]
   222  	if !ok {
   223  		return nil
   224  	}
   225  	return msgs
   226  }
   227  
   228  func (pool *MsgPool) GetEarthMsgs(prehash common.Hash) map[string][]byte {
   229  	pool.lock.RLock()
   230  	defer pool.lock.RUnlock()
   231  
   232  	msgs, ok := pool.earthSigs[prehash]
   233  	if !ok {
   234  		return nil
   235  	}
   236  
   237  	return msgs
   238  }
   239  
   240  func (pool *MsgPool) onBlockSealed(blockNum uint64) {
   241  	if blockNum <= pool.cacheLen {
   242  		return
   243  	}
   244  	pool.lock.Lock()
   245  	defer pool.lock.Unlock()
   246  
   247  	toFreeRound := make([]uint64, 0)
   248  	for n := range pool.rounds {
   249  		if n < blockNum-pool.cacheLen {
   250  			toFreeRound = append(toFreeRound, n)
   251  		}
   252  	}
   253  	for _, n := range toFreeRound {
   254  		delete(pool.rounds, n)
   255  	}
   256  }
   257  
   258  func (pool *MsgPool) IncInsert(blockNum uint32, msgtype comm.MsgType, msg interface{}) {
   259  }