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