github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/consensus/dbft/backend/engine.go (about) 1 package backend 2 3 import ( 4 "bytes" 5 "errors" 6 //"fmt" 7 "math/big" 8 //"math/rand" 9 "time" 10 11 lru "github.com/hashicorp/golang-lru" 12 "github.com/quickchainproject/quickchain/common" 13 "github.com/quickchainproject/quickchain/common/hexutil" 14 "github.com/quickchainproject/quickchain/consensus" 15 bft "github.com/quickchainproject/quickchain/consensus/dbft" 16 dbftCore "github.com/quickchainproject/quickchain/consensus/dbft/core" 17 "github.com/quickchainproject/quickchain/consensus/dbft/validator" 18 "github.com/quickchainproject/quickchain/core/state" 19 "github.com/quickchainproject/quickchain/core/types" 20 "github.com/quickchainproject/quickchain/crypto/sha3" 21 "github.com/quickchainproject/quickchain/log" 22 "github.com/quickchainproject/quickchain/rlp" 23 "github.com/quickchainproject/quickchain/rpc" 24 ) 25 26 const ( 27 //checkpointInterval = 1024 // Number of blocks after which to save the vote snapshot to the database 28 checkpointInterval = 1 // Number of blocks after which to save the vote snapshot to the database 29 inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory 30 inmemorySignatures = 4096 // Number of recent block signatures to keep in memory 31 inmemoryPeers = 40 32 inmemoryMessages = 1024 33 34 maxValidatorSize = 11 35 safeSize = 1 36 ) 37 38 var ( 39 MinDelegateBalance = big.NewFloat(10 * 1e18) //10QCT 40 MinCandidateBalance = big.NewFloat(100 * 1e18) //100QCT 41 UnlockInterval = big.NewInt(10) //10 Block 42 43 //epochLength = uint64(30000) // Default number of blocks after which to checkpoint and reset the pending votes 44 epochLength = uint64(30) 45 epochInterval = int64(epochLength) //alias for epochLength for test 46 ) 47 48 var ( 49 // errInvalidProposal is returned when a prposal is malformed. 50 errInvalidProposal = errors.New("invalid proposal") 51 // errInvalidSignature is returned when given signature is not signed by given 52 // address. 53 errInvalidSignature = errors.New("invalid signature") 54 // errUnknownBlock is returned when the list of validators is requested for a block 55 // that is not part of the local blockchain. 56 errUnknownBlock = errors.New("unknown block") 57 // errUnauthorized is returned if a header is signed by a non authorized entity. 58 errUnauthorized = errors.New("unauthorized") 59 // errInvalidDifficulty is returned if the difficulty of a block is not 1 60 errInvalidDifficulty = errors.New("invalid difficulty") 61 // errInvalidExtraDataFormat is returned when the extra data format is incorrect 62 errInvalidExtraDataFormat = errors.New("invalid extra data format") 63 // errInvalidMixDigest is returned if a block's mix digest is not BFT digest. 64 errInvalidMixDigest = errors.New("invalid BFT mix digest") 65 // errInvalidNonce is returned if a block's nonce is invalid 66 errInvalidNonce = errors.New("invalid nonce") 67 // errInvalidUncleHash is returned if a block contains an non-empty uncle list. 68 errInvalidUncleHash = errors.New("non empty uncle hash") 69 // errInconsistentValidatorSet is returned if the validator set is inconsistent 70 errInconsistentValidatorSet = errors.New("non empty uncle hash") 71 // errInvalidTimestamp is returned if the timestamp of a block is lower than the previous block's timestamp + the minimum block period. 72 errInvalidTimestamp = errors.New("invalid timestamp") 73 // errInvalidVotingChain is returned if an authorization list is attempted to 74 // be modified via out-of-range or non-contiguous headers. 75 errInvalidVotingChain = errors.New("invalid voting chain") 76 // errInvalidVote is returned if a nonce value is something else that the two 77 // allowed constants of 0x00..0 or 0xff..f. 78 errInvalidVote = errors.New("vote nonce not 0x00..0 or 0xff..f") 79 // errInvalidCommittedSeals is returned if the committed seal is not signed by any of parent validators. 80 errInvalidCommittedSeals = errors.New("invalid committed seals") 81 // errEmptyCommittedSeals is returned if the field of committed seals is zero. 82 errEmptyCommittedSeals = errors.New("zero committed seals") 83 // errMismatchTxhashes is returned if the TxHash in header is mismatch. 84 errMismatchTxhashes = errors.New("mismatch transcations hashes") 85 86 ErrMismatchSignerAndValidator = errors.New("mismatch block signer and validator") 87 ErrNilBlockHeader = errors.New("nil block header returned") 88 ) 89 var ( 90 defaultDifficulty = big.NewInt(1) 91 nilUncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW. 92 emptyNonce = types.BlockNonce{} 93 now = time.Now 94 95 nonceAuthVote = hexutil.MustDecode("0xffffffffffffffff") // Magic nonce number to vote on adding a new validator 96 nonceDropVote = hexutil.MustDecode("0x0000000000000000") // Magic nonce number to vote on removing a validator. 97 98 inmemoryAddresses = 20 // Number of recent addresses from ecrecover 99 recentAddresses, _ = lru.NewARC(inmemoryAddresses) 100 ) 101 102 // Author retrieves the Ethereum address of the account that minted the given 103 // block, which may be different from the header's coinbase if a consensus 104 // engine is based on signatures. 105 func (sb *backend) Author(header *types.Header) (common.Address, error) { 106 return ecrecover(header, recentAddresses) 107 } 108 109 // Authorize injects a private key into the consensus engine to mint new blocks 110 // with. 111 func (sb *backend) Authorize(signer common.Address, signFn SignerFn) { 112 sb.dpos.Authorize(signer, signFn) 113 } 114 115 116 // VerifyHeader checks whether a header conforms to the consensus rules of a 117 // given engine. Verifying the seal may be done optionally here, or explicitly 118 // via the VerifySeal method. 119 func (sb *backend) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { 120 return sb.verifyHeader(chain, header, nil) 121 } 122 123 // verifyHeader checks whether a header conforms to the consensus rules.The 124 // caller may optionally pass in a batch of parents (ascending order) to avoid 125 // looking those up from the database. This is useful for concurrently verifying 126 // a batch of new headers. 127 func (sb *backend) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 128 if header.Number == nil { 129 return errUnknownBlock 130 } 131 132 // Don't waste time checking blocks from the future 133 if header.Time.Cmp(big.NewInt(now().Unix())) > 0 { 134 return consensus.ErrFutureBlock 135 } 136 137 // Ensure that the extra data format is satisfied 138 if _, err := types.ExtractBFTExtra(header); err != nil { 139 return errInvalidExtraDataFormat 140 } 141 142 /* 143 // Ensure that the coinbase is valid 144 if header.Nonce != (emptyNonce) && !bytes.Equal(header.Nonce[:], nonceAuthVote) && !bytes.Equal(header.Nonce[:], nonceDropVote) { 145 return errInvalidNonce 146 } 147 */ 148 149 // Ensure that the mix digest is zero as we don't have fork protection currently 150 if header.MixDigest != types.BFTDigest { 151 return errInvalidMixDigest 152 } 153 // Ensure that the block doesn't contain any uncles which are meaningless in BFT 154 if header.UncleHash != nilUncleHash { 155 return errInvalidUncleHash 156 } 157 // Ensure that the block's difficulty is meaningful (may not be correct at this point) 158 if header.Difficulty == nil || header.Difficulty.Cmp(defaultDifficulty) != 0 { 159 return errInvalidDifficulty 160 } 161 162 // //signer, err := ecrecover(header, c.signatures) //dpos 163 // signer, err := ecrecover(header, recentAddresses) 164 // if err != nil { 165 // return err 166 // } 167 // //check validator 168 // if bytes.Compare(signer.Bytes(), header.Coinbase.Bytes()) != 0 { 169 // return ErrMismatchSignerAndValidator 170 // } 171 172 // If all checks passed, validate any special fields for hard forks 173 // if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil { 174 // return err 175 // } 176 177 return sb.verifyCascadingFields(chain, header, parents) 178 } 179 180 // verifyCascadingFields verifies all the header fields that are not standalone, 181 // rather depend on a batch of previous headers. The caller may optionally pass 182 // in a batch of parents (ascending order) to avoid looking those up from the 183 // database. This is useful for concurrently verifying a batch of new headers. 184 func (sb *backend) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 185 // The genesis block is the always valid dead-end 186 number := header.Number.Uint64() 187 if number == 0 { 188 return nil 189 } 190 // Ensure that the block's timestamp isn't too close to it's parent 191 var parent *types.Header 192 if len(parents) > 0 { 193 parent = parents[len(parents)-1] 194 } else { 195 parent = chain.GetHeader(header.ParentHash, number-1) 196 } 197 if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { 198 return consensus.ErrUnknownAncestor 199 } 200 if parent.Time.Uint64()+sb.config.BlockPeriod > header.Time.Uint64() { 201 return errInvalidTimestamp 202 } 203 // Verify validators in extraData. Validators in snapshot and extraData should be the same. 204 snap, err := sb.snapshot(chain, number-1, header.ParentHash, parents) 205 if err != nil { 206 return err 207 } 208 validators := make([]byte, len(snap.validators())*common.AddressLength) 209 for i, validator := range snap.validators() { 210 copy(validators[i*common.AddressLength:], validator[:]) 211 } 212 if err := sb.verifySigner(chain, header, parents); err != nil { 213 return err 214 } 215 216 return sb.verifyCommittedSeals(chain, header, parents) 217 } 218 219 // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers 220 // concurrently. The method returns a quit channel to abort the operations and 221 // a results channel to retrieve the async verifications (the order is that of 222 // the input slice). 223 func (sb *backend) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { 224 abort := make(chan struct{}) 225 results := make(chan error, len(headers)) 226 go func() { 227 for i, header := range headers { 228 err := sb.verifyHeader(chain, header, headers[:i]) 229 230 select { 231 case <-abort: 232 return 233 case results <- err: 234 } 235 } 236 }() 237 return abort, results 238 } 239 240 // VerifyUncles verifies that the given block's uncles conform to the consensus 241 // rules of a given engine. 242 func (sb *backend) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { 243 if len(block.Uncles()) > 0 { 244 return errInvalidUncleHash 245 } 246 return nil 247 } 248 249 // verifySigner checks whether the signer is in parent's validator set 250 func (sb *backend) verifySigner(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 251 // Verifying the genesis block is not supported 252 number := header.Number.Uint64() 253 if number == 0 { 254 return errUnknownBlock 255 } 256 257 // Retrieve the snapshot needed to verify this header and cache it 258 snap, err := sb.snapshot(chain, number-1, header.ParentHash, parents) 259 if err != nil { 260 return err 261 } 262 263 // resolve the authorization key and check against signers 264 signer, err := ecrecover(header, recentAddresses) 265 if err != nil { 266 return err 267 } 268 269 // Signer should be in the validator set of previous block's extraData. 270 if _, v := snap.ValSet.GetByAddress(signer); v == nil { 271 sb.logger.Error("verifySigner", "err", err) 272 sb.logger.Info(" ", "signer", signer) 273 sb.logger.Info(" ", "valSet", snap.ValSet) 274 return errUnauthorized 275 } 276 return nil 277 } 278 279 // verifyCommittedSeals checks whether every committed seal is signed by one of the parent's validators 280 func (sb *backend) verifyCommittedSeals(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 281 number := header.Number.Uint64() 282 // We don't need to verify committed seals in the genesis block 283 if number == 0 { 284 return nil 285 } 286 287 // Retrieve the snapshot needed to verify this header and cache it 288 snap, err := sb.snapshot(chain, number-1, header.ParentHash, parents) 289 if err != nil { 290 return err 291 } 292 293 extra, err := types.ExtractBFTExtra(header) 294 if err != nil { 295 return err 296 } 297 // The length of Committed seals should be larger than 0 298 if len(extra.CommittedSeal) == 0 { 299 return errEmptyCommittedSeals 300 } 301 302 validators := snap.ValSet.Copy() 303 // Check whether the committed seals are generated by parent's validators 304 validSeal := 0 305 proposalSeal := dbftCore.PrepareCommittedSeal(header.Hash()) 306 // 1. Get committed seals from current header 307 for _, seal := range extra.CommittedSeal { 308 // 2. Get the original address by seal and parent block hash 309 addr, err := bft.GetSignatureAddress(proposalSeal, seal) 310 if err != nil { 311 sb.logger.Error("not a valid address", "err", err) 312 return errInvalidSignature 313 } 314 // Every validator can have only one seal. If more than one seals are signed by a 315 // validator, the validator cannot be found and errInvalidCommittedSeals is returned. 316 if validators.RemoveValidator(addr) { 317 validSeal += 1 318 } else { 319 return errInvalidCommittedSeals 320 } 321 } 322 323 // The length of validSeal should be larger than number of faulty node + 1 324 if validSeal <= 2*snap.ValSet.F() { 325 return errInvalidCommittedSeals 326 } 327 328 return nil 329 } 330 331 // VerifySeal checks whether the crypto seal on a header is valid according to 332 // the consensus rules of the given engine. 333 func (sb *backend) VerifySeal(chain consensus.ChainReader, header *types.Header) error { 334 return sb.verifySeal(chain, header, nil) 335 } 336 337 func (sb *backend) verifySeal(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 338 // get parent header and ensure the signer is in parent's validator set 339 number := header.Number.Uint64() 340 if number == 0 { 341 return errUnknownBlock 342 } 343 344 var parent *types.Header 345 if len(parents) > 0 { 346 parent = parents[len(parents)-1] 347 } else { 348 parent = chain.GetHeader(header.ParentHash, number-1) 349 } 350 if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { 351 return consensus.ErrUnknownAncestor 352 } 353 // Retrieve the epochcontext needed to verify this header and cache it 354 // epoch, err := sb.snapshot(chain, number-1, header.ParentHash, parents) 355 _, err := sb.snapshot(chain, number-1, header.ParentHash, parents) 356 if err != nil { 357 return err 358 } 359 360 // // Resolve the authorization key and check against signers 361 // //signer, err := ecrecover(header, c.signatures) 362 // signer, err := ecrecover(header, recentAddresses) 363 // if err != nil { 364 // return err 365 // } 366 // if _, ok := epoch.Signers[signer]; !ok { 367 // return errUnauthorized 368 // } 369 // for seen, recent := range epoch.Recents { 370 // if recent == signer { 371 // // Signer is among recents, only fail if the current block doesn't shift it out 372 // if limit := uint64(len(epoch.Signers)/2 + 1); seen > number-limit { 373 // return errUnauthorized 374 // } 375 // } 376 // } 377 378 // ensure that the difficulty equals to defaultDifficulty 379 if header.Difficulty.Cmp(defaultDifficulty) != 0 { 380 return errInvalidDifficulty 381 } 382 return sb.verifySigner(chain, header, nil) 383 } 384 385 // Prepare initializes the consensus fields of a block header according to the 386 // rules of a particular engine. The changes are executed inline. 387 func (sb *backend) Prepare(chain consensus.ChainReader, header *types.Header) error { 388 // unused fields, force to set to empty 389 header.Coinbase = common.Address{} 390 header.Nonce = emptyNonce 391 header.MixDigest = types.BFTDigest 392 393 // copy the parent extra data as the header extra data 394 number := header.Number.Uint64() 395 parent := chain.GetHeader(header.ParentHash, number-1) 396 if parent == nil { 397 return consensus.ErrUnknownAncestor 398 } 399 // use the same difficulty for all blocks 400 header.Difficulty = defaultDifficulty 401 402 // Assemble the voting snapshot 403 snap, err := sb.snapshot(chain, number-1, header.ParentHash, nil) 404 if err != nil { 405 return err 406 } 407 408 /* 409 // get valid candidate list 410 sb.candidatesLock.RLock() 411 var addresses []common.Address 412 var authorizes []bool 413 for address, authorize := range sb.candidates { 414 if snap.checkVote(address, authorize) { 415 addresses = append(addresses, address) 416 authorizes = append(authorizes, authorize) 417 } 418 } 419 sb.candidatesLock.RUnlock() 420 421 // pick one of the candidates randomly 422 if len(addresses) > 0 { 423 index := rand.Intn(len(addresses)) 424 // add validator voting in coinbase 425 header.Coinbase = addresses[index] 426 if authorizes[index] { 427 copy(header.Nonce[:], nonceAuthVote) 428 } else { 429 copy(header.Nonce[:], nonceDropVote) 430 } 431 } 432 */ 433 434 // add validators in snapshot to extraData's validators section 435 extra, err := prepareExtra(header, snap.validators()) 436 if err != nil { 437 return err 438 } 439 header.Extra = extra 440 441 // set header's timestamp 442 header.Time = new(big.Int).Add(parent.Time, new(big.Int).SetUint64(sb.config.BlockPeriod)) 443 if header.Time.Int64() < time.Now().Unix() { 444 header.Time = big.NewInt(time.Now().Unix()) 445 } 446 return nil 447 } 448 449 // Judge the create contract Transaction from a no authorized account for clique engine. 450 func (sb *backend) JudgeTx(chain consensus.ChainReader, header *types.Header, tx *types.Transaction, from common.Address) error { 451 /* 452 // get the number of the new block 453 number := header.Number.Uint64() 454 //log.Info("PrepareTx number ","number", number) 455 // get current block sanpshot 456 snap, err := sb.snapshot(chain, number-1, header.ParentHash, nil) 457 if err != nil { 458 return err 459 } 460 //log.Info("PrepareTx get snapshot ") 461 if tx.To() == nil { 462 //log.Info("PrepareTx tx.To() == nil") 463 //judge a account is not a authorizer 464 if _, authorized := snap.Signers[from]; !authorized { 465 log.Info("PrepareTx create contract no authorized", "from", from) 466 return errUnauthorized 467 } else { 468 log.Info("PrepareTx create contract authorized", "from", from) 469 } 470 } else { 471 //log.Info("PrepareTx tx.To() != nil", "from", from) 472 }*/ 473 return nil 474 } 475 476 // Finalize runs any post-transaction state modifications (e.g. block rewards) 477 // and assembles the final block. 478 // 479 // Note, the block header and state database might be updated to reflect any 480 // consensus rules that happen at finalization (e.g. block rewards). 481 func (sb *backend) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, 482 uncles []*types.Header, receipts []*types.Receipt, dposContext *types.DposContext) (*types.Block, error) { 483 // No block rewards in BFT, so the state remains as is and uncles are dropped 484 /* 485 header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) 486 header.UncleHash = nilUncleHash 487 488 number := header.Number.Uint64() 489 parent := chain.GetHeader(header.ParentHash, number-1) 490 if parent == nil { 491 return nil, consensus.ErrUnknownAncestor 492 } 493 494 header.DposContext = dposContext.ToProto() 495 496 // Assemble and return the final block for sealing 497 block := types.NewBlock(header, txs, nil, receipts) 498 block.DposContext = dposContext 499 return block, nil 500 */ 501 return sb.dpos.Finalize(chain, header, state, txs, uncles, receipts, dposContext) 502 } 503 504 // Seal generates a new block for the given input block with the local miner's 505 // seal place on top. 506 func (sb *backend) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) { 507 // update the block header timestamp and signature and propose the block to core engine 508 header := block.Header() 509 number := header.Number.Uint64() 510 511 // Bail out if we're unauthorized to sign a block 512 snap, err := sb.snapshot(chain, number-1, header.ParentHash, nil) 513 if err != nil { 514 return nil, err 515 } 516 if _, v := snap.ValSet.GetByAddress(sb.address); v == nil { 517 return nil, errUnauthorized 518 } 519 520 parent := chain.GetHeader(header.ParentHash, number-1) 521 if parent == nil { 522 return nil, consensus.ErrUnknownAncestor 523 } 524 block, err = sb.updateBlock(parent, block) 525 if err != nil { 526 return nil, err 527 } 528 529 // wait for the timestamp of header, use this to adjust the block period 530 delay := time.Unix(block.Header().Time.Int64(), 0).Sub(now()) 531 select { 532 case <-time.After(delay): 533 case <-stop: 534 return nil, nil 535 } 536 537 // get the proposed block hash and clear it if the seal() is completed. 538 sb.sealMu.Lock() 539 sb.proposedBlockHash = block.Hash() 540 clear := func() { 541 sb.proposedBlockHash = common.Hash{} 542 sb.sealMu.Unlock() 543 } 544 defer clear() 545 546 // post block into BFT engine 547 go sb.EventMux().Post(bft.RequestEvent{ 548 Proposal: block, 549 }) 550 551 for { 552 select { 553 case result := <-sb.commitCh: 554 // if the block hash and the hash from channel are the same, 555 // return the result. Otherwise, keep waiting the next hash. 556 if block.Hash() == result.Hash() { 557 return result, nil 558 } 559 case <-stop: 560 return nil, nil 561 } 562 } 563 } 564 565 // update timestamp and signature of the block based on its number of transactions 566 func (sb *backend) updateBlock(parent *types.Header, block *types.Block) (*types.Block, error) { 567 header := block.Header() 568 // sign the hash 569 seal, err := sb.Sign(sigHash(header).Bytes()) 570 if err != nil { 571 return nil, err 572 } 573 574 err = writeSeal(header, seal) 575 if err != nil { 576 return nil, err 577 } 578 579 return block.WithSeal(header), nil 580 } 581 582 // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty 583 // that a new block should have based on the previous blocks in the chain and the 584 // current signer. 585 func (sb *backend) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { 586 587 return defaultDifficulty 588 } 589 590 // APIs returns the RPC APIs this consensus engine provides. 591 func (sb *backend) APIs(chain consensus.ChainReader) []rpc.API { 592 return []rpc.API{{ 593 Namespace: "dbft", 594 Version: "1.0", 595 Service: &API{chain: chain, bft: sb}, 596 Public: true, 597 }} 598 } 599 600 // Start implements consensus.BFT.Start 601 func (sb *backend) Start(chain consensus.ChainReader, currentBlock func() *types.Block, hasBadBlock func(hash common.Hash) bool) error { 602 sb.coreMu.Lock() 603 defer sb.coreMu.Unlock() 604 if sb.coreStarted { 605 return bft.ErrStartedEngine 606 } 607 608 // clear previous data 609 sb.proposedBlockHash = common.Hash{} 610 if sb.commitCh != nil { 611 close(sb.commitCh) 612 } 613 sb.commitCh = make(chan *types.Block, 1) 614 615 sb.chain = chain 616 sb.currentBlock = currentBlock 617 sb.hasBadBlock = hasBadBlock 618 619 if err := sb.core.Start(); err != nil { 620 return err 621 } 622 623 sb.coreStarted = true 624 return nil 625 } 626 627 // Stop implements consensus.BFT.Stop 628 func (sb *backend) Stop() error { 629 sb.coreMu.Lock() 630 defer sb.coreMu.Unlock() 631 if !sb.coreStarted { 632 return bft.ErrStoppedEngine 633 } 634 if err := sb.core.Stop(); err != nil { 635 return err 636 } 637 sb.coreStarted = false 638 return nil 639 } 640 641 // snapshot retrieves the authorization snapshot at a given point in time. 642 func (sb *backend) snapshot(chain consensus.ChainReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) { 643 // Search for a snapshot in memory or on disk for checkpoints 644 var ( 645 headers []*types.Header 646 snap *Snapshot 647 ) 648 for snap == nil { 649 // If an in-memory snapshot was found, use that 650 if s, ok := sb.recents.Get(hash); ok { 651 snap = s.(*Snapshot) 652 break 653 } 654 // If an on-disk checkpoint snapshot can be found, use that 655 if number%checkpointInterval == 0 { 656 if s, err := loadSnapshot(sb.config.Epoch, sb.db, hash); err == nil { 657 log.Trace("Loaded voting snapshot form disk", "number", number, "hash", hash) 658 snap = s 659 break 660 } 661 } 662 // If we're at block zero, make a snapshot 663 if number == 0 { 664 genesis := chain.GetHeaderByNumber(0) 665 if err := sb.VerifyHeader(chain, genesis, false); err != nil { 666 return nil, err 667 } 668 bftExtra, err := types.ExtractBFTExtra(genesis) 669 if err != nil { 670 return nil, err 671 } 672 673 dposContext, err := types.NewDposContextFromProto(sb.db, genesis.DposContext) 674 if err != nil { 675 return nil, err 676 } 677 678 snap = newSnapshot(sb.config.Epoch, 0, genesis.Hash(), validator.NewSet(bftExtra.Validators, sb.config.ProposerPolicy), dposContext, nil) 679 if err := snap.store(sb.db); err != nil { 680 return nil, err 681 } 682 log.Trace("Stored genesis voting snapshot to disk") 683 break 684 } 685 // No snapshot for this header, gather the header and move backward 686 var header *types.Header 687 if len(parents) > 0 { 688 // If we have explicit parents, pick from there (enforced) 689 header = parents[len(parents)-1] 690 if header.Hash() != hash || header.Number.Uint64() != number { 691 return nil, consensus.ErrUnknownAncestor 692 } 693 parents = parents[:len(parents)-1] 694 } else { 695 // No explicit parents (or no more left), reach out to the database 696 header = chain.GetHeader(hash, number) 697 if header == nil { 698 return nil, consensus.ErrUnknownAncestor 699 } 700 } 701 702 //FIXME: 703 if number > 0 { 704 dposContext, err := types.NewDposContextFromProto(sb.db, header.DposContext) 705 if err != nil { 706 return nil, err 707 } 708 709 bftExtra, err := types.ExtractBFTExtra(header) 710 if err != nil { 711 return nil, err 712 } 713 snap = newSnapshot(sb.config.Epoch, number-1, header.Hash(), validator.NewSet(bftExtra.Validators, sb.config.ProposerPolicy), dposContext, nil) 714 } 715 716 headers = append(headers, header) 717 number, hash = number-1, header.ParentHash 718 } 719 // Previous snapshot found, apply any pending headers on top of it 720 for i := 0; i < len(headers)/2; i++ { 721 headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i] 722 } 723 724 725 726 snap, err := snap.apply(headers) 727 if err != nil { 728 return nil, err 729 } 730 sb.recents.Add(snap.Hash, snap) 731 732 // // get recent block signers list 733 // curHeader := chain.GetHeaderByHash(hash) 734 // if curHeader == nil { 735 // return nil, ErrNilBlockHeader 736 // } 737 738 // for curHeader.Number.Uint64() > 0 && len(snap.Recents) < (len(snap.Signers)/2+1) && (curHeader.Number.Uint64()%sb.config.Epoch) != 0 { 739 740 // snap.Recents[curHeader.Number.Uint64()] = curHeader.Coinbase 741 742 // curHeader = chain.GetHeaderByHash(curHeader.ParentHash) 743 // if curHeader == nil { 744 // return nil, ErrNilBlockHeader 745 // } 746 // } 747 748 // If we've generated a new checkpoint snapshot, save to disk 749 if snap.Number%checkpointInterval == 0 && len(headers) > 0 { 750 if err = snap.store(sb.db); err != nil { 751 return nil, err 752 } 753 log.Trace("Stored voting snapshot to disk", "number", snap.Number, "hash", snap.Hash) 754 } 755 return snap, err 756 } 757 758 // FIXME: Need to update this for BFT 759 // sigHash returns the hash which is used as input for the BFT 760 // signing. It is the hash of the entire header apart from the 65 byte signature 761 // contained at the end of the extra data. 762 // 763 // Note, the method requires the extra data to be at least 65 bytes, otherwise it 764 // panics. This is done to avoid accidentally using both forms (signature present 765 // or not), which could be abused to produce different hashes for the same header. 766 func sigHash(header *types.Header) (hash common.Hash) { 767 hasher := sha3.NewKeccak256() 768 769 // Clean seal is required for calculating proposer seal. 770 rlp.Encode(hasher, types.BFTFilteredHeader(header, false)) 771 hasher.Sum(hash[:0]) 772 return hash 773 } 774 775 // ecrecover extracts the Ethereum account address from a signed header. 776 func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { 777 hash := header.Hash() 778 if addr, ok := sigcache.Get(hash); ok { 779 return addr.(common.Address), nil 780 } 781 782 // Retrieve the signature from the header extra-data 783 bftExtra, err := types.ExtractBFTExtra(header) 784 if err != nil { 785 return common.Address{}, err 786 } 787 788 addr, err := bft.GetSignatureAddress(sigHash(header).Bytes(), bftExtra.Seal) 789 if err != nil { 790 return addr, err 791 } 792 sigcache.Add(hash, addr) 793 return addr, nil 794 } 795 796 // prepareExtra returns a extra-data of the given header and validators 797 func prepareExtra(header *types.Header, vals []common.Address) ([]byte, error) { 798 var buf bytes.Buffer 799 800 // compensate the lack bytes if header.Extra is not enough BFTExtraVanity bytes. 801 if len(header.Extra) < types.BFTExtraVanity { 802 header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, types.BFTExtraVanity-len(header.Extra))...) 803 } 804 buf.Write(header.Extra[:types.BFTExtraVanity]) 805 806 ist := &types.BFTExtra{ 807 Validators: vals, 808 Seal: []byte{}, 809 CommittedSeal: [][]byte{}, 810 } 811 812 payload, err := rlp.EncodeToBytes(&ist) 813 if err != nil { 814 return nil, err 815 } 816 817 return append(buf.Bytes(), payload...), nil 818 } 819 820 // writeSeal writes the extra-data field of the given header with the given seals. 821 // suggest to rename to writeSeal. 822 func writeSeal(h *types.Header, seal []byte) error { 823 if len(seal)%types.BFTExtraSeal != 0 { 824 return errInvalidSignature 825 } 826 827 bftExtra, err := types.ExtractBFTExtra(h) 828 if err != nil { 829 return err 830 } 831 832 bftExtra.Seal = seal 833 payload, err := rlp.EncodeToBytes(&bftExtra) 834 if err != nil { 835 return err 836 } 837 838 h.Extra = append(h.Extra[:types.BFTExtraVanity], payload...) 839 return nil 840 } 841 842 // writeCommittedSeals writes the extra-data field of a block header with given committed seals. 843 func writeCommittedSeals(h *types.Header, committedSeals [][]byte) error { 844 if len(committedSeals) == 0 { 845 return errInvalidCommittedSeals 846 } 847 848 for _, seal := range committedSeals { 849 if len(seal) != types.BFTExtraSeal { 850 return errInvalidCommittedSeals 851 } 852 } 853 854 bftExtra, err := types.ExtractBFTExtra(h) 855 if err != nil { 856 return err 857 } 858 859 bftExtra.CommittedSeal = make([][]byte, len(committedSeals)) 860 copy(bftExtra.CommittedSeal, committedSeals) 861 862 payload, err := rlp.EncodeToBytes(&bftExtra) 863 if err != nil { 864 return err 865 } 866 867 h.Extra = append(h.Extra[:types.BFTExtraVanity], payload...) 868 return nil 869 } 870