github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/consensus/dpos/dpos.go (about) 1 // Copyright 2019 The go-vnt Authors 2 // This file is part of the go-vnt library. 3 // 4 // The go-vnt library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-vnt library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-vnt library. If not, see <http://www.gnu.org/licenses/>. 16 17 package dpos 18 19 import ( 20 "errors" 21 "math/big" 22 "sync" 23 "time" 24 25 "bytes" 26 "encoding/binary" 27 "fmt" 28 29 lru "github.com/hashicorp/golang-lru" 30 "github.com/vntchain/go-vnt/accounts" 31 "github.com/vntchain/go-vnt/common" 32 "github.com/vntchain/go-vnt/common/math" 33 "github.com/vntchain/go-vnt/consensus" 34 "github.com/vntchain/go-vnt/core" 35 "github.com/vntchain/go-vnt/core/state" 36 "github.com/vntchain/go-vnt/core/types" 37 "github.com/vntchain/go-vnt/core/vm/election" 38 "github.com/vntchain/go-vnt/crypto" 39 "github.com/vntchain/go-vnt/crypto/sha3" 40 "github.com/vntchain/go-vnt/log" 41 "github.com/vntchain/go-vnt/params" 42 "github.com/vntchain/go-vnt/rlp" 43 "github.com/vntchain/go-vnt/rpc" 44 "github.com/vntchain/go-vnt/vntdb" 45 ) 46 47 const ( 48 inMemorySignatures = 4096 // Number of recent block signatures to keep in memory 49 updateTimeLen = 8 // Number of bytes the witnesses list update time take up 50 ) 51 52 var ( 53 VortexBlockReward *big.Int = big.NewInt(24e+17) // 2.4VNT 54 VortexCandidatesBonus *big.Int = big.NewInt(16e+17) // 1.6VNT 55 // 2 seconds one block, 3 years producing about 47304000 blocks 56 stageTwoBlkNr = big.NewInt(47304000) 57 // 2 seconds one block, 6 years producing about 94608000 blocks 58 stageThreeBlkNr = big.NewInt(94608000) 59 ) 60 61 // Various error messages to mark blocks invalid. These should be private to 62 // prevent engine specific errors from being referenced in the remainder of the 63 // codebase, inherently breaking if the engine is swapped out. Please put common 64 // error types into the consensus package. 65 var ( 66 // errUnknownBlock is returned when the list of signers is requested for a block 67 // that is not part of the local blockchain. 68 errUnknownBlock = errors.New("unknown block") 69 70 // block has a beneficiary set to non-zeroes. 71 errInvalidCoinBase = errors.New("coinbase in block non-zero") 72 73 // errInvalidDifficulty is returned if the difficulty of a block is not 1 74 errInvalidDifficulty = errors.New("invalid difficulty") 75 76 // errInvalidTimestamp is returned if the timestamp of a block is lower than 77 // the previous block's timestamp + the minimum block period. 78 errInvalidTimestamp = errors.New("invalid timestamp") 79 80 // witness should be same with the parent 81 errWitnesses = errors.New("witnesses is different from parent") 82 83 // witness should in turn 84 errOutTurn = errors.New("witness is out turn") 85 86 // errNoPreviousWitness is returned if no previous witness still in current witness list 87 errNoPreviousWitness = errors.New("no previous witness still in current witness list") 88 89 // errInvalidExtraLen is returned if extra length is invalid 90 errInvalidExtraLen = errors.New("invalid Extra length") 91 ) 92 93 type SignerFn func(accounts.Account, []byte) ([]byte, error) 94 95 // getHeaderFromParentsFn get header from previous headers 96 type getHeaderFromParentsFn func(hash common.Hash, num uint64) *types.Header 97 98 type Dpos struct { 99 config *params.DposConfig 100 bft *BftManager 101 db vntdb.Database // Database to store and retrieve dpos temp data, current not used 102 signatures *lru.ARCCache // Signatures of recent blocks to speed up block producing 103 signer common.Address // VNT address of the signing key 104 signFn SignerFn // Signer function to authorize hashes with 105 lock sync.RWMutex // Protects the signer fields 106 updateInterval *big.Int // Duration of update witnesses list 107 lastBounty lastBountyInfo // 上次发放激励的信息 108 109 sendBftPeerUpdateFn func(urls []string) 110 } 111 112 type lastBountyInfo struct { 113 bountyHeight *big.Int // 上次发送激励的高度 114 updateHeight *big.Int // 更新当前数据的高度 115 sync.RWMutex // 存在并发访问,加锁保护 116 } 117 118 // sigHash returns the hash which is used as input for the proof-of-authority 119 // signing. It is the hash of the entire header apart from the 65 byte signature 120 // contained at the end of the extra data. 121 // 122 // Note, the method requires the extra data to be at least 65 bytes, otherwise it 123 // panics. This is done to avoid accidentally using both forms (signature present 124 // or not), which could be abused to produce different hashes for the same header. 125 func sigHash(header *types.Header) (hash common.Hash, err error) { 126 hasher := sha3.NewKeccak256() 127 128 err = rlp.Encode(hasher, []interface{}{ 129 header.ParentHash, 130 header.Coinbase, 131 header.Root, 132 header.TxHash, 133 header.ReceiptHash, 134 header.Bloom, 135 header.Difficulty, 136 header.Number, 137 header.GasLimit, 138 header.GasUsed, 139 header.Time, 140 header.Extra, 141 header.Witnesses, 142 }) 143 if err != nil { 144 return common.Hash{}, err 145 } 146 147 hasher.Sum(hash[:0]) 148 return hash, nil 149 } 150 151 // ecrecover extracts the VNT account address from a signed header. 152 func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { 153 // If the signature's already cached, return that 154 hash := header.Hash() 155 if address, known := sigcache.Get(hash); known { 156 return address.(common.Address), nil 157 } 158 159 signature := header.Signature 160 161 // Recover the public key and the VNT address 162 sh, err := sigHash(header) 163 if err != nil { 164 return common.Address{}, err 165 } 166 pubkey, err := crypto.Ecrecover(sh.Bytes(), signature) 167 if err != nil { 168 return common.Address{}, fmt.Errorf("ecrecover fialed: %s", err.Error()) 169 } 170 var signer common.Address 171 copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) 172 173 sigcache.Add(hash, signer) 174 return signer, nil 175 } 176 177 // New creates a Delegated proof-of-stake consensus engine with the initial 178 // signers set to the ones provided by the user. 179 func New(config *params.DposConfig, db vntdb.Database) *Dpos { 180 signatures, _ := lru.NewARC(inMemorySignatures) 181 182 d := &Dpos{ 183 config: config, 184 bft: nil, 185 db: db, 186 signatures: signatures, 187 updateInterval: nil, 188 189 lastBounty: lastBountyInfo{ 190 bountyHeight: big.NewInt(0), 191 updateHeight: big.NewInt(0), 192 }, 193 } 194 195 d.bft = newBftManager(d) 196 d.setUpdateInterval() 197 198 return d 199 } 200 201 func (d *Dpos) InitBft(sendBftMsg func(types.ConsensusMsg), SendPeerUpdate func(urls []string), verifyBlock func(*types.Block) (types.Receipts, []*types.Log, uint64, error), writeBlock func(*types.Block) error) { 202 d.sendBftPeerUpdateFn = SendPeerUpdate 203 204 // Init bft function 205 d.bft.sendBftMsg = sendBftMsg 206 d.bft.verifyBlock = verifyBlock 207 d.bft.writeBlock = writeBlock 208 209 // Init bft field 210 d.bft.coinBase = d.coinBase() 211 212 d.bft.producingStart() 213 } 214 215 // Author implements consensus.Engine, returning the VNT address recovered 216 // from the signature in the header's extra-data section. 217 func (d *Dpos) Author(header *types.Header) (common.Address, error) { 218 return ecrecover(header, d.signatures) 219 } 220 221 // VerifyHeader checks whether a header conforms to the consensus rules. 222 func (d *Dpos) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { 223 224 err := d.verifyHeader(chain, header, nil) 225 if err != nil { 226 log.Debug("VerifyHeader error", "hash", header.Hash().String(), "err", err.Error()) 227 } else { 228 log.Debug("VerifyHeader NO error", "hash", header.Hash().String(), "number", header.Number.Int64()) 229 } 230 return err 231 } 232 233 // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The 234 // method returns a quit channel to abort the operations and a results channel to 235 // retrieve the async verifications (the order is that of the input slice). 236 func (d *Dpos) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { 237 abort := make(chan struct{}) 238 results := make(chan error, len(headers)) 239 go func() { 240 for i, header := range headers { 241 err := d.verifyHeader(chain, header, headers[:i]) 242 243 select { 244 case <-abort: 245 return 246 case results <- err: 247 } 248 } 249 }() 250 return abort, results 251 } 252 253 // verifyHeader checks whether a header conforms to the consensus rules.The 254 // caller may optionally pass in a batch of parents (ascending order) to avoid 255 // looking those up from the database. This is useful for concurrently verifying 256 // a batch of new headers. 257 func (d *Dpos) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 258 if header.Number == nil { 259 return errUnknownBlock 260 } 261 number := header.Number.Uint64() 262 263 // todo verify header.time after implement bft without time trigger produce block 264 // Don't waste time checking blocks from the future 265 // if header.Time.Cmp(big.NewInt(time.Now().Unix())) > 0 { 266 // return consensus.ErrFutureBlock 267 // } 268 269 // Ensure extra has correct length' value checked in verify witnesses 270 if len(header.Extra) != updateTimeLen { 271 return errInvalidExtraLen 272 } 273 274 // Ensure that the block's difficulty is meaningful (may not be correct at this point) 275 if number > 0 { 276 if header.Difficulty == nil || header.Difficulty.Cmp(big.NewInt(1)) != 0 { 277 return errInvalidDifficulty 278 } 279 } 280 // All basic checks passed, verify cascading fields 281 return d.verifyCascadingFields(chain, header, parents) 282 } 283 284 // verifyCascadingFields verifies all the header fields that are not standalone, 285 // rather depend on a batch of previous headers. The caller may optionally pass 286 // in a batch of parents (ascending order) to avoid looking those up from the 287 // database. This is useful for concurrently verifying a batch of new headers. 288 func (d *Dpos) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 289 // The genesis block is the always valid dead-end 290 number := header.Number.Uint64() 291 if number == 0 { 292 return nil 293 } 294 // Ensure that the block's timestamp isn't too close to it's parent 295 var parent *types.Header 296 if len(parents) > 0 { 297 parent = parents[len(parents)-1] 298 } else { 299 parent = chain.GetHeader(header.ParentHash, number-1) 300 } 301 if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { 302 return consensus.ErrUnknownAncestor 303 } 304 305 headerTime, parentTime := header.Time.Uint64(), parent.Time.Uint64() 306 if headerTime <= parentTime || (headerTime-parentTime)%d.config.Period != 0 { 307 log.Warn("Timestamp is invalid", "headerTime", headerTime, "parentTime", parentTime) 308 return errInvalidTimestamp 309 } 310 311 // Verify that the gas limit is <= 2^63-1 312 cap := uint64(0x7fffffffffffffff) 313 if header.GasLimit > cap { 314 return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap) 315 } 316 // Verify that the gasUsed is <= gasLimit 317 if header.GasUsed > header.GasLimit { 318 return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) 319 } 320 // Verify that the gas limit remains within allowed bounds 321 diff := int64(parent.GasLimit) - int64(header.GasLimit) 322 if diff < 0 { 323 diff *= -1 324 } 325 limit := parent.GasLimit / params.GasLimitBoundDivisor 326 if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit { 327 return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit) 328 } 329 330 if len(header.Witnesses) != d.config.WitnessesNum { 331 return errWitnesses 332 } 333 334 // All basic checks passed, verify the seal and return 335 return d.verifySeal(chain, header, parents) 336 } 337 338 // VerifySeal implements consensus.Engine, checking whether the signature contained 339 // in the header satisfies the consensus protocol requirements. 340 func (d *Dpos) VerifySeal(chain consensus.ChainReader, header *types.Header) error { 341 return d.verifySeal(chain, header, nil) 342 } 343 344 // verifySeal checks whether the signature contained in the header satisfies the 345 // consensus protocol requirements. The method accepts an optional list of parent 346 // headers that aren't yet part of the local blockchain to generate the snapshots 347 // from. 348 func (d *Dpos) verifySeal(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 349 // Verifying the genesis block is not supported 350 number := header.Number.Uint64() 351 if number == 0 { 352 return errUnknownBlock 353 } 354 // Resolve the authorization key and check against signers 355 signer, err := ecrecover(header, d.signatures) 356 if err != nil { 357 return err 358 } 359 360 if signer != header.Coinbase { 361 return errInvalidCoinBase 362 } 363 364 // 确认轮次对不对,是不是该这个节点出块 365 if !d.inTurn(header, signer, chain, parents) { 366 return errOutTurn 367 } 368 return nil 369 } 370 371 // VerifyWitnesses Verify witness list and update time(header.Extra) for DPoS 372 func (d *Dpos) VerifyWitnesses(header *types.Header, db *state.StateDB, parent *types.Header) error { 373 updated, localWitnesses := d.getWitnesses(header, db, parent) 374 if len(localWitnesses) != len(header.Witnesses) { 375 return fmt.Errorf("witnesses length not match") 376 } 377 378 // Check header.Extra 379 if needSetUpdateTime(updated, header.Number.Uint64()) { 380 if !d.updatedWitnessCheckByTime(header) { 381 return fmt.Errorf("header.Extra is mismatch with header.Time when update") 382 } 383 } else { 384 if !bytes.Equal(header.Extra, parent.Extra) { 385 return fmt.Errorf("header.Extra is mismatch with parent.Time when NOT update") 386 } 387 } 388 389 // Check the witnesses list 390 for i := 0; i < len(localWitnesses); i++ { 391 if localWitnesses[i] != header.Witnesses[i] { 392 return fmt.Errorf("witnesses is not match") 393 } 394 } 395 return nil 396 } 397 398 // Prepare implements consensus.Engine, preparing all the consensus fields of the 399 // header for running the transactions on top. 400 func (d *Dpos) Prepare(chain consensus.ChainReader, header *types.Header) error { 401 var ( 402 updated bool 403 err error 404 ) 405 406 number := header.Number.Uint64() 407 if number == 0 { 408 return errUnknownBlock 409 } 410 411 d.lock.RLock() 412 header.Coinbase = d.signer 413 d.lock.RUnlock() 414 415 // Set the correct difficulty 416 header.Difficulty = big.NewInt(1) 417 418 // Try to sleep if can not find parent header, try to stop commitNewWork start again immediately. 419 // WARN: there must be some db write or read error 420 parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) 421 if parent == nil { 422 log.Error("Miss parent in dos.Prepare()", "hash", header.ParentHash.String(), "number", header.Number.Uint64()-1) 423 time.Sleep(time.Minute * 2) 424 return consensus.ErrUnknownAncestor 425 } 426 427 // Put next time in header 428 produceTime, nPeriod, err := d.nextProduceTime(parent.Time) 429 if err != nil { 430 return err 431 } 432 header.Time = produceTime 433 434 // Update witness list if needed,and set Extra with update value 435 updated, header.Witnesses, err = d.getWitnessesForProduce(header, chain, parent) 436 if err != nil { 437 return err 438 } 439 440 // Start a new round of bft 441 r := uint32(nPeriod.Uint64()) - 1 442 d.bft.blockRound = r 443 go d.bft.newRound(header.Number, r, header.Witnesses) 444 445 // Make sure self is the current block producer before produce 446 witness := header.Coinbase 447 if !d.inTurn(header, witness, chain, nil) { 448 log.Debug("Prepare failed", "err", errOutTurn) 449 return fmt.Errorf("node is out of turn") 450 } 451 452 // Fill Extra with the update time 453 // If this updated the witnesses list in this block, extra = this header time 454 // else, extra = last update time(get from parent's block) 455 header.Extra = make([]byte, updateTimeLen) 456 if needSetUpdateTime(updated, number) { 457 copy(header.Extra, encodeUpdateTime(header.Time)) 458 } else { 459 copy(header.Extra, parent.Extra) 460 } 461 462 return nil 463 } 464 465 // needSetUpdateTime block 1 is special, should use it's header time instead of 466 // genesis's extra, because genesis's extra is nil 467 func needSetUpdateTime(update bool, number uint64) bool { 468 return update || number == 1 469 } 470 471 // Finalize implements consensus.Engine, grants reward and returns the final block. 472 func (d *Dpos) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, receipts []*types.Receipt) (*types.Block, error) { 473 // Granting bounty, if any left 474 if err := d.grantingReward(chain, header, state); err != nil { 475 return nil, err 476 } 477 478 // Commit db 479 header.Root = state.IntermediateRoot(true) 480 481 // Assemble and return the final block for sealing 482 return types.NewBlock(header, txs, receipts), nil 483 } 484 485 // grantingReward granting producing reward to the current block producer for producing this block, 486 // and granting vote reward to all the active witness candidates. the vote reward, which each witness 487 // earned, in direct proportion to it's vote percentage. 488 // WARN: There is no reward if no VNT bounty left. 489 func (d *Dpos) grantingReward(chain consensus.ChainReader, header *types.Header, state *state.StateDB) error { 490 if restBounty := election.QueryRestReward(state, header.Number); restBounty.Cmp(common.Big0) > 0 { 491 var err error 492 // Reward BP for producing this block 493 reward := curHeightBonus(header.Number, VortexBlockReward) 494 if restBounty.Cmp(reward) < 0 { 495 reward = restBounty 496 } 497 rewards := make(map[common.Address]*big.Int) 498 rewards[header.Coinbase] = reward 499 restBounty.Sub(restBounty, reward) 500 501 // 计算投票激励 502 // Reward all witness candidates, when update witness list, if has any bounty 503 if d.updatedWitnessCheckByTime(header) && restBounty.Cmp(common.Big0) > 0 { 504 candis, allBonus, err := d.voteBonusPreWork(chain, header, state) 505 if err != nil { 506 return err 507 } 508 509 // the amount of bounty granted must not greater than the left bounty 510 actualBonus := math.BigMin(allBonus, restBounty) 511 log.Debug("Vote bounty", "bounty(wei)", actualBonus.String()) 512 d.calcVoteBounty(candis, actualBonus, rewards) 513 } 514 515 // 统一发放激励 516 if err = election.GrantReward(state, rewards, header.Number); err != nil { 517 log.Warn("Granting reward failed", "error", err.Error()) 518 return err 519 } 520 } 521 return nil 522 } 523 524 // Authorize injects a private key into the consensus engine to mint new blocks 525 // with. 526 func (d *Dpos) Authorize(signer common.Address, signFn SignerFn) { 527 d.lock.Lock() 528 defer d.lock.Unlock() 529 530 d.signer = signer 531 d.signFn = signFn 532 } 533 534 // Seal implements consensus.Engine, attempting to create a sealed block using 535 // the local signing credentials. 536 func (d *Dpos) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) { 537 header := block.Header() 538 539 // Sealing the genesis block is not supported 540 number := header.Number.Uint64() 541 if number == 0 { 542 return nil, errUnknownBlock 543 } 544 545 // Don't hold the witness fields for the entire sealing procedure 546 d.lock.RLock() 547 witness, signFn := d.signer, d.signFn 548 d.lock.RUnlock() 549 550 // Sign all the things without Signature 551 sh, err := sigHash(header) 552 if err != nil { 553 return nil, err 554 } 555 sighash, err := signFn(accounts.Account{Address: witness}, sh.Bytes()) 556 if err != nil { 557 return nil, err 558 } 559 header.Signature = make([]byte, len(sighash)) 560 copy(header.Signature[:], sighash) 561 562 log.Info("Seal block", "at time", time.Now().Unix()) 563 d.bft.startPrePrepare(block.WithSeal(header)) 564 // DPoS no need return block 565 return nil, nil 566 } 567 568 // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty 569 // that a new block should have based on the previous blocks in the chain and the 570 // current signer. 571 func (d *Dpos) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { 572 return common.Big1 573 } 574 575 // APIs implements consensus.Engine, returning the user facing RPC API to allow 576 // controlling the signer voting. 577 func (d *Dpos) APIs(chain consensus.ChainReader) []rpc.API { 578 return []rpc.API{{ 579 Namespace: "dpos", 580 Version: "1.0", 581 Service: &API{chain: chain, dpos: d}, 582 Public: false, 583 }} 584 } 585 586 // nextProduceTime calculate next block produce time with previous block time 587 // cur_time = time() 588 // dur = cur_time - parent_time 589 // nPeriod = dur / interval 590 // // always up bound 591 // nPeriod++ 592 // return parent_time + diff_index * interval 593 func (d *Dpos) nextProduceTime(preBlockTime *big.Int) (produceTime *big.Int, nPeriod *big.Int, err error) { 594 now := time.Now().Unix() 595 dur := new(big.Int).Sub(new(big.Int).SetInt64(now), preBlockTime) 596 period := new(big.Int).SetUint64(d.config.Period) 597 // the unit is second, even no left of DivMod, but current time is in new period 598 nPeriod = new(big.Int).Div(dur, period) 599 nPeriod.Add(nPeriod, common.Big1) 600 601 nextTime := new(big.Int).Mul(nPeriod, period) 602 nextTime.Add(nextTime, preBlockTime) 603 604 return nextTime, nPeriod, nil 605 } 606 607 func (d *Dpos) inTurn(header *types.Header, witness common.Address, chain consensus.ChainReader, parents []*types.Header) bool { 608 var ( 609 preWitness common.Address 610 preTime *big.Int 611 manager *Manager 612 err error 613 ) 614 615 getHeaderFromParents := func(hash common.Hash, num uint64) *types.Header { 616 if len(parents) == 0 { 617 return nil 618 } 619 620 for i := len(parents) - 1; i >= 0; i-- { 621 if parents[i].Hash() == hash && parents[i].Number.Uint64() == num { 622 return parents[i] 623 } 624 } 625 return nil 626 } 627 628 number := header.Number.Uint64() 629 // using current block's witness list create manager 630 if manager, err = d.manager(header); err != nil { 631 log.Warn("Not find manager", "err", err.Error(), "number", number) 632 return false 633 } 634 635 // first block always belongs to first witness 636 if number == 1 { 637 if len(manager.Witnesses) > 0 && manager.Witnesses[0] == witness { 638 return true 639 } else { 640 return false 641 } 642 } 643 644 preWitness, preTime, err = d.previousWitness(manager, chain, header.ParentHash, number-1, getHeaderFromParents) 645 if err == errNoPreviousWitness { 646 return manager.Witnesses[0] == witness 647 } else if err != nil { 648 log.Warn("Not find preWitness", "err", err.Error()) 649 return false 650 } 651 652 return manager.inTurn(witness, preWitness, header.Time, preTime) 653 } 654 655 // previousWitness find the previous witness who still in current witness list 656 func (d *Dpos) previousWitness(manager *Manager, chain consensus.ChainReader, hash common.Hash, number uint64, getHeaderFromParents getHeaderFromParentsFn) (witness common.Address, produceTime *big.Int, err error) { 657 var header *types.Header 658 659 find := false 660 for !find { 661 if number == 0 { 662 return witness, produceTime, errNoPreviousWitness 663 } 664 665 header = getHeaderFromParents(hash, number) 666 if header == nil { 667 header = chain.GetHeader(hash, number) 668 } 669 if header == nil { 670 return witness, produceTime, fmt.Errorf("can not find block header hash: %x, at hight: %d", hash, number) 671 } 672 673 // check is witness still valid 674 witness = header.Coinbase 675 find = manager.has(witness) 676 if find { 677 break 678 } 679 680 hash, number = header.ParentHash, number-1 681 } 682 683 // produce time from parent 684 produceTime = header.Time 685 686 return witness, produceTime, nil 687 } 688 689 // manager create a witness list manager using header 690 func (d *Dpos) manager(header *types.Header) (*Manager, error) { 691 if len(header.Witnesses) == 0 { 692 return nil, fmt.Errorf("header.Witnesses is empty") 693 } 694 695 // using header's witness list create manager 696 return NewManager(d.config.Period, header.Witnesses), nil 697 } 698 699 // getWitnessesForProduce Get the first N candidates as witnesses from chain 700 func (d *Dpos) getWitnessesForProduce(header *types.Header, chain consensus.ChainReader, parent *types.Header) (bool, []common.Address, error) { 701 var ( 702 bc *core.BlockChain 703 ok bool 704 ) 705 706 // get state db from parent's root 707 if bc, ok = chain.(*core.BlockChain); !ok { 708 return false, nil, fmt.Errorf("getWitnessesForProduce, get block chain instance error") 709 } 710 db, err := bc.StateAt(parent.Root) 711 if db == nil { 712 return false, nil, err 713 } 714 715 updated, witnesses := d.getWitnesses(header, db, parent) 716 return updated, witnesses, nil 717 } 718 719 // getWitnesses 根据当前情况,判断从指定的state db读取或者使用前一个区块的 720 func (d *Dpos) getWitnesses(header *types.Header, db *state.StateDB, parent *types.Header) (bool, []common.Address) { 721 var ( 722 witnesses []common.Address 723 lastUpdateTime *big.Int 724 urls []string 725 ) 726 727 // Get last update witnesses list time from parent block 728 if parent.Number.Int64() == 0 { 729 lastUpdateTime = parent.Time 730 } else { 731 var upTime updateTime 732 copy(upTime[:], parent.Extra[:updateTimeLen]) 733 lastUpdateTime = upTime.bigInt() 734 } 735 736 need := d.needUpdateWitnesses(header.Time, lastUpdateTime) 737 if need { 738 log.Debug("Get new witness from db", "height", header.Number.String()) 739 witnesses, urls = d.GetWitnessesFromStateDB(db) 740 } 741 742 // Using parent's witnesses, when update failed or No need update 743 updated := need 744 if len(witnesses) == 0 { 745 witnesses = parent.Witnesses 746 updated = false 747 } 748 if updated && d.sendBftPeerUpdateFn != nil { 749 d.sendBftPeerUpdateFn(urls) 750 } 751 return updated, witnesses 752 } 753 754 // GetWitnessesFromStateDB Get the first N candidates as witnesses from stateDB 755 // It's can be used for get produce block and verify witnesses 756 func (d *Dpos) GetWitnessesFromStateDB(stateDB *state.StateDB) ([]common.Address, []string) { 757 if stateDB == nil { 758 log.Error("GetWitnessesFromStateDB, stateDB is nil") 759 } 760 761 return election.GetFirstNCandidates(stateDB, d.config.WitnessesNum) 762 } 763 764 // needUpdateWitnesses weather current time needs update witnesses list 765 func (d *Dpos) needUpdateWitnesses(t *big.Int, lastUpdateTime *big.Int) bool { 766 log.Debug("needUpdateWitnesses", "last", lastUpdateTime.String(), "current", t.String()) 767 dur := new(big.Int).Sub(t, lastUpdateTime) 768 return dur.Cmp(d.updateInterval) >= 0 769 } 770 771 // setUpdateInterval only called when start up 772 func (d *Dpos) setUpdateInterval() { 773 d.updateInterval = new(big.Int).SetUint64(3 * uint64(d.config.WitnessesNum) * d.config.Period) 774 } 775 776 // coinBase get the address of this producer 777 func (d *Dpos) coinBase() (cb common.Address) { 778 d.lock.RLock() 779 cb = d.signer 780 d.lock.RUnlock() 781 return 782 } 783 784 // HandleBftMsg handle the bft message received from peer. 785 func (d *Dpos) HandleBftMsg(chain consensus.ChainReader, msg types.ConsensusMsg) { 786 go d.bft.handleBftMsg(msg) 787 } 788 789 func (d *Dpos) CleanOldMsg(h *big.Int) { 790 d.bft.cleanOldMsg(h) 791 } 792 793 func (d *Dpos) VerifyCommitMsg(block *types.Block) error { 794 return d.bft.VerifyCmtMsgOf(block) 795 } 796 797 func (d *Dpos) ProducingStop() { 798 d.bft.producingStop() 799 } 800 801 type updateTime [updateTimeLen]byte 802 803 func encodeUpdateTime(uTime *big.Int) []byte { 804 var upTime updateTime 805 binary.BigEndian.PutUint64(upTime[:], uTime.Uint64()) 806 return upTime[:] 807 } 808 809 func (upTime *updateTime) bigInt() *big.Int { 810 uTime := binary.BigEndian.Uint64(upTime[:]) 811 return big.NewInt(0).SetUint64(uTime) 812 } 813 814 // calcVoteBounty returns a map, which contains the vote bonus of each candidates 815 // in this period. If active candidates less than WitnessesNum it will not reward candidate. 816 func (d *Dpos) calcVoteBounty(candis election.CandidateList, allBonus *big.Int, rewards map[common.Address]*big.Int) { 817 totalVotes := big.NewInt(0) 818 activeCnt := 0 819 for _, can := range candis { 820 if !can.Active() { 821 continue 822 } 823 totalVotes.Add(totalVotes, can.VoteCount) 824 activeCnt++ 825 } 826 // Too less candidates before main net start, but it's normal 827 if activeCnt < d.config.WitnessesNum || totalVotes.Cmp(common.Big0) == 0 { 828 return 829 } 830 831 // Calc each candidates' bonus 832 for _, can := range candis { 833 if !can.Active() { 834 continue 835 } 836 837 reward := big.NewInt(0).Mul(allBonus, can.VoteCount) 838 reward.Div(reward, totalVotes) 839 if _, ok := rewards[can.Owner]; ok { 840 rewards[can.Owner] = big.NewInt(0).Add(rewards[can.Owner], reward) 841 } else { 842 rewards[can.Owner] = reward 843 } 844 } 845 } 846 847 // voteBonusPreWork 848 // 1) calculate vote bonus 849 // 2) get witness candidates of last update witness 850 func (d *Dpos) voteBonusPreWork(chain consensus.ChainReader, header *types.Header, 851 curStateDB *state.StateDB) (election.CandidateList, *big.Int, error) { 852 var ( 853 bc *core.BlockChain 854 ok bool 855 ) 856 // Block 1, no need bonus, it's no error 857 if header.Number.Cmp(common.Big1) <= 0 { 858 return make(election.CandidateList, 0), big.NewInt(0), nil 859 } 860 861 // Get state db from previous block 862 if bc, ok = chain.(*core.BlockChain); !ok { 863 return nil, nil, fmt.Errorf("voteBonusPreWork, get block chain instance error") 864 } 865 866 // Calc all vote bonus 867 // the last block number of calculate vote reward is the last block number of updating witness list 868 lastCalcBountyBlkNr := d.lastBountyBlkNr(header, bc) 869 log.Debug("Bounus", "lastCalcBountyBlkNr", lastCalcBountyBlkNr.String()) 870 allBonus := big.NewInt(0).Sub(header.Number, lastCalcBountyBlkNr) 871 if allBonus.Sign() <= 0 { 872 return make(election.CandidateList, 0), big.NewInt(0), nil 873 } 874 allBonus.Mul(allBonus, curHeightBonus(header.Number, VortexCandidatesBonus)) 875 876 // Get all witnesses candidates 877 lastCandis := election.GetAllCandidates(curStateDB, false) 878 879 return lastCandis, allBonus, nil 880 } 881 882 // lastBountyBlkNr returns the block number of last update witness list. Returns 883 // the current block number if not find. This prevents excessive incentives. 884 // 见证人列表长时间未更新时,可能查找耗时,所以设置缓存数据, 885 // 同过度的下次查找将不再耗时。 886 // 不同高度的话,必然已经进行了下一轮见证人列表更新,以链上数据 887 // 为准,所以进行查找,然后记录数据。 888 func (d *Dpos) lastBountyBlkNr(header *types.Header, bc *core.BlockChain) (bh *big.Int) { 889 // 数据老旧时,尝试更新数据 890 d.lastBounty.RLock() 891 outdated := d.lastBounty.updateHeight.Cmp(header.Number) < 0 892 d.lastBounty.RUnlock() 893 if outdated { 894 h := bc.CurrentHeader() 895 for !d.updatedWitnessCheckByTime(h) && h != nil { 896 h = bc.GetHeaderByHash(h.ParentHash) 897 } 898 if h != nil { 899 bh = new(big.Int).Set(h.Number) 900 } else { 901 bh = new(big.Int).Set(header.Number) 902 } 903 904 d.lastBounty.Lock() 905 d.lastBounty.bountyHeight.Set(bh) 906 d.lastBounty.updateHeight.Set(header.Number) 907 d.lastBounty.Unlock() 908 return 909 } 910 911 // 本高度已查找过,使用已查得数据 912 d.lastBounty.RLock() 913 bh = big.NewInt(0).Set(d.lastBounty.bountyHeight) 914 d.lastBounty.RUnlock() 915 916 return bh 917 } 918 919 // updatedWitnessCheckByTime using time to check whether this block updated 920 // witness list or not. 921 func (d *Dpos) updatedWitnessCheckByTime(header *types.Header) bool { 922 if len(header.Extra) < updateTimeLen { 923 return false 924 } 925 926 var upTime updateTime 927 copy(upTime[:], header.Extra[:updateTimeLen]) 928 uTime := upTime.bigInt() 929 return uTime.Cmp(header.Time) == 0 930 } 931 932 // curHeightBonus return the VNT bonus at blkNr block number. 933 func curHeightBonus(blkNr *big.Int, initBonus *big.Int) *big.Int { 934 var denominator *big.Int 935 if blkNr.Cmp(stageTwoBlkNr) < 0 { 936 return initBonus 937 } else if blkNr.Cmp(stageThreeBlkNr) < 0 { 938 denominator = common.Big2 939 } else { 940 denominator = common.Big4 941 } 942 943 return big.NewInt(0).Div(initBonus, denominator) 944 }