github.com/klaytn/klaytn@v1.12.1/consensus/istanbul/backend/engine.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2017 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from quorum/consensus/istanbul/backend/engine.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package backend 22 23 import ( 24 "bytes" 25 "encoding/hex" 26 "encoding/json" 27 "errors" 28 "math/big" 29 "time" 30 31 lru "github.com/hashicorp/golang-lru" 32 "github.com/klaytn/klaytn/blockchain/state" 33 "github.com/klaytn/klaytn/blockchain/system" 34 "github.com/klaytn/klaytn/blockchain/types" 35 "github.com/klaytn/klaytn/common" 36 "github.com/klaytn/klaytn/consensus" 37 "github.com/klaytn/klaytn/consensus/istanbul" 38 istanbulCore "github.com/klaytn/klaytn/consensus/istanbul/core" 39 "github.com/klaytn/klaytn/consensus/istanbul/validator" 40 "github.com/klaytn/klaytn/consensus/misc" 41 "github.com/klaytn/klaytn/crypto/sha3" 42 "github.com/klaytn/klaytn/networks/rpc" 43 "github.com/klaytn/klaytn/params" 44 "github.com/klaytn/klaytn/reward" 45 "github.com/klaytn/klaytn/rlp" 46 ) 47 48 const ( 49 // CheckpointInterval = 1024 // Number of blocks after which to save the vote snapshot to the database 50 // inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory 51 // inmemoryPeers = 40 52 // inmemoryMessages = 1024 53 54 inmemorySnapshots = 496 // Number of recent vote snapshots to keep in memory 55 inmemoryPeers = 200 56 inmemoryMessages = 4096 57 58 allowedFutureBlockTime = 1 * time.Second // Max time from current time allowed for blocks, before they're considered future blocks 59 ) 60 61 var ( 62 // errInvalidProposal is returned when a prposal is malformed. 63 errInvalidProposal = errors.New("invalid proposal") 64 // errInvalidSignature is returned when given signature is not signed by given 65 // address. 66 errInvalidSignature = errors.New("invalid signature") 67 // errUnknownBlock is returned when the list of validators is requested for a block 68 // that is not part of the local blockchain. 69 errUnknownBlock = errors.New("unknown block") 70 // errUnauthorized is returned if a header is signed by a non authorized entity. 71 errUnauthorized = errors.New("unauthorized") 72 // errInvalidBlockScore is returned if the BlockScore of a block is not 1 73 errInvalidBlockScore = errors.New("invalid blockscore") 74 // errInvalidExtraDataFormat is returned when the extra data format is incorrect 75 errInvalidExtraDataFormat = errors.New("invalid extra data format") 76 // errInvalidTimestamp is returned if the timestamp of a block is lower than the previous block's timestamp + the minimum block period. 77 errInvalidTimestamp = errors.New("invalid timestamp") 78 // errInvalidVotingChain is returned if an authorization list is attempted to 79 // be modified via out-of-range or non-contiguous headers. 80 errInvalidVotingChain = errors.New("invalid voting chain") 81 // errInvalidCommittedSeals is returned if the committed seal is not signed by any of parent validators. 82 errInvalidCommittedSeals = errors.New("invalid committed seals") 83 // errEmptyCommittedSeals is returned if the field of committed seals is zero. 84 errEmptyCommittedSeals = errors.New("zero committed seals") 85 // errMismatchTxhashes is returned if the TxHash in header is mismatch. 86 errMismatchTxhashes = errors.New("mismatch transactions hashes") 87 // errNoBlsKey is returned if the BLS secret key is not configured. 88 errNoBlsKey = errors.New("bls key not configured") 89 // errNoBlsPub is returned if the BLS public key is not found for the proposer. 90 errNoBlsPub = errors.New("bls pubkey not found for the proposer") 91 // errInvalidRandaoFields is returned if the Randao fields randomReveal or mixHash are invalid. 92 errInvalidRandaoFields = errors.New("invalid randao fields") 93 // errUnexpectedRandao is returned if the Randao fields randomReveal or mixHash are present when must not. 94 errUnexpectedRandao = errors.New("unexpected randao fields") 95 ) 96 97 var ( 98 defaultBlockScore = big.NewInt(1) 99 now = time.Now 100 101 inmemoryBlocks = 2048 // Number of blocks to precompute validators' addresses 102 inmemoryValidatorsPerBlock = 30 // Approximate number of validators' addresses from ecrecover 103 signatureAddresses, _ = lru.NewARC(inmemoryBlocks * inmemoryValidatorsPerBlock) 104 ) 105 106 // cacheSignatureAddresses extracts the address from the given data and signature and cache them for later usage. 107 func cacheSignatureAddresses(data []byte, sig []byte) (common.Address, error) { 108 sigStr := hex.EncodeToString(sig) 109 if addr, ok := signatureAddresses.Get(sigStr); ok { 110 return addr.(common.Address), nil 111 } 112 addr, err := istanbul.GetSignatureAddress(data, sig) 113 if err != nil { 114 return common.Address{}, err 115 } 116 signatureAddresses.Add(sigStr, addr) 117 return addr, err 118 } 119 120 // Author retrieves the Klaytn address of the account that minted the given block. 121 func (sb *backend) Author(header *types.Header) (common.Address, error) { 122 return ecrecover(header) 123 } 124 125 // CanVerifyHeadersConcurrently returns true if concurrent header verification possible, otherwise returns false. 126 func (sb *backend) CanVerifyHeadersConcurrently() bool { 127 return false 128 } 129 130 // PreprocessHeaderVerification prepares header verification for heavy computation before synchronous header verification such as ecrecover. 131 func (sb *backend) PreprocessHeaderVerification(headers []*types.Header) (chan<- struct{}, <-chan error) { 132 abort := make(chan struct{}) 133 results := make(chan error, inmemoryBlocks) 134 go func() { 135 for _, header := range headers { 136 err := sb.computeSignatureAddrs(header) 137 138 select { 139 case <-abort: 140 return 141 case results <- err: 142 } 143 } 144 }() 145 return abort, results 146 } 147 148 // computeSignatureAddrs computes the addresses of signer and validators and caches them. 149 func (sb *backend) computeSignatureAddrs(header *types.Header) error { 150 _, err := ecrecover(header) 151 if err != nil { 152 return err 153 } 154 155 // Retrieve the signature from the header extra-data 156 istanbulExtra, err := types.ExtractIstanbulExtra(header) 157 if err != nil { 158 return err 159 } 160 161 proposalSeal := istanbulCore.PrepareCommittedSeal(header.Hash()) 162 for _, seal := range istanbulExtra.CommittedSeal { 163 _, err := cacheSignatureAddresses(proposalSeal, seal) 164 if err != nil { 165 return errInvalidSignature 166 } 167 } 168 return nil 169 } 170 171 // VerifyHeader checks whether a header conforms to the consensus rules of a 172 // given engine. Verifying the seal may be done optionally here, or explicitly 173 // via the VerifySeal method. 174 func (sb *backend) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { 175 var parent []*types.Header 176 if header.Number.Sign() == 0 { 177 // If current block is genesis, the parent is also genesis 178 parent = append(parent, chain.GetHeaderByNumber(0)) 179 } else { 180 parent = append(parent, chain.GetHeader(header.ParentHash, header.Number.Uint64()-1)) 181 } 182 return sb.verifyHeader(chain, header, parent) 183 } 184 185 // verifyHeader checks whether a header conforms to the consensus rules.The 186 // caller may optionally pass in a batch of parents (ascending order) to avoid 187 // looking those up from the database. This is useful for concurrently verifying 188 // a batch of new headers. 189 func (sb *backend) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 190 if header.Number == nil { 191 return errUnknownBlock 192 } 193 194 // Header verify before/after magma fork 195 if chain.Config().IsMagmaForkEnabled(header.Number) { 196 // the kip71Config used when creating the block number is a previous block config. 197 blockNum := header.Number.Uint64() 198 pset, err := sb.governance.EffectiveParams(blockNum) 199 if err != nil { 200 return err 201 } 202 203 kip71 := pset.ToKIP71Config() 204 if err := misc.VerifyMagmaHeader(parents[len(parents)-1], header, kip71); err != nil { 205 return err 206 } 207 } else if header.BaseFee != nil { 208 return consensus.ErrInvalidBaseFee 209 } 210 211 // Don't waste time checking blocks from the future 212 if header.Time.Cmp(big.NewInt(now().Add(allowedFutureBlockTime).Unix())) > 0 { 213 return consensus.ErrFutureBlock 214 } 215 216 // Ensure that the extra data format is satisfied 217 if _, err := types.ExtractIstanbulExtra(header); err != nil { 218 return errInvalidExtraDataFormat 219 } 220 // Ensure that the block's blockscore is meaningful (may not be correct at this point) 221 if header.BlockScore == nil || header.BlockScore.Cmp(defaultBlockScore) != 0 { 222 return errInvalidBlockScore 223 } 224 225 return sb.verifyCascadingFields(chain, header, parents) 226 } 227 228 // verifyCascadingFields verifies all the header fields that are not standalone, 229 // rather depend on a batch of previous headers. The caller may optionally pass 230 // in a batch of parents (ascending order) to avoid looking those up from the 231 // database. This is useful for concurrently verifying a batch of new headers. 232 func (sb *backend) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 233 // The genesis block is the always valid dead-end 234 number := header.Number.Uint64() 235 if number == 0 { 236 return nil 237 } 238 // Ensure that the block's timestamp isn't too close to it's parent 239 var parent *types.Header 240 if len(parents) > 0 { 241 parent = parents[len(parents)-1] 242 } else { 243 parent = chain.GetHeader(header.ParentHash, number-1) 244 } 245 if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { 246 return consensus.ErrUnknownAncestor 247 } 248 if parent.Time.Uint64()+sb.config.BlockPeriod > header.Time.Uint64() { 249 return errInvalidTimestamp 250 } 251 if err := sb.verifySigner(chain, header, parents); err != nil { 252 return err 253 } 254 255 // VerifyRandao must be after verifySigner because it needs the signer (proposer) address 256 if chain.Config().IsRandaoForkEnabled(header.Number) { 257 prevMixHash := headerMixHash(chain, parent) 258 if err := sb.VerifyRandao(chain, header, prevMixHash); err != nil { 259 return err 260 } 261 } else if header.RandomReveal != nil || header.MixHash != nil { 262 return errUnexpectedRandao 263 } 264 265 // At every epoch governance data will come in block header. Verify it. 266 pset, err := sb.governance.EffectiveParams(number) 267 if err != nil { 268 return err 269 } 270 pendingBlockNum := new(big.Int).Add(chain.CurrentHeader().Number, common.Big1) 271 if number%pset.Epoch() == 0 && len(header.Governance) > 0 && pendingBlockNum.Cmp(header.Number) == 0 { 272 if err := sb.governance.VerifyGovernance(header.Governance); err != nil { 273 return err 274 } 275 } 276 return sb.verifyCommittedSeals(chain, header, parents) 277 } 278 279 // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers 280 // concurrently. The method returns a quit channel to abort the operations and 281 // a results channel to retrieve the async verifications (the order is that of 282 // the input slice). 283 func (sb *backend) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { 284 abort := make(chan struct{}) 285 results := make(chan error, len(headers)) 286 go func() { 287 for i, header := range headers { 288 err := sb.verifyHeader(chain, header, headers[:i]) 289 290 select { 291 case <-abort: 292 return 293 case results <- err: 294 } 295 } 296 }() 297 return abort, results 298 } 299 300 // verifySigner checks whether the signer is in parent's validator set 301 func (sb *backend) verifySigner(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 302 // Verifying the genesis block is not supported 303 number := header.Number.Uint64() 304 if number == 0 { 305 return errUnknownBlock 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, true) 310 if err != nil { 311 return err 312 } 313 314 // resolve the authorization key and check against signers 315 signer, err := ecrecover(header) 316 if err != nil { 317 return err 318 } 319 320 // Signer should be in the validator set of previous block's extraData. 321 if _, v := snap.ValSet.GetByAddress(signer); v == nil { 322 return errUnauthorized 323 } 324 return nil 325 } 326 327 // verifyCommittedSeals checks whether every committed seal is signed by one of the parent's validators 328 func (sb *backend) verifyCommittedSeals(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 329 number := header.Number.Uint64() 330 // We don't need to verify committed seals in the genesis block 331 if number == 0 { 332 return nil 333 } 334 335 // Retrieve the snapshot needed to verify this header and cache it 336 snap, err := sb.snapshot(chain, number-1, header.ParentHash, parents, true) 337 if err != nil { 338 return err 339 } 340 341 extra, err := types.ExtractIstanbulExtra(header) 342 if err != nil { 343 return err 344 } 345 // The length of Committed seals should be larger than 0 346 if len(extra.CommittedSeal) == 0 { 347 return errEmptyCommittedSeals 348 } 349 350 validators := snap.ValSet.Copy() 351 // Check whether the committed seals are generated by parent's validators 352 validSeal := 0 353 proposalSeal := istanbulCore.PrepareCommittedSeal(header.Hash()) 354 // 1. Get committed seals from current header 355 for _, seal := range extra.CommittedSeal { 356 // 2. Get the original address by seal and parent block hash 357 addr, err := cacheSignatureAddresses(proposalSeal, seal) 358 if err != nil { 359 return errInvalidSignature 360 } 361 // Every validator can have only one seal. If more than one seals are signed by a 362 // validator, the validator cannot be found and errInvalidCommittedSeals is returned. 363 if validators.RemoveValidator(addr) { 364 validSeal += 1 365 } else { 366 return errInvalidCommittedSeals 367 } 368 } 369 370 // The length of validSeal should be larger than number of faulty node + 1 371 if validSeal <= 2*snap.ValSet.F() { 372 return errInvalidCommittedSeals 373 } 374 375 return nil 376 } 377 378 // VerifySeal checks whether the crypto seal on a header is valid according to 379 // the consensus rules of the given engine. 380 func (sb *backend) VerifySeal(chain consensus.ChainReader, header *types.Header) error { 381 // get parent header and ensure the signer is in parent's validator set 382 number := header.Number.Uint64() 383 if number == 0 { 384 return errUnknownBlock 385 } 386 387 // ensure that the blockscore equals to defaultBlockScore 388 if header.BlockScore.Cmp(defaultBlockScore) != 0 { 389 return errInvalidBlockScore 390 } 391 return sb.verifySigner(chain, header, nil) 392 } 393 394 // Prepare initializes the consensus fields of a block header according to the 395 // rules of a particular engine. The changes are executed inline. 396 func (sb *backend) Prepare(chain consensus.ChainReader, header *types.Header) error { 397 // unused fields, force to set to empty 398 header.Rewardbase = sb.rewardbase 399 400 // copy the parent extra data as the header extra data 401 number := header.Number.Uint64() 402 parent := chain.GetHeader(header.ParentHash, number-1) 403 if parent == nil { 404 return consensus.ErrUnknownAncestor 405 } 406 // use the same blockscore for all blocks 407 header.BlockScore = defaultBlockScore 408 409 // Assemble the voting snapshot 410 snap, err := sb.snapshot(chain, number-1, header.ParentHash, nil, true) 411 if err != nil { 412 return err 413 } 414 415 // If it reaches the Epoch, governance config will be added to block header 416 pset, err := sb.governance.EffectiveParams(number) 417 if err != nil { 418 return err 419 } 420 if number%pset.Epoch() == 0 { 421 if g := sb.governance.GetGovernanceChange(); g != nil { 422 if data, err := json.Marshal(g); err != nil { 423 logger.Error("Failed to encode governance changes!! Possible configuration mismatch!! ") 424 } else { 425 if header.Governance, err = rlp.EncodeToBytes(data); err != nil { 426 logger.Error("Failed to encode governance data for the header", "num", number) 427 } else { 428 logger.Info("Put governanceData", "num", number, "data", hex.EncodeToString(header.Governance)) 429 } 430 } 431 } 432 } 433 434 // if there is a vote to attach, attach it to the header 435 header.Vote = sb.governance.GetEncodedVote(sb.address, number) 436 if len(header.Vote) > 0 { 437 logger.Info("Put voteData", "num", number, "data", hex.EncodeToString(header.Vote)) 438 } 439 440 if chain.Config().IsRandaoForkEnabled(header.Number) { 441 prevMixHash := headerMixHash(chain, parent) 442 randomReveal, mixHash, err := sb.CalcRandao(header.Number, prevMixHash) 443 if err != nil { 444 return err 445 } 446 header.RandomReveal = randomReveal 447 header.MixHash = mixHash 448 } 449 450 // add validators (council list) in snapshot to extraData's validators section 451 extra, err := prepareExtra(header, snap.validators()) 452 if err != nil { 453 return err 454 } 455 header.Extra = extra 456 457 // set header's timestamp 458 header.Time = new(big.Int).Add(parent.Time, new(big.Int).SetUint64(sb.config.BlockPeriod)) 459 header.TimeFoS = parent.TimeFoS 460 if header.Time.Int64() < time.Now().Unix() { 461 t := time.Now() 462 header.Time = big.NewInt(t.Unix()) 463 header.TimeFoS = uint8((t.UnixNano() / 1000 / 1000 / 10) % 100) 464 } 465 return nil 466 } 467 468 // Finalize runs any post-transaction state modifications (e.g. block rewards) 469 // and assembles the final block. 470 // 471 // Note, the block header and state database might be updated to reflect any 472 // consensus rules that happen at finalization (e.g. block rewards). 473 func (sb *backend) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, 474 receipts []*types.Receipt, 475 ) (*types.Block, error) { 476 // We can assure that if the magma hard forked block should have the field of base fee 477 if chain.Config().IsMagmaForkEnabled(header.Number) { 478 if header.BaseFee == nil { 479 logger.Error("Magma hard forked block should have baseFee", "blockNum", header.Number.Uint64()) 480 return nil, errors.New("Invalid Magma block without baseFee") 481 } 482 } else if header.BaseFee != nil { 483 logger.Error("A block before Magma hardfork shouldn't have baseFee", "blockNum", header.Number.Uint64()) 484 return nil, consensus.ErrInvalidBaseFee 485 } 486 487 var rewardSpec *reward.RewardSpec 488 489 rules := chain.Config().Rules(header.Number) 490 pset, err := sb.governance.EffectiveParams(header.Number.Uint64()) 491 if err != nil { 492 return nil, err 493 } 494 495 // If sb.chain is nil, it means backend is not initialized yet. 496 if sb.chain != nil && !reward.IsRewardSimple(pset) { 497 // TODO-Klaytn Let's redesign below logic and remove dependency between block reward and istanbul consensus. 498 499 lastHeader := chain.CurrentHeader() 500 valSet := sb.getValidators(lastHeader.Number.Uint64(), lastHeader.Hash()) 501 502 // Determine and update Rewardbase when mining. When mining, state root is not yet determined and will be determined at the end of this Finalize below. 503 if common.EmptyHash(header.Root) { 504 var logMsg string 505 _, nodeValidator := valSet.GetByAddress(sb.address) 506 if nodeValidator == nil || (nodeValidator.RewardAddress() == common.Address{}) { 507 logMsg = "No reward address for nodeValidator. Use node's rewardbase." 508 } else { 509 // use reward address of current node. 510 // only a block made by proposer will be accepted. However, due to round change any node can be the proposer of a block. 511 // so need to write reward address of current node to receive reward when it becomes proposer. 512 // if current node does not become proposer, the block will be abandoned 513 header.Rewardbase = nodeValidator.RewardAddress() 514 logMsg = "Use reward address for nodeValidator." 515 } 516 logger.Trace(logMsg, "header.Number", header.Number.Uint64(), "node address", sb.address, "rewardbase", header.Rewardbase) 517 } 518 519 rewardSpec, err = reward.CalcDeferredReward(header, rules, pset) 520 } else { 521 rewardSpec, err = reward.CalcDeferredRewardSimple(header, rules, pset) 522 } 523 524 if err != nil { 525 return nil, err 526 } 527 528 reward.DistributeBlockReward(state, rewardSpec.Rewards) 529 530 // Only on the KIP-103 hardfork block, the following logic should be executed 531 if chain.Config().IsKIP103ForkBlock(header.Number) { 532 // RebalanceTreasury can modify the global state (state), 533 // so the existing state db should be used to apply the rebalancing result. 534 c := &Kip103ContractCaller{state, chain, header} 535 result, err := RebalanceTreasury(state, chain, header, c) 536 if err != nil { 537 logger.Error("failed to execute treasury rebalancing (KIP-103). State not changed", "err", err) 538 } else { 539 memo, err := json.Marshal(result) 540 if err != nil { 541 logger.Warn("failed to marshal KIP-103 result", "err", err, "result", result) 542 } 543 logger.Info("successfully executed treasury rebalancing (KIP-103)", "memo", string(memo)) 544 } 545 } 546 547 // The Registry contract must be immediately available from the fork block. 548 // So it is installed at block (RandaoCompatibleBlock - 1) which is before the fork block. 549 if chain.Config().IsRandaoForkBlock(header.Number) { 550 err := system.InstallRegistry(state, chain.Config().RandaoRegistry) 551 if err != nil { 552 return nil, err 553 } 554 } 555 556 header.Root = state.IntermediateRoot(true) 557 558 // Assemble and return the final block for sealing 559 return types.NewBlock(header, txs, receipts), nil 560 } 561 562 // Seal generates a new block for the given input block with the local miner's 563 // seal place on top. 564 func (sb *backend) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) { 565 // update the block header timestamp and signature and propose the block to core engine 566 header := block.Header() 567 number := header.Number.Uint64() 568 569 // Bail out if we're unauthorized to sign a block 570 snap, err := sb.snapshot(chain, number-1, header.ParentHash, nil, true) 571 if err != nil { 572 return nil, err 573 } 574 if _, v := snap.ValSet.GetByAddress(sb.address); v == nil { 575 return nil, errUnauthorized 576 } 577 578 parent := chain.GetHeader(header.ParentHash, number-1) 579 if parent == nil { 580 return nil, consensus.ErrUnknownAncestor 581 } 582 block, err = sb.updateBlock(block) 583 if err != nil { 584 return nil, err 585 } 586 587 // wait for the timestamp of header, use this to adjust the block period 588 delay := time.Unix(block.Header().Time.Int64(), 0).Sub(now()) 589 select { 590 case <-time.After(delay): 591 case <-stop: 592 return nil, nil 593 } 594 595 // get the proposed block hash and clear it if the seal() is completed. 596 sb.sealMu.Lock() 597 sb.proposedBlockHash = block.Hash() 598 clear := func() { 599 sb.proposedBlockHash = common.Hash{} 600 sb.sealMu.Unlock() 601 } 602 defer clear() 603 604 // post block into Istanbul engine 605 go sb.EventMux().Post(istanbul.RequestEvent{ 606 Proposal: block, 607 }) 608 609 for { 610 select { 611 case result := <-sb.commitCh: 612 if result == nil { 613 return nil, nil 614 } 615 // if the block hash and the hash from channel are the same, 616 // return the result. Otherwise, keep waiting the next hash. 617 block = types.SetRoundToBlock(block, result.Round) 618 if block.Hash() == result.Block.Hash() { 619 return result.Block, nil 620 } 621 case <-stop: 622 return nil, nil 623 } 624 } 625 } 626 627 // update timestamp and signature of the block based on its number of transactions 628 func (sb *backend) updateBlock(block *types.Block) (*types.Block, error) { 629 header := block.Header() 630 // sign the hash 631 seal, err := sb.Sign(sigHash(header).Bytes()) 632 if err != nil { 633 return nil, err 634 } 635 636 err = writeSeal(header, seal) 637 if err != nil { 638 return nil, err 639 } 640 641 return block.WithSeal(header), nil 642 } 643 644 func (sb *backend) CalcBlockScore(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { 645 return big.NewInt(0) 646 } 647 648 // APIs returns the RPC APIs this consensus engine provides. 649 func (sb *backend) APIs(chain consensus.ChainReader) []rpc.API { 650 return []rpc.API{ 651 { 652 Namespace: "istanbul", 653 Version: "1.0", 654 Service: &API{chain: chain, istanbul: sb}, 655 Public: true, 656 }, { 657 Namespace: "klay", 658 Version: "1.0", 659 Service: &APIExtension{chain: chain, istanbul: sb}, 660 Public: true, 661 }, 662 } 663 } 664 665 // SetChain sets chain of the Istanbul backend 666 func (sb *backend) SetChain(chain consensus.ChainReader) { 667 sb.chain = chain 668 } 669 670 // Start implements consensus.Istanbul.Start 671 func (sb *backend) Start(chain consensus.ChainReader, currentBlock func() *types.Block, hasBadBlock func(hash common.Hash) bool) error { 672 sb.coreMu.Lock() 673 defer sb.coreMu.Unlock() 674 if sb.coreStarted { 675 return istanbul.ErrStartedEngine 676 } 677 678 // clear previous data 679 sb.proposedBlockHash = common.Hash{} 680 if sb.commitCh != nil { 681 close(sb.commitCh) 682 } 683 sb.commitCh = make(chan *types.Result, 1) 684 685 sb.SetChain(chain) 686 sb.currentBlock = currentBlock 687 sb.hasBadBlock = hasBadBlock 688 689 if err := sb.core.Start(); err != nil { 690 return err 691 } 692 693 sb.coreStarted = true 694 return nil 695 } 696 697 // Stop implements consensus.Istanbul.Stop 698 func (sb *backend) Stop() error { 699 sb.coreMu.Lock() 700 defer sb.coreMu.Unlock() 701 if !sb.coreStarted { 702 return istanbul.ErrStoppedEngine 703 } 704 if err := sb.core.Stop(); err != nil { 705 return err 706 } 707 sb.coreStarted = false 708 return nil 709 } 710 711 // UpdateParam implements consensus.Istanbul.UpdateParam and it updates the governance parameters 712 func (sb *backend) UpdateParam(number uint64) error { 713 if err := sb.governance.UpdateParams(number); err != nil { 714 return err 715 } 716 return nil 717 } 718 719 // initSnapshot initializes and stores a new Snapshot. 720 func (sb *backend) initSnapshot(chain consensus.ChainReader) (*Snapshot, error) { 721 genesis := chain.GetHeaderByNumber(0) 722 if err := sb.VerifyHeader(chain, genesis, false); err != nil { 723 return nil, err 724 } 725 istanbulExtra, err := types.ExtractIstanbulExtra(genesis) 726 if err != nil { 727 return nil, err 728 } 729 730 pset, err := sb.governance.EffectiveParams(0) 731 if err != nil { 732 return nil, err 733 } 734 valSet := validator.NewValidatorSet(istanbulExtra.Validators, nil, 735 istanbul.ProposerPolicy(pset.Policy()), 736 pset.CommitteeSize(), chain) 737 valSet.SetMixHash(genesis.MixHash) 738 snap := newSnapshot(sb.governance, 0, genesis.Hash(), valSet, chain.Config()) 739 740 if err := snap.store(sb.db); err != nil { 741 return nil, err 742 } 743 logger.Trace("Stored genesis voting snapshot to disk") 744 return snap, nil 745 } 746 747 // getPrevHeaderAndUpdateParents returns previous header to find stored Snapshot object and drops the last element of the parents parameter. 748 func getPrevHeaderAndUpdateParents(chain consensus.ChainReader, number uint64, hash common.Hash, parents *[]*types.Header) *types.Header { 749 var header *types.Header 750 if len(*parents) > 0 { 751 // If we have explicit parents, pick from there (enforced) 752 header = (*parents)[len(*parents)-1] 753 if header.Hash() != hash || header.Number.Uint64() != number { 754 return nil 755 } 756 *parents = (*parents)[:len(*parents)-1] 757 } else { 758 // No explicit parents (or no more left), reach out to the database 759 header = chain.GetHeader(hash, number) 760 if header == nil { 761 return nil 762 } 763 } 764 return header 765 } 766 767 // CreateSnapshot does not return a snapshot but creates a new snapshot if not exists at a given point in time 768 func (sb *backend) CreateSnapshot(chain consensus.ChainReader, number uint64, hash common.Hash, parents []*types.Header) error { 769 if _, err := sb.snapshot(chain, number, hash, parents, true); err != nil { 770 return err 771 } 772 return nil 773 } 774 775 // GetConsensusInfo returns consensus information regarding the given block number. 776 func (sb *backend) GetConsensusInfo(block *types.Block) (consensus.ConsensusInfo, error) { 777 blockNumber := block.NumberU64() 778 if blockNumber == 0 { 779 return consensus.ConsensusInfo{}, nil 780 } 781 782 round := block.Header().Round() 783 view := &istanbul.View{ 784 Sequence: new(big.Int).Set(block.Number()), 785 Round: new(big.Int).SetInt64(int64(round)), 786 } 787 788 // get the proposer of this block. 789 proposer, err := ecrecover(block.Header()) 790 if err != nil { 791 return consensus.ConsensusInfo{}, err 792 } 793 794 if sb.chain == nil { 795 return consensus.ConsensusInfo{}, errNoChainReader 796 } 797 798 // get the snapshot of the previous block. 799 parentHash := block.ParentHash() 800 snap, err := sb.snapshot(sb.chain, blockNumber-1, parentHash, nil, false) 801 if err != nil { 802 logger.Error("Failed to get snapshot.", "blockNum", blockNumber, "err", err) 803 return consensus.ConsensusInfo{}, errInternalError 804 } 805 806 // get origin proposer at 0 round. 807 originProposer := common.Address{} 808 lastProposer := sb.GetProposer(blockNumber - 1) 809 810 newValSet := snap.ValSet.Copy() 811 newValSet.CalcProposer(lastProposer, 0) 812 originProposer = newValSet.GetProposer().Address() 813 814 // get the committee list of this block at the view (blockNumber, round) 815 committee := snap.ValSet.SubListWithProposer(parentHash, proposer, view) 816 committeeAddrs := make([]common.Address, len(committee)) 817 for i, v := range committee { 818 committeeAddrs[i] = v.Address() 819 } 820 821 // get the committers of this block from committed seals 822 extra, err := types.ExtractIstanbulExtra(block.Header()) 823 if err != nil { 824 return consensus.ConsensusInfo{}, err 825 } 826 committers, err := RecoverCommittedSeals(extra, block.Hash()) 827 if err != nil { 828 return consensus.ConsensusInfo{}, err 829 } 830 831 // Uncomment to validate if committers are in the committee 832 // for _, recovered := range committers { 833 // found := false 834 // for _, calculated := range committeeAddrs { 835 // if recovered == calculated { 836 // found = true 837 // } 838 // } 839 // if !found { 840 // return consensus.ConsensusInfo{}, errInvalidCommittedSeals 841 // } 842 // } 843 844 cInfo := consensus.ConsensusInfo{ 845 SigHash: sigHash(block.Header()), 846 Proposer: proposer, 847 OriginProposer: originProposer, 848 Committee: committeeAddrs, 849 Committers: committers, 850 Round: round, 851 } 852 853 return cInfo, nil 854 } 855 856 func (sb *backend) InitSnapshot() { 857 sb.recents.Purge() 858 sb.blsPubkeyProvider.ResetBlsCache() 859 } 860 861 // snapshot retrieves the state of the authorization voting at a given point in time. 862 // There's in-memory snapshot and on-disk snapshot. On-disk snapshot is stored every checkpointInterval blocks. 863 // Moreover, if the block has no in-memory or on-disk snapshot, before generating snapshot, it gathers the header and apply the vote in it. 864 func (sb *backend) snapshot(chain consensus.ChainReader, number uint64, hash common.Hash, parents []*types.Header, writable bool) (*Snapshot, error) { 865 // Search for a snapshot in memory or on disk for checkpoints 866 var ( 867 headers []*types.Header 868 snap *Snapshot 869 ) 870 871 for snap == nil { 872 // If an in-memory snapshot was found, use that 873 if s, ok := sb.recents.Get(hash); ok { 874 snap = s.(*Snapshot) 875 break 876 } 877 // If an on-disk checkpoint snapshot can be found, use that 878 if params.IsCheckpointInterval(number) { 879 if s, err := loadSnapshot(sb.db, hash); err == nil { 880 logger.Trace("Loaded voting snapshot form disk", "number", number, "hash", hash) 881 snap = s 882 break 883 } 884 } 885 // If we're at block zero, make a snapshot 886 if number == 0 { 887 var err error 888 if snap, err = sb.initSnapshot(chain); err != nil { 889 return nil, err 890 } 891 break 892 } 893 // No snapshot for this header, gather the header and move backward 894 if header := getPrevHeaderAndUpdateParents(chain, number, hash, &parents); header == nil { 895 return nil, consensus.ErrUnknownAncestor 896 } else { 897 headers = append(headers, header) 898 number, hash = number-1, header.ParentHash 899 } 900 } 901 // Previous snapshot found, apply any pending headers on top of it 902 for i := 0; i < len(headers)/2; i++ { 903 headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i] 904 } 905 pset, err := sb.governance.EffectiveParams(number) 906 if err != nil { 907 return nil, err 908 } 909 snap, err = snap.apply(headers, sb.governance, sb.address, pset.Policy(), chain, writable) 910 if err != nil { 911 return nil, err 912 } 913 914 // If we've generated a new checkpoint snapshot, save to disk 915 if writable && params.IsCheckpointInterval(snap.Number) && len(headers) > 0 { 916 if sb.governance.CanWriteGovernanceState(snap.Number) { 917 sb.governance.WriteGovernanceState(snap.Number, true) 918 } 919 if err = snap.store(sb.db); err != nil { 920 return nil, err 921 } 922 logger.Trace("Stored voting snapshot to disk", "number", snap.Number, "hash", snap.Hash) 923 } 924 925 sb.regen(chain, headers) 926 927 sb.recents.Add(snap.Hash, snap) 928 return snap, err 929 } 930 931 // regen commits snapshot data to database 932 // regen is triggered if there is any checkpoint block in the `headers`. 933 // For each checkpoint block, this function verifies the existence of its snapshot in DB and stores one if missing. 934 /* 935 Triggered: 936 | ^ ^ ^ ^ ...| 937 SI SI*(last snapshot) SI SI 938 | header1, .. headerN | 939 Not triggered: (Guaranteed SI* was committed before ) 940 | ^ ^ ^ ^ ...| 941 SI SI*(last snapshot) SI SI 942 | header1, .. headerN | 943 */ 944 func (sb *backend) regen(chain consensus.ChainReader, headers []*types.Header) { 945 // Prevent nested call. Ignore header length one 946 // because it was handled before the `regen` called. 947 if !sb.isRestoringSnapshots.CompareAndSwap(false, true) || len(headers) <= 1 { 948 return 949 } 950 defer func() { 951 sb.isRestoringSnapshots.Store(false) 952 }() 953 954 var ( 955 from = headers[0].Number.Uint64() 956 to = headers[len(headers)-1].Number.Uint64() 957 start = time.Now() 958 commitTried = false 959 ) 960 961 // Shortcut: No missing snapshot data to be processed. 962 if to-(to%uint64(params.CheckpointInterval)) < from { 963 return 964 } 965 966 for _, header := range headers { 967 var ( 968 hn = header.Number.Uint64() 969 hh = header.Hash() 970 ) 971 if params.IsCheckpointInterval(hn) { 972 // Store snapshot data if it was not committed before 973 if loadSnap, _ := sb.db.ReadIstanbulSnapshot(hh); loadSnap != nil { 974 continue 975 } 976 snap, err := sb.snapshot(chain, hn, hh, nil, false) 977 if err != nil { 978 logger.Warn("[Snapshot] Snapshot restoring failed", "len(headers)", len(headers), "from", from, "to", to, "headerNumber", hn) 979 continue 980 } 981 if err = snap.store(sb.db); err != nil { 982 logger.Warn("[Snapshot] Snapshot restoring failed", "len(headers)", len(headers), "from", from, "to", to, "headerNumber", hn) 983 } 984 commitTried = true 985 } 986 } 987 if commitTried { // This prevents pushing too many logs by potential DoS attack 988 logger.Trace("[Snapshot] Snapshot restoring completed", "len(headers)", len(headers), "from", from, "to", to, "elapsed", time.Since(start)) 989 } 990 } 991 992 // FIXME: Need to update this for Istanbul 993 // sigHash returns the hash which is used as input for the Istanbul 994 // signing. It is the hash of the entire header apart from the 65 byte signature 995 // contained at the end of the extra data. 996 // 997 // Note, the method requires the extra data to be at least 65 bytes, otherwise it 998 // panics. This is done to avoid accidentally using both forms (signature present 999 // or not), which could be abused to produce different hashes for the same header. 1000 func sigHash(header *types.Header) (hash common.Hash) { 1001 hasher := sha3.NewKeccak256() 1002 1003 // Clean seal is required for calculating proposer seal. 1004 rlp.Encode(hasher, types.IstanbulFilteredHeader(header, false)) 1005 hasher.Sum(hash[:0]) 1006 return hash 1007 } 1008 1009 // ecrecover extracts the Klaytn account address from a signed header. 1010 func ecrecover(header *types.Header) (common.Address, error) { 1011 // Retrieve the signature from the header extra-data 1012 istanbulExtra, err := types.ExtractIstanbulExtra(header) 1013 if err != nil { 1014 return common.Address{}, err 1015 } 1016 addr, err := cacheSignatureAddresses(sigHash(header).Bytes(), istanbulExtra.Seal) 1017 if err != nil { 1018 return addr, err 1019 } 1020 1021 return addr, nil 1022 } 1023 1024 // prepareExtra returns a extra-data of the given header and validators 1025 func prepareExtra(header *types.Header, vals []common.Address) ([]byte, error) { 1026 var buf bytes.Buffer 1027 1028 // compensate the lack bytes if header.Extra is not enough IstanbulExtraVanity bytes. 1029 if len(header.Extra) < types.IstanbulExtraVanity { 1030 header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, types.IstanbulExtraVanity-len(header.Extra))...) 1031 } 1032 buf.Write(header.Extra[:types.IstanbulExtraVanity]) 1033 1034 ist := &types.IstanbulExtra{ 1035 Validators: vals, 1036 Seal: []byte{}, 1037 CommittedSeal: [][]byte{}, 1038 } 1039 1040 payload, err := rlp.EncodeToBytes(&ist) 1041 if err != nil { 1042 return nil, err 1043 } 1044 1045 return append(buf.Bytes(), payload...), nil 1046 } 1047 1048 // writeSeal writes the extra-data field of the given header with the given seals. 1049 // suggest to rename to writeSeal. 1050 func writeSeal(h *types.Header, seal []byte) error { 1051 if len(seal)%types.IstanbulExtraSeal != 0 { 1052 return errInvalidSignature 1053 } 1054 1055 istanbulExtra, err := types.ExtractIstanbulExtra(h) 1056 if err != nil { 1057 return err 1058 } 1059 1060 istanbulExtra.Seal = seal 1061 payload, err := rlp.EncodeToBytes(&istanbulExtra) 1062 if err != nil { 1063 return err 1064 } 1065 1066 h.Extra = append(h.Extra[:types.IstanbulExtraVanity], payload...) 1067 return nil 1068 } 1069 1070 // writeCommittedSeals writes the extra-data field of a block header with given committed seals. 1071 func writeCommittedSeals(h *types.Header, committedSeals [][]byte) error { 1072 if len(committedSeals) == 0 { 1073 return errInvalidCommittedSeals 1074 } 1075 1076 for _, seal := range committedSeals { 1077 if len(seal) != types.IstanbulExtraSeal { 1078 return errInvalidCommittedSeals 1079 } 1080 } 1081 1082 istanbulExtra, err := types.ExtractIstanbulExtra(h) 1083 if err != nil { 1084 return err 1085 } 1086 1087 istanbulExtra.CommittedSeal = make([][]byte, len(committedSeals)) 1088 copy(istanbulExtra.CommittedSeal, committedSeals) 1089 1090 payload, err := rlp.EncodeToBytes(&istanbulExtra) 1091 if err != nil { 1092 return err 1093 } 1094 1095 h.Extra = append(h.Extra[:types.IstanbulExtraVanity], payload...) 1096 return nil 1097 }