github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/consensus/dbft/backend/dpos.go (about) 1 // Package backend implements the Delegated-Proof-of-Stake consensus engine. 2 package backend 3 4 import ( 5 "bytes" 6 "errors" 7 "fmt" 8 "hash" 9 "math/big" 10 //"math/rand" 11 "sync" 12 "time" 13 14 lru "github.com/hashicorp/golang-lru" 15 "github.com/quickchainproject/quickchain/accounts" 16 "github.com/quickchainproject/quickchain/common" 17 //"github.com/quickchainproject/quickchain/common/hexutil" 18 "github.com/quickchainproject/quickchain/consensus" 19 "github.com/quickchainproject/quickchain/consensus/misc" 20 "github.com/quickchainproject/quickchain/core/state" 21 "github.com/quickchainproject/quickchain/core/types" 22 //"github.com/quickchainproject/quickchain/crypto" 23 "github.com/quickchainproject/quickchain/crypto/sha3" 24 "github.com/quickchainproject/quickchain/qctdb" 25 "github.com/quickchainproject/quickchain/log" 26 "github.com/quickchainproject/quickchain/params" 27 //"github.com/quickchainproject/quickchain/rlp" 28 "github.com/quickchainproject/quickchain/rpc" 29 ) 30 31 const ( 32 inmemoryEpochContexts = 128 // Number of recent vote epochcontexts to keep in memory 33 //inmemorySignatures = 4096 // Number of recent block signatures to keep in memory 34 35 wiggleTime = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers 36 37 //maxValidatorSize = 5 38 //safeSize = 1 39 ) 40 41 var ( 42 //MinDelegateBalance = big.NewFloat(10 * 1e18) //10QCT 43 //MinCandidateBalance = big.NewFloat(100 * 1e18) //100QCT 44 //UnlockInterval = big.NewInt(10) //10 Block 45 ) 46 47 // Delegated-Proof-of-Stake protocol constants. 48 var ( 49 //epochLength = uint64(30000) // Default number of blocks after which to checkpoint and reset the pending votes 50 //epochLength = uint64(30) 51 //epochInterval = int64(epochLength) //alias for epochLength for test 52 blockPeriod = uint64(5) // Default minimum difference between two consecutive block's timestamps 53 blockInterval = int64(blockPeriod) //alias for blockPeriod for test 54 55 extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity 56 extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal 57 58 //nonceAuthVote = hexutil.MustDecode("0xffffffffffffffff") // Magic nonce number to vote on adding a new signer 59 //nonceDropVote = hexutil.MustDecode("0x0000000000000000") // Magic nonce number to vote on removing a signer. 60 61 uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW. 62 63 diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures 64 diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures 65 diffMax = big.NewInt(5) // Max Block difficulty 66 ) 67 68 // Various error messages to mark blocks invalid. These should be private to 69 // prevent engine specific errors from being referenced in the remainder of the 70 // codebase, inherently breaking if the engine is swapped out. Please put common 71 // error types into the consensus package. 72 var ( 73 // errUnknownBlock is returned when the list of signers is requested for a block 74 // that is not part of the local blockchain. 75 //errUnknownBlock = errors.New("unknown block") 76 77 // errInvalidCheckpointBeneficiary is returned if a checkpoint/epoch transition 78 // block has a beneficiary set to non-zeroes. 79 errInvalidCheckpointBeneficiary = errors.New("beneficiary in checkpoint block non-zero") 80 81 // errInvalidVote is returned if a nonce value is something else that the two 82 // allowed constants of 0x00..0 or 0xff..f. 83 //errInvalidVote = errors.New("vote nonce not 0x00..0 or 0xff..f") 84 85 // errInvalidCheckpointVote is returned if a checkpoint/epoch transition block 86 // has a vote nonce set to non-zeroes. 87 errInvalidCheckpointVote = errors.New("vote nonce in checkpoint block non-zero") 88 89 // errMissingVanity is returned if a block's extra-data section is shorter than 90 // 32 bytes, which is required to store the signer vanity. 91 errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing") 92 93 // errMissingSignature is returned if a block's extra-data section doesn't seem 94 // to contain a 65 byte secp256k1 signature. 95 errMissingSignature = errors.New("extra-data 65 byte suffix signature missing") 96 97 // errExtraSigners is returned if non-checkpoint block contain signer data in 98 // their extra-data fields. 99 errExtraSigners = errors.New("non-checkpoint block contains extra signer list") 100 101 // errInvalidCheckpointSigners is returned if a checkpoint block contains an 102 // invalid list of signers (i.e. non divisible by 20 bytes, or not the correct 103 // ones). 104 errInvalidCheckpointSigners = errors.New("invalid signer list on checkpoint block") 105 106 // errInvalidMixDigest is returned if a block's mix digest is non-zero. 107 //errInvalidMixDigest = errors.New("non-zero mix digest") 108 109 // errInvalidUncleHash is returned if a block contains an non-empty uncle list. 110 //errInvalidUncleHash = errors.New("non empty uncle hash") 111 112 // errInvalidDifficulty is returned if the difficulty of a block is not either 113 // of 1 or 2, or if the value does not match the turn of the signer. 114 //errInvalidDifficulty = errors.New("invalid difficulty") 115 116 // ErrInvalidTimestamp is returned if the timestamp of a block is lower than 117 // the previous block's timestamp + the minimum block period. 118 ErrInvalidTimestamp = errors.New("invalid timestamp") 119 120 // errInvalidVotingChain is returned if an authorization list is attempted to 121 // be modified via out-of-range or non-contiguous headers. 122 //errInvalidVotingChain = errors.New("invalid voting chain") 123 124 // errUnauthorized is returned if a header is signed by a non-authorized entity. 125 //errUnauthorized = errors.New("unauthorized") 126 127 // errWaitTransactions is returned if an empty block is attempted to be sealed 128 // on an instant chain (0 second period). It's important to refuse these as the 129 // block reward is zero, so an empty block just bloats the chain... fast. 130 errWaitTransactions = errors.New("waiting for transactions") 131 132 ErrWaitForPrevBlock = errors.New("wait for last block arrived") 133 ErrMintFutureBlock = errors.New("mint the future block") 134 //ErrMismatchSignerAndValidator = errors.New("mismatch block signer and validator") 135 ErrInvalidBlockValidator = errors.New("invalid block validator") 136 ErrInvalidMintBlockTime = errors.New("invalid time to mint the block") 137 //ErrNilBlockHeader = errors.New("nil block header returned") 138 ) 139 140 // SignerFn is a signer callback function to request a hash to be signed by a 141 // backing account. 142 type SignerFn func(accounts.Account, []byte) ([]byte, error) 143 144 // sigHash returns the hash which is used as input for the Delegated-Proof-of-Stake 145 // signing. It is the hash of the entire header apart from the 65 byte signature 146 // contained at the end of the extra data. 147 // 148 // Note, the method requires the extra data to be at least 65 bytes, otherwise it 149 // panics. This is done to avoid accidentally using both forms (signature present 150 // or not), which could be abused to produce different hashes for the same header. 151 /* 152 func sigHash(header *types.Header) (hash common.Hash) { 153 hasher := sha3.NewKeccak256() 154 155 rlp.Encode(hasher, []interface{}{ 156 header.ParentHash, 157 header.UncleHash, 158 header.Coinbase, 159 header.Root, 160 header.TxHash, 161 header.ReceiptHash, 162 header.Bloom, 163 header.Difficulty, 164 header.Number, 165 header.GasLimit, 166 header.GasUsed, 167 header.Time, 168 header.Extra, 169 header.MixDigest, 170 header.Nonce, 171 header.DposContext.Root(), 172 }) 173 hasher.Sum(hash[:0]) 174 return hash 175 } 176 */ 177 178 // ecrecover extracts the Quickchain account address from a signed header. 179 /* 180 func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { 181 // If the signature's already cached, return that 182 hash := header.Hash() 183 if address, known := sigcache.Get(hash); known { 184 return address.(common.Address), nil 185 } 186 187 signature := header.Signature[0:] 188 189 // Recover the public key and the Quickchain address 190 pubkey, err := crypto.Ecrecover(sigHash(header).Bytes(), signature) 191 if err != nil { 192 return common.Address{}, err 193 } 194 var signer common.Address 195 copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) 196 197 sigcache.Add(hash, signer) 198 return signer, nil 199 } 200 */ 201 202 // dpos is the Delegated-Proof-of-Stake consensus engine 203 type DPOS struct { 204 config *params.DPOSConfig // Consensus engine configuration parameters 205 db qctdb.Database // Database to store and retrieve snapshot checkpoints 206 207 recents *lru.ARCCache // Epochcontexts for recent block to speed up reorgs 208 signatures *lru.ARCCache // Signatures of recent blocks to speed up mining 209 210 proposals map[common.Address]bool // Current list of proposals we are pushing 211 212 signer common.Address // Quickchain address of the signing key 213 signFn SignerFn // Signer function to authorize hashes with 214 lock sync.RWMutex // Protects the signer fields 215 } 216 217 // New creates a Delegated-Proof-of-Stake consensus engine with the initial 218 // signers set to the ones provided by the user. 219 func NewDPOS(config *params.DPOSConfig, db qctdb.Database) *DPOS { 220 // Set any missing consensus parameters to their defaults 221 conf := *config 222 if conf.Epoch == 0 { 223 conf.Epoch = epochLength 224 } 225 // Allocate the snapshot caches and create the engine 226 recents, _ := lru.NewARC(inmemoryEpochContexts) 227 signatures, _ := lru.NewARC(inmemorySignatures) 228 229 return &DPOS{ 230 config: &conf, 231 db: db, 232 recents: recents, 233 signatures: signatures, 234 proposals: make(map[common.Address]bool), 235 } 236 } 237 238 func (c *DPOS) DB() qctdb.Database { return c.db } 239 240 // Author implements consensus.Engine, returning the Quickchain address recovered 241 // from the signature in the header's extra-data section. 242 func (c *DPOS) Author(header *types.Header) (common.Address, error) { 243 return ecrecover(header, c.signatures) 244 } 245 246 // VerifyHeader checks whether a header conforms to the consensus rules. 247 func (c *DPOS) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { 248 return c.verifyHeader(chain, header, nil) 249 } 250 251 // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The 252 // method returns a quit channel to abort the operations and a results channel to 253 // retrieve the async verifications (the order is that of the input slice). 254 func (c *DPOS) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { 255 abort := make(chan struct{}) 256 results := make(chan error, len(headers)) 257 258 go func() { 259 for i, header := range headers { 260 err := c.verifyHeader(chain, header, headers[:i]) 261 262 select { 263 case <-abort: 264 return 265 case results <- err: 266 } 267 } 268 }() 269 return abort, results 270 } 271 272 // verifyHeader checks whether a header conforms to the consensus rules.The 273 // caller may optionally pass in a batch of parents (ascending order) to avoid 274 // looking those up from the database. This is useful for concurrently verifying 275 // a batch of new headers. 276 func (c *DPOS) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 277 if header.Number == nil { 278 return errUnknownBlock 279 } 280 //number := header.Number.Uint64() 281 282 // Don't waste time checking blocks from the future 283 if header.Time.Cmp(big.NewInt(time.Now().Unix())) > 0 { 284 return consensus.ErrFutureBlock 285 } 286 // Checkpoint blocks need to enforce zero beneficiary 287 /*checkpoint := (number % c.config.Epoch) == 0 288 if checkpoint && header.Coinbase != (common.Address{}) { 289 return errInvalidCheckpointBeneficiary 290 }*/ 291 // Nonces must be 0x00..0 or 0xff..f, zeroes enforced on checkpoints 292 /* 293 if !bytes.Equal(header.Nonce[:], nonceAuthVote) && !bytes.Equal(header.Nonce[:], nonceDropVote) { 294 return errInvalidVote 295 } 296 */ 297 /*if checkpoint && !bytes.Equal(header.Nonce[:], nonceDropVote) { 298 return errInvalidCheckpointVote 299 }*/ 300 301 // Check that the extra-data contains both the vanity and signature 302 if len(header.Extra) < extraVanity { 303 return errMissingVanity 304 } 305 /*if len(header.Extra) < extraVanity+extraSeal { 306 return errMissingSignature 307 }*/ 308 // Ensure that the extra-data contains a signer list on checkpoint, but none otherwise 309 /*signersBytes := len(header.Extra) - extraVanity - extraSeal 310 if !checkpoint && signersBytes != 0 { 311 return errExtraSigners 312 } 313 if checkpoint && signersBytes%common.AddressLength != 0 { 314 return errInvalidCheckpointSigners 315 }*/ 316 // Ensure that the mix digest is zero as we don't have fork protection currently 317 if header.MixDigest != (common.Hash{}) { 318 return errInvalidMixDigest 319 } 320 // Ensure that the block doesn't contain any uncles which are meaningless in DPOS 321 if header.UncleHash != uncleHash { 322 return errInvalidUncleHash 323 } 324 // Ensure that the block's difficulty is meaningful (may not be correct at this point) 325 /*if number > 0 { 326 if header.Difficulty == nil || (header.Difficulty.Cmp(diffInTurn) != 0 && header.Difficulty.Cmp(diffNoTurn) != 0) { 327 return errInvalidDifficulty 328 } 329 }*/ 330 signer, err := ecrecover(header, c.signatures) 331 if err != nil { 332 return err 333 } 334 //check validator 335 if bytes.Compare(signer.Bytes(), header.Coinbase.Bytes()) != 0 { 336 return ErrMismatchSignerAndValidator 337 } 338 339 // If all checks passed, validate any special fields for hard forks 340 if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil { 341 return err 342 } 343 // All basic checks passed, verify cascading fields 344 return c.verifyCascadingFields(chain, header, parents) 345 } 346 347 // verifyCascadingFields verifies all the header fields that are not standalone, 348 // rather depend on a batch of previous headers. The caller may optionally pass 349 // in a batch of parents (ascending order) to avoid looking those up from the 350 // database. This is useful for concurrently verifying a batch of new headers. 351 func (c *DPOS) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 352 // The genesis block is the always valid dead-end 353 number := header.Number.Uint64() 354 if number == 0 { 355 return nil 356 } 357 // Ensure that the block's timestamp isn't too close to it's parent 358 var parent *types.Header 359 if len(parents) > 0 { 360 parent = parents[len(parents)-1] 361 } else { 362 parent = chain.GetHeader(header.ParentHash, number-1) 363 } 364 if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { 365 return consensus.ErrUnknownAncestor 366 } 367 if parent.Time.Uint64()+c.config.Period > header.Time.Uint64() { 368 return ErrInvalidTimestamp 369 } 370 371 // All basic checks passed, verify the seal and return 372 return nil 373 } 374 375 // snapshot retrieves the authorization snapshot at a given point in time. 376 func (c *DPOS) epochContext(chain consensus.ChainReader, number uint64, hash common.Hash, header *types.Header) (epoch *EpochContext, err error) { 377 // Search for a snapshot in memory or on disk for checkpoints 378 379 // If an in-memory snapshot was found, use that 380 if s, ok := c.recents.Get(hash); ok { 381 epoch = s.(*EpochContext) 382 return epoch, nil 383 } 384 385 dposContext, err := types.NewDposContextFromProto(c.db, header.DposContext) 386 if err != nil { 387 return nil, err 388 } 389 390 epoch, err = newEpochContext(number, hash, dposContext, nil) 391 if err != nil { 392 return nil, err 393 } 394 395 // get recent block signers list 396 curHeader := chain.GetHeaderByHash(hash) 397 if curHeader == nil { 398 return nil, ErrNilBlockHeader 399 } 400 401 for curHeader.Number.Uint64() > 0 && len(epoch.Recents) < (len(epoch.Signers)/2+1) && (curHeader.Number.Uint64()%c.config.Epoch) != 0 { 402 403 epoch.Recents[curHeader.Number.Uint64()] = curHeader.Coinbase 404 405 curHeader = chain.GetHeaderByHash(curHeader.ParentHash) 406 if curHeader == nil { 407 return nil, ErrNilBlockHeader 408 } 409 } 410 411 c.recents.Add(epoch.Hash, epoch) 412 413 return epoch, nil 414 } 415 416 // VerifyUncles implements consensus.Engine, always returning an error for any 417 // uncles as this consensus mechanism doesn't permit uncles. 418 func (c *DPOS) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { 419 if len(block.Uncles()) > 0 { 420 return errors.New("uncles not allowed") 421 } 422 return nil 423 } 424 425 // VerifySeal implements consensus.Engine, checking whether the signature contained 426 // in the header satisfies the consensus protocol requirements. 427 func (c *DPOS) VerifySeal(chain consensus.ChainReader, header *types.Header) error { 428 return c.verifySeal(chain, header, nil) 429 } 430 431 // verifySeal checks whether the signature contained in the header satisfies the 432 // consensus protocol requirements. The method accepts an optional list of parent 433 // headers that aren't yet part of the local blockchain to generate the snapshots 434 // from. 435 func (c *DPOS) verifySeal(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 436 437 //log.Info("verifySeal") 438 // Verifying the genesis block is not supported 439 number := header.Number.Uint64() 440 if number == 0 { 441 return errUnknownBlock 442 } 443 444 var parent *types.Header 445 if len(parents) > 0 { 446 parent = parents[len(parents)-1] 447 } else { 448 parent = chain.GetHeader(header.ParentHash, number-1) 449 } 450 if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { 451 return consensus.ErrUnknownAncestor 452 } 453 454 // Retrieve the epochcontext needed to verify this header and cache it 455 epoch, err := c.epochContext(chain, number-1, header.ParentHash, parent) 456 if err != nil { 457 return err 458 } 459 460 // Resolve the authorization key and check against signers 461 signer, err := ecrecover(header, c.signatures) 462 if err != nil { 463 return err 464 } 465 if _, ok := epoch.Signers[signer]; !ok { 466 log.Error("verifySeal", "signer", signer, "Signers", epoch.Signers) 467 return errUnauthorized 468 } 469 for seen, recent := range epoch.Recents { 470 if recent == signer { 471 // Signer is among recents, only fail if the current block doesn't shift it out 472 if limit := uint64(len(epoch.Signers)/2 + 1); seen > number-limit { 473 log.Error("Recents", "limit", limit, "seen", seen, "number", number) 474 return errUnauthorized 475 } 476 } 477 } 478 // Ensure that the difficulty corresponds to the turn-ness of the signer 479 /*inturn := snap.inturn(header.Number.Uint64(), signer) 480 if inturn && header.Difficulty.Cmp(diffInTurn) != 0 { 481 return errInvalidDifficulty 482 } 483 if !inturn && header.Difficulty.Cmp(diffNoTurn) != 0 { 484 return errInvalidDifficulty 485 }*/ 486 487 expected := CalcDifficulty(epoch, signer, parent) 488 489 if expected.Cmp(header.Difficulty) != 0 { 490 return errInvalidDifficulty 491 } 492 493 // Ensure that we have a valid difficulty for the block 494 if header.Difficulty.Sign() <= 0 { 495 log.Info("header.Difficulty.Sign() <= 0") 496 return errInvalidDifficulty 497 } 498 499 return nil 500 } 501 502 // Prepare implements consensus.Engine, preparing all the consensus fields of the 503 // header for running the transactions on top. 504 func (c *DPOS) Prepare(chain consensus.ChainReader, header *types.Header) error { 505 //log.Info("Prepare") 506 // If the block isn't a checkpoint, cast a random vote (good enough for now) 507 header.Coinbase = common.Address{} 508 header.Nonce = types.BlockNonce{} 509 510 number := header.Number.Uint64() 511 512 parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) 513 if parent == nil { 514 return consensus.ErrUnknownAncestor 515 } 516 517 // Assemble the voting snapshot to check which votes make sense 518 epoch, err := c.epochContext(chain, number-1, header.ParentHash, parent) 519 if err != nil { 520 return err 521 } 522 523 // set Validator 524 header.Coinbase = c.signer 525 526 // Set the correct difficulty 527 header.Difficulty = CalcDifficulty(epoch, c.signer, parent) 528 529 // Ensure the extra data has all it's components 530 if len(header.Extra) < extraVanity { 531 header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...) 532 } 533 /*header.Extra = header.Extra[:extraVanity] 534 535 header.Extra = append(header.Extra, make([]byte, extraSeal)...)*/ 536 537 // Mix digest is reserved for now, set to empty 538 header.MixDigest = common.Hash{} 539 540 header.Time = new(big.Int).Add(parent.Time, new(big.Int).SetUint64(c.config.Period)) 541 if header.Time.Int64() < time.Now().Unix() { 542 header.Time = big.NewInt(time.Now().Unix()) 543 } 544 return nil 545 } 546 547 // Judge the create contract Transaction from a no authorized account for dpos engine. 548 func (c *DPOS) JudgeTx(chain consensus.ChainReader, header *types.Header, tx *types.Transaction, from common.Address) error { 549 550 // get the number of the new block 551 number := header.Number.Uint64() 552 //log.Info("PrepareTx number ","number", number) 553 554 parent := chain.GetHeader(header.ParentHash, number-1) 555 if parent == nil { 556 return consensus.ErrUnknownAncestor 557 } 558 // get current block epochcontext 559 epoch, err := c.epochContext(chain, number-1, header.ParentHash, parent) 560 if err != nil { 561 return err 562 } 563 //log.Info("PrepareTx get snapshot ") 564 if tx.To() == nil { 565 //log.Info("PrepareTx tx.To() == nil") 566 //judge a account is not a authorizer 567 if _, authorized := epoch.Signers[from]; !authorized { 568 log.Info("PrepareTx create contract no authorized", "from", from) 569 return errUnauthorized 570 } else { 571 log.Info("PrepareTx create contract authorized", "from", from) 572 } 573 } else { 574 //log.Info("PrepareTx tx.To() != nil", "from", from) 575 } 576 return nil 577 } 578 579 // Finalize implements consensus.Engine, ensuring no uncles are set, nor block 580 // rewards given, and returns the final block. 581 func (c *DPOS) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, dposContext *types.DposContext) (*types.Block, error) { 582 // No block rewards in DPOS, so the state remains as is and uncles are dropped 583 header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) 584 header.UncleHash = types.CalcUncleHash(nil) 585 586 number := header.Number.Uint64() 587 parent := chain.GetHeader(header.ParentHash, number-1) 588 if parent == nil { 589 return nil, consensus.ErrUnknownAncestor 590 } 591 592 epoch, err := newEpochContext(number-1, header.ParentHash, dposContext, state) 593 if err != nil { 594 log.Error("newEpochContext", "err", err) 595 return nil, err 596 } 597 598 // every epoch , reset signer list 599 if number%c.config.Epoch == 0 { 600 genesis := chain.GetHeaderByNumber(0) 601 err = epoch.tryElect(genesis, parent) 602 if err != nil { 603 log.Error("tryElect", "err", err) 604 return nil, fmt.Errorf("got error when elect next epoch, err: %s", err) 605 } 606 } 607 608 //update mint count trie 609 //epoch.updateMintCnt(header.Coinbase) 610 611 header.DposContext = epoch.DposContext.ToProto() 612 613 //add dposcontext 614 if _, err := dposContext.CommitTo(state.Database().TrieDB()); err != nil { 615 log.Error("Finalize dposContext.CommitTo", "err", err) 616 } 617 618 // Assemble and return the final block for sealing 619 block := types.NewBlock(header, txs, nil, receipts) 620 block.DposContext = epoch.DposContext 621 return block, nil 622 } 623 624 // Authorize injects a private key into the consensus engine to mint new blocks 625 // with. 626 func (c *DPOS) Authorize(signer common.Address, signFn SignerFn) { 627 c.lock.Lock() 628 defer c.lock.Unlock() 629 630 c.signer = signer 631 c.signFn = signFn 632 } 633 634 // Seal implements consensus.Engine, attempting to create a sealed block using 635 // the local signing credentials. 636 func (c *DPOS) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) { 637 header := block.Header() 638 639 // Sealing the genesis block is not supported 640 number := header.Number.Uint64() 641 if number == 0 { 642 return nil, errUnknownBlock 643 } 644 //log.Info("Seal", "number", number) 645 646 // For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing) 647 if c.config.Period == 0 && len(block.Transactions()) == 0 { 648 return nil, errWaitTransactions 649 } 650 // Don't hold the signer fields for the entire sealing procedure 651 c.lock.RLock() 652 //signer, signFn := c.signer, c.signFn 653 c.lock.RUnlock() 654 655 parent := chain.GetHeader(header.ParentHash, number-1) 656 if parent == nil { 657 return nil, consensus.ErrUnknownAncestor 658 } 659 660 // Bail out if we're unauthorized to sign a block 661 //epoch, err := c.epochContext(chain, number-1, header.ParentHash, parent) 662 _, err := c.epochContext(chain, number-1, header.ParentHash, parent) 663 if err != nil { 664 return nil, err 665 } 666 /* 667 if _, authorized := epoch.Signers[signer]; !authorized { 668 log.Error("Seal", "signer", signer, "Signers", epoch.Signers) 669 return nil, errUnauthorized 670 } 671 // If we're amongst the recent signers, wait for the next block 672 for seen, recent := range epoch.Recents { 673 if recent == signer { 674 // Signer is among recents, only wait if the current block doesn't shift it out 675 if limit := uint64(len(epoch.Signers)/2 + 1); number < limit || seen > number-limit { 676 log.Info("Signed recently,but < signer/2 + 1", "len", len(epoch.Signers)) 677 var period int64 678 period = int64(c.config.Period) 679 period = period * int64(len(epoch.Signers)/2+1) 680 //delay := time.Duration((len(snap.Signers)/2+1) * c.config.Period * time.Second) 681 delay := time.Duration(period) * time.Second 682 683 select { 684 case <-stop: 685 log.Info("Signed recently wait , exit from stop event") 686 return nil, nil 687 case <-time.After(delay): 688 log.Info("Signed recently wait, exit from delay", "delay", delay) 689 return nil, consensus.ErrMining 690 } 691 692 //return nil, nil 693 } 694 } 695 } 696 // Sweet, the protocol permits us to sign the block, wait for our time 697 delay := time.Unix(header.Time.Int64(), 0).Sub(time.Now()) // nolint: gosimple 698 //if header.Difficulty.Cmp(diffNoTurn) == 0 { 699 if !epoch.inturn(number, signer) { 700 // It's not our turn explicitly to sign, delay it a bit 701 wiggle := time.Duration(len(epoch.Signers)/2+1) * wiggleTime 702 delay += time.Duration(rand.Int63n(int64(wiggle))) 703 704 log.Info("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle)) 705 } else { 706 log.Info("In-of-turn signing requested") 707 } 708 log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay)) 709 710 select { 711 case <-stop: 712 return nil, nil 713 case <-time.After(delay): 714 } 715 // Sign all the things! 716 sighash, err := signFn(accounts.Account{Address: signer}, sigHash(header).Bytes()) 717 if err != nil { 718 return nil, err 719 } 720 copy((&header.Signature)[:], sighash) 721 */ 722 723 return block.WithSeal(header), nil 724 } 725 726 // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty 727 // that a new block should have based on the previous blocks in the chain and the 728 // current signer. 729 func (c *DPOS) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { 730 snap, err := c.epochContext(chain, parent.Number.Uint64(), parent.Hash(), nil) 731 if err != nil { 732 return nil 733 } 734 735 return CalcDifficulty(snap, c.signer, parent) 736 } 737 738 // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty 739 // that a new block should have based on the previous blocks in the chain and the 740 // current signer. 741 func CalcDifficulty(epoch *EpochContext, signer common.Address, parent *types.Header) *big.Int { 742 /*if snap.inturn(snap.Number+1, signer) { 743 return new(big.Int).Set(diffInTurn) 744 } 745 return new(big.Int).Set(diffNoTurn)*/ 746 if len(epoch.Signers) == 0 { 747 return new(big.Int).SetUint64(0) 748 } 749 soffset := epoch.signerIndex(signer) 750 noffset := (epoch.Number + 1) % uint64(len(epoch.Signers)) 751 var index uint64 752 if noffset > soffset { 753 index = noffset - soffset 754 } else { 755 index = uint64(len(epoch.Signers)) - (soffset - noffset) 756 } 757 //diff = diff * uint64(diffMax) / uint64(len(snap.Signers)) 758 //diff = diff + parent.Difficulty 759 760 diff := new(big.Int).SetUint64(index) 761 signerCount := new(big.Int).SetUint64(uint64(len(epoch.Signers))) 762 diff.Mul(diff, diffMax) 763 diff.Div(diff, signerCount) 764 //diff.Add(diff, parent.Difficulty) 765 diff.Add(diff, new(big.Int).SetUint64(1000)) // add a fixed number to avoid wiggle 766 767 //log.Info("CalcDifficulty ","number", snap.Number+1, "diff", diff) 768 769 return diff 770 } 771 772 // APIs implements consensus.Engine, returning the user facing RPC API to allow 773 // controlling the signer voting. 774 func (c *DPOS) APIs(chain consensus.ChainReader) []rpc.API { 775 return []rpc.API{{ 776 Namespace: "dpos", 777 Version: "1.0", 778 //Service: &API{chain: chain, bft: c}, 779 Public: false, 780 }} 781 } 782 783 // hasher is a repetitive hasher allowing the same hash data structures to be 784 // reused between hash runs instead of requiring new ones to be created. 785 type hasher func(dest []byte, data []byte) 786 787 // makeHasher creates a repetitive hasher, allowing the same hash data structures 788 // to be reused between hash runs instead of requiring new ones to be created. 789 // The returned function is not thread safe! 790 func makeHasher(h hash.Hash) hasher { 791 return func(dest []byte, data []byte) { 792 h.Write(data) 793 h.Sum(dest[:0]) 794 h.Reset() 795 } 796 } 797 798 // seedHash is the seed to use for generating a verification cache and the mining 799 // dataset. 800 func seedHash(block uint64) []byte { 801 seed := make([]byte, 32) 802 if block < epochLength { 803 return seed 804 } 805 keccak256 := makeHasher(sha3.NewKeccak256()) 806 for i := 0; i < int(block/epochLength); i++ { 807 keccak256(seed, seed) 808 } 809 return seed 810 } 811 812 // SeedHash is the seed to use for generating a verification cache and the mining 813 // dataset. 814 func SeedHash(block uint64) []byte { 815 return seedHash(block) 816 }