github.com/annchain/OG@v0.0.9/consensus/term/archive/term.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 archive
    15  
    16  import (
    17  	"github.com/annchain/OG/arefactor/og/types"
    18  	"github.com/annchain/OG/common"
    19  	"github.com/annchain/OG/common/crypto"
    20  	"github.com/annchain/OG/consensus/campaign"
    21  	"sync"
    22  
    23  	log "github.com/sirupsen/logrus"
    24  )
    25  
    26  type Term struct {
    27  	id                     uint32 `json:"id"`
    28  	flag                   bool
    29  	partsNum               int
    30  	senators               Senators            `json:"senators"`
    31  	formerSenators         map[uint32]Senators `json:"former_senators"`
    32  	candidates             map[common.Address]*campaign.Campaign
    33  	publicKeys             []crypto.PublicKey
    34  	formerPublicKeys       []crypto.PublicKey
    35  	alsorans               map[common.Address]*campaign.Campaign
    36  	campaigns              map[common.Address]*campaign.Campaign
    37  	startedHeight          uint64
    38  	generateCampaignHeight uint64
    39  	newTerm                bool
    40  	termChangeInterval     int
    41  
    42  	mu                sync.RWMutex
    43  	currentTermChange *campaign.TermChange
    44  	genesisTermChange *campaign.TermChange
    45  	started           bool
    46  }
    47  
    48  func NewTerm(id uint32, participantNumber int, termChangeInterval int) *Term {
    49  	return &Term{
    50  		id:                 id,
    51  		flag:               false,
    52  		partsNum:           participantNumber,
    53  		termChangeInterval: termChangeInterval,
    54  		senators:           make(Senators),
    55  		formerSenators:     make(map[uint32]Senators),
    56  		candidates:         make(map[common.Address]*campaign.Campaign),
    57  		alsorans:           make(map[common.Address]*campaign.Campaign),
    58  		campaigns:          make(map[common.Address]*campaign.Campaign),
    59  	}
    60  }
    61  
    62  func (t *Term) ID() uint32 {
    63  	t.mu.RLock()
    64  	defer t.mu.RUnlock()
    65  
    66  	return t.id
    67  }
    68  
    69  func (t *Term) UpdateID(id uint32) {
    70  	t.mu.Lock()
    71  	defer t.mu.Unlock()
    72  
    73  	t.id = id
    74  }
    75  
    76  func (t *Term) SwitchFlag(flag bool) {
    77  	t.mu.Lock()
    78  	defer t.mu.Unlock()
    79  	t.flag = flag
    80  }
    81  
    82  func (t *Term) SetStartedHeight(h uint64) {
    83  	t.mu.Lock()
    84  	defer t.mu.Unlock()
    85  	t.startedHeight = h
    86  }
    87  
    88  func (t *Term) GetGenesisTermChange() *campaign.TermChange {
    89  	t.mu.RLock()
    90  	defer t.mu.RUnlock()
    91  	return t.genesisTermChange
    92  }
    93  
    94  func (t *Term) Changing() bool {
    95  	t.mu.RLock()
    96  	defer t.mu.RUnlock()
    97  
    98  	return t.flag
    99  }
   100  
   101  func (t *Term) Started() bool {
   102  	return t.started
   103  }
   104  
   105  func (t *Term) GetCandidate(addr common.Address) *campaign.Campaign {
   106  	t.mu.RLock()
   107  	defer t.mu.RUnlock()
   108  
   109  	return t.candidates[addr]
   110  }
   111  
   112  func (t *Term) Candidates() map[common.Address]*campaign.Campaign {
   113  	t.mu.RLock()
   114  	defer t.mu.RUnlock()
   115  
   116  	return t.candidates
   117  }
   118  
   119  func (t *Term) AddCandidate(c *campaign.Campaign, publicKey crypto.PublicKey) {
   120  	t.mu.Lock()
   121  	defer t.mu.Unlock()
   122  
   123  	t.candidates[c.Sender()] = c
   124  	t.publicKeys = append(t.publicKeys, publicKey)
   125  	//sort.Sort(t.publicKeys)
   126  }
   127  
   128  func (t *Term) AddCampaign(c *campaign.Campaign) {
   129  	t.mu.Lock()
   130  	defer t.mu.Unlock()
   131  
   132  	t.campaigns[c.Sender()] = c
   133  }
   134  
   135  func (t *Term) GetCampaign(addr common.Address) *campaign.Campaign {
   136  	t.mu.RLock()
   137  	defer t.mu.RUnlock()
   138  
   139  	return t.campaigns[addr]
   140  }
   141  
   142  func (t *Term) Campaigns() map[common.Address]*campaign.Campaign {
   143  	t.mu.RLock()
   144  	defer t.mu.RUnlock()
   145  
   146  	return t.campaigns
   147  }
   148  
   149  func (t *Term) GetAlsoran(addr common.Address) *campaign.Campaign {
   150  	t.mu.RLock()
   151  	defer t.mu.RUnlock()
   152  
   153  	return t.alsorans[addr]
   154  }
   155  
   156  func (t *Term) Alsorans() map[common.Address]*campaign.Campaign {
   157  	t.mu.RLock()
   158  	defer t.mu.RUnlock()
   159  
   160  	return t.alsorans
   161  }
   162  
   163  func (t *Term) AddAlsorans(camps []*campaign.Campaign) {
   164  	t.mu.Lock()
   165  	defer t.mu.Unlock()
   166  
   167  	for _, c := range camps {
   168  		if c == nil {
   169  			continue
   170  		}
   171  		// TODO
   172  		// this check is not proper enough, try optimize it.
   173  		if t.hasCampaign(c.Sender()) {
   174  			continue
   175  		}
   176  		t.alsorans[c.Sender()] = c
   177  	}
   178  }
   179  
   180  func (t *Term) HasCampaign(address common.Address) bool {
   181  	t.mu.RLock()
   182  	defer t.mu.RUnlock()
   183  
   184  	return t.hasCampaign(address)
   185  }
   186  
   187  func (t *Term) hasCampaign(address common.Address) bool {
   188  	if _, exists := t.candidates[address]; exists {
   189  		log.Debug("exist in candidates")
   190  		return true
   191  	}
   192  	if _, exists := t.campaigns[address]; exists {
   193  		log.Debug("exist in campaigns")
   194  		return true
   195  	}
   196  	if _, exists := t.alsorans[address]; exists {
   197  		log.Debug("exist in alsorans")
   198  		return true
   199  	}
   200  	return false
   201  }
   202  
   203  // CanChange returns true if the campaigns cached reaches the
   204  // term change requirments.
   205  func (t *Term) CanChange(lastHeight uint64, isGenesis bool) bool {
   206  	//TODO change this in future , make more slower
   207  	var a = 1
   208  	var b = 0
   209  	t.mu.RLock()
   210  	defer t.mu.RUnlock()
   211  
   212  	// TODO:
   213  	// term change requirements are not enough now.
   214  	if len(t.campaigns) == 0 {
   215  		return false
   216  	}
   217  	if len(t.campaigns) < t.partsNum {
   218  		log.WithField("len ", len(t.campaigns)).Debug("not enough campaigns , waiting")
   219  		return false
   220  	}
   221  	if isGenesis {
   222  		log.Debug("is genesis consensus, change term")
   223  		return true
   224  	}
   225  	if lastHeight-t.startedHeight < uint64(t.termChangeInterval*a+b) {
   226  		return false
   227  	}
   228  	return true
   229  }
   230  
   231  func (t *Term) ChangeTerm(tc *campaign.TermChange, lastHeight uint64) error {
   232  	t.mu.Lock()
   233  	defer t.mu.Unlock()
   234  
   235  	snts := make(map[common.Address]*Senator)
   236  	for addr, c := range t.candidates {
   237  		s := newSenator(addr, c.PublicKey, tc.PkBls)
   238  		snts[addr] = s
   239  	}
   240  
   241  	t.formerPublicKeys = t.publicKeys
   242  	if t.id == 0 {
   243  		t.genesisTermChange = tc
   244  	}
   245  
   246  	t.currentTermChange = tc
   247  
   248  	t.candidates = make(map[common.Address]*campaign.Campaign)
   249  	t.alsorans = make(map[common.Address]*campaign.Campaign)
   250  	t.campaigns = make(map[common.Address]*campaign.Campaign)
   251  	t.publicKeys = nil
   252  
   253  	formerSnts := t.senators
   254  	t.formerSenators[t.id] = formerSnts
   255  
   256  	t.senators = snts
   257  	t.started = true
   258  
   259  	// TODO
   260  	// 1. update id.
   261  	// 2. process alsorans.
   262  
   263  	t.id++
   264  	t.startedHeight = lastHeight
   265  	log.WithField("startedHeight", t.startedHeight).WithField("len senators ", len(t.senators)).WithField("id ", t.id).Info("term changed , id updated")
   266  	t.flag = false
   267  	return nil
   268  }
   269  
   270  type Senator struct {
   271  	addr         common.Address
   272  	pk           []byte
   273  	blspk        []byte
   274  	Id           int
   275  	CampaignHash types.Hash
   276  	// TODO:
   277  	// more variables?
   278  }
   279  
   280  func newSenator(addr common.Address, publickey, blspk []byte) *Senator {
   281  	s := &Senator{}
   282  	s.addr = addr
   283  	s.pk = publickey
   284  	s.blspk = blspk
   285  
   286  	return s
   287  }
   288  
   289  type Senators map[common.Address]*Senator
   290  
   291  func (t *Term) GetSenator(address common.Address) *Senator {
   292  	t.mu.RLock()
   293  	defer t.mu.RUnlock()
   294  	if v, ok := t.senators[address]; ok {
   295  		return v
   296  	}
   297  	return nil
   298  }
   299  
   300  func (t *Term) ClearCampaigns() {
   301  	t.mu.Lock()
   302  	defer t.mu.Unlock()
   303  	t.campaigns = nil
   304  }
   305  
   306  func (t *Term) GetFormerPks() []crypto.PublicKey {
   307  	return t.formerPublicKeys
   308  }