github.com/DxChainNetwork/dxc@v0.8.1-0.20220824085222-1162e304b6e7/consensus/dpos/dpos.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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-ethereum 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-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package dpos implements the proof-of-stake-authority consensus engine. 18 package dpos 19 20 import ( 21 "bytes" 22 "encoding/binary" 23 "errors" 24 "fmt" 25 "io" 26 "math" 27 "math/big" 28 "math/rand" 29 "sync" 30 "time" 31 32 "github.com/DxChainNetwork/dxc/accounts" 33 "github.com/DxChainNetwork/dxc/accounts/abi" 34 "github.com/DxChainNetwork/dxc/common" 35 "github.com/DxChainNetwork/dxc/consensus" 36 "github.com/DxChainNetwork/dxc/consensus/dpos/systemcontract" 37 "github.com/DxChainNetwork/dxc/consensus/dpos/vmcaller" 38 "github.com/DxChainNetwork/dxc/consensus/misc" 39 "github.com/DxChainNetwork/dxc/core/state" 40 "github.com/DxChainNetwork/dxc/core/types" 41 "github.com/DxChainNetwork/dxc/crypto" 42 "github.com/DxChainNetwork/dxc/ethdb" 43 "github.com/DxChainNetwork/dxc/log" 44 "github.com/DxChainNetwork/dxc/metrics" 45 "github.com/DxChainNetwork/dxc/params" 46 "github.com/DxChainNetwork/dxc/rlp" 47 "github.com/DxChainNetwork/dxc/rpc" 48 "github.com/DxChainNetwork/dxc/trie" 49 lru "github.com/hashicorp/golang-lru" 50 "golang.org/x/crypto/sha3" 51 ) 52 53 const ( 54 checkpointInterval = 1024 // Number of blocks after which to save the vote snapshot to the database 55 inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory 56 inmemorySignatures = 4096 // Number of recent block signatures to keep in memory 57 58 wiggleTime = 500 * time.Millisecond // Random delay (per validator) to allow concurrent validators 59 maxValidators = 99 // Max validators allowed sealing. 60 61 inmemoryBlacklist = 21 // Number of recent blacklist snapshots to keep in memory 62 ) 63 64 type blacklistDirection uint 65 66 const ( 67 DirectionFrom blacklistDirection = iota 68 DirectionTo 69 DirectionBoth 70 ) 71 72 // Dpos delegated proof-of-stake protocol constants. 73 var ( 74 epochLength = uint64(14400) // Default number of blocks after which to checkpoint and reset the pending votes 75 76 extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for validator vanity 77 extraSeal = crypto.SignatureLength // Fixed number of extra-data suffix bytes reserved for validator seal 78 79 uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW. 80 81 diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures 82 diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures 83 ) 84 85 // Various error messages to mark blocks invalid. These should be private to 86 // prevent engine specific errors from being referenced in the remainder of the 87 // codebase, inherently breaking if the engine is swapped out. Please put common 88 // error types into the consensus package. 89 var ( 90 // errUnknownBlock is returned when the list of validators is requested for a block 91 // that is not part of the local blockchain. 92 errUnknownBlock = errors.New("unknown block") 93 94 // errMissingVanity is returned if a block's extra-data section is shorter than 95 // 32 bytes, which is required to store the validator vanity. 96 errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing") 97 98 // errMissingSignature is returned if a block's extra-data section doesn't seem 99 // to contain a 65 byte secp256k1 signature. 100 errMissingSignature = errors.New("extra-data 65 byte signature suffix missing") 101 102 // errExtraValidators is returned if non-checkpoint block contain validator data in 103 // their extra-data fields. 104 errExtraValidators = errors.New("non-checkpoint block contains extra validator list") 105 106 // errInvalidExtraValidators is returned if validator data in extra-data field is invalid. 107 errInvalidExtraValidators = errors.New("invalid extra validators in extra data field") 108 109 // errInvalidCheckpointValidators is returned if a checkpoint block contains an 110 // invalid list of validators (i.e. non-divisible by 20 bytes). 111 errInvalidCheckpointValidators = errors.New("invalid validator list on checkpoint block") 112 113 // errMismatchingCheckpointValidators is returned if a checkpoint block contains a 114 // list of validators different from the one the local node calculated. 115 errMismatchingCheckpointValidators = errors.New("mismatching validator list on checkpoint block") 116 117 // errInvalidMixDigest is returned if a block's mix digest is non-zero. 118 errInvalidMixDigest = errors.New("non-zero mix digest") 119 120 // errInvalidUncleHash is returned if a block contains an non-empty uncle list. 121 errInvalidUncleHash = errors.New("non empty uncle hash") 122 123 // errInvalidDifficulty is returned if the difficulty of a block neither 1 or 2. 124 errInvalidDifficulty = errors.New("invalid difficulty") 125 126 // errWrongDifficulty is returned if the difficulty of a block doesn't match the 127 // turn of the validator. 128 errWrongDifficulty = errors.New("wrong difficulty") 129 130 // errInvalidTimestamp is returned if the timestamp of a block is lower than 131 // the previous block's timestamp + the minimum block period. 132 errInvalidTimestamp = errors.New("invalid timestamp") 133 134 // ErrInvalidTimestamp is returned if the timestamp of a block is lower than 135 // the previous block's timestamp + the minimum block period. 136 ErrInvalidTimestamp = errors.New("invalid timestamp") 137 138 // errInvalidVotingChain is returned if an authorization list is attempted to 139 // be modified via out-of-range or non-contiguous headers. 140 errInvalidVotingChain = errors.New("invalid voting chain") 141 142 // errUnauthorizedValidator is returned if a header is signed by a non-authorized entity. 143 errUnauthorizedValidator = errors.New("unauthorized validator") 144 145 // errRecentlySigned is returned if a header is signed by an authorized entity 146 // that already signed a header recently, thus is temporarily not allowed to. 147 errRecentlySigned = errors.New("recently signed") 148 149 // errInvalidValidatorLen is returned if validators length is zero or bigger than maxValidators. 150 errInvalidValidatorsLength = errors.New("invalid validators length") 151 152 // errInvalidCoinbase is returned if the coinbase isn't the validator of the block. 153 errInvalidCoinbase = errors.New("invalid coin base") 154 155 errInvalidSysGovCount = errors.New("invalid system governance tx count") 156 ) 157 158 var ( 159 getblacklistTimer = metrics.NewRegisteredTimer("dpos/blacklist/get", nil) 160 getRulesTimer = metrics.NewRegisteredTimer("dpos/eventcheckrules/get", nil) 161 ) 162 163 // StateFn gets state by the state root hash. 164 type StateFn func(hash common.Hash) (*state.StateDB, error) 165 166 // ValidatorFn hashes and signs the data to be signed by a backing account. 167 type ValidatorFn func(validator accounts.Account, mimeType string, message []byte) ([]byte, error) 168 type SignTxFn func(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) 169 170 // ecrecover extracts the Ethereum account address from a signed header. 171 func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { 172 // If the signature's already cached, return that 173 hash := header.Hash() 174 if address, known := sigcache.Get(hash); known { 175 return address.(common.Address), nil 176 } 177 // Retrieve the signature from the header extra-data 178 if len(header.Extra) < extraSeal { 179 return common.Address{}, errMissingSignature 180 } 181 signature := header.Extra[len(header.Extra)-extraSeal:] 182 183 // Recover the public key and the Ethereum address 184 pubkey, err := crypto.Ecrecover(SealHash(header).Bytes(), signature) 185 if err != nil { 186 return common.Address{}, err 187 } 188 var validator common.Address 189 copy(validator[:], crypto.Keccak256(pubkey[1:])[12:]) 190 191 sigcache.Add(hash, validator) 192 return validator, nil 193 } 194 195 // Dpos is the proof-of-stake-authority consensus engine proposed to support the 196 // Ethereum testnet following the Ropsten attacks. 197 type Dpos struct { 198 chainConfig *params.ChainConfig // ChainConfig to execute evm 199 config *params.DposConfig // Consensus engine configuration parameters 200 db ethdb.Database // Database to store and retrieve snapshot checkpoints 201 202 recents *lru.ARCCache // Snapshots for recent block to speed up reorgs 203 signatures *lru.ARCCache // Signatures of recent blocks to speed up mining 204 205 blacklists *lru.Cache // blacklists caches recent blacklist to speed up transactions validation 206 blLock sync.Mutex // Make sure only get blacklist once for each block 207 eventCheckRules *lru.Cache // eventCheckRules caches recent EventCheckRules to speed up log validation 208 rulesLock sync.Mutex // Make sure only get eventCheckRules once for each block 209 210 proposals map[common.Address]bool // Current list of proposals we are pushing 211 212 signer types.Signer // the signer instance to recover tx sender 213 214 validator common.Address // Ethereum address of the signing key 215 signFn ValidatorFn // Validator function to authorize hashes with 216 signTxFn SignTxFn 217 lock sync.RWMutex // Protects the validator fields 218 219 stateFn StateFn // Function to get state by state root 220 221 abi map[string]abi.ABI // Interactive with system contracts 222 223 chain consensus.ChainHeaderReader // chain is only for reading parent headers when getting blacklist and rules 224 225 // The fields below are for testing only 226 fakeDiff bool // Skip difficulty verifications 227 } 228 229 // New creates a Dpos proof-of-stake-authority consensus engine with the initial 230 // validators set to the ones provided by the user. 231 func New(chainConfig *params.ChainConfig, db ethdb.Database) *Dpos { 232 // Set any missing consensus parameters to their defaults 233 conf := *chainConfig.Dpos 234 if conf.Epoch == 0 { 235 conf.Epoch = epochLength 236 } 237 // Allocate the snapshot caches and create the engine 238 recents, _ := lru.NewARC(inmemorySnapshots) 239 signatures, _ := lru.NewARC(inmemorySignatures) 240 blacklists, _ := lru.New(inmemoryBlacklist) 241 rules, _ := lru.New(inmemoryBlacklist) 242 243 return &Dpos{ 244 chainConfig: chainConfig, 245 config: &conf, 246 db: db, 247 recents: recents, 248 signatures: signatures, 249 blacklists: blacklists, 250 eventCheckRules: rules, 251 proposals: make(map[common.Address]bool), 252 abi: systemcontract.GetInteractiveABI(), 253 signer: types.LatestSignerForChainID(chainConfig.ChainID), 254 } 255 } 256 257 func (d *Dpos) SetChain(chain consensus.ChainHeaderReader) { 258 d.chain = chain 259 } 260 261 // SetStateFn sets the function to get state. 262 func (d *Dpos) SetStateFn(fn StateFn) { 263 d.stateFn = fn 264 } 265 266 // Author implements consensus.Engine, returning the Ethereum address recovered 267 // from the signature in the header's extra-data section. 268 func (d *Dpos) Author(header *types.Header) (common.Address, error) { 269 return header.Coinbase, nil 270 // return ecrecover(header, d.signatures) 271 } 272 273 // VerifyHeader checks whether a header conforms to the consensus rules. 274 func (d *Dpos) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { 275 return d.verifyHeader(chain, header, nil) 276 } 277 278 // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The 279 // method returns a quit channel to abort the operations and a results channel to 280 // retrieve the async verifications (the order is that of the input slice). 281 func (d *Dpos) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { 282 abort := make(chan struct{}) 283 results := make(chan error, len(headers)) 284 285 go func() { 286 for i, header := range headers { 287 err := d.verifyHeader(chain, header, headers[:i]) 288 289 select { 290 case <-abort: 291 return 292 case results <- err: 293 } 294 } 295 }() 296 return abort, results 297 } 298 299 // verifyHeader checks whether a header conforms to the consensus rules.The 300 // caller may optionally pass in a batch of parents (ascending order) to avoid 301 // looking those up from the database. This is useful for concurrently verifying 302 // a batch of new headers. 303 func (d *Dpos) verifyHeader(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { 304 if header.Number == nil { 305 return errUnknownBlock 306 } 307 number := header.Number.Uint64() 308 309 // Don't waste time checking blocks from the future 310 if header.Time > uint64(time.Now().Unix()) { 311 return consensus.ErrFutureBlock 312 } 313 // Check that the extra-data contains the vanity, validators and signature. 314 if len(header.Extra) < extraVanity { 315 return errMissingVanity 316 } 317 if len(header.Extra) < extraVanity+extraSeal { 318 return errMissingSignature 319 } 320 // check extra data 321 isEpoch := number%d.config.Epoch == 0 322 323 // Ensure that the extra-data contains a validator list on checkpoint, but none otherwise 324 validatorsBytes := len(header.Extra) - extraVanity - extraSeal 325 if !isEpoch && validatorsBytes != 0 { 326 return errExtraValidators 327 } 328 // Ensure that the validator bytes length is valid 329 if isEpoch && validatorsBytes%common.AddressLength != 0 { 330 return errExtraValidators 331 } 332 333 // Ensure that the mix digest is zero as we don't have fork protection currently 334 if header.MixDigest != (common.Hash{}) { 335 return errInvalidMixDigest 336 } 337 // Ensure that the block doesn't contain any uncles which are meaningless in PoA 338 if header.UncleHash != uncleHash { 339 return errInvalidUncleHash 340 } 341 // Ensure that the block's difficulty is meaningful (may not be correct at this point) 342 if number > 0 && header.Difficulty == nil { 343 return errInvalidDifficulty 344 } 345 // Verify that the gas limit is <= 2^63-1 346 cap := uint64(0x7fffffffffffffff) 347 if header.GasLimit > cap { 348 return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap) 349 } 350 // If all checks passed, validate any special fields for hard forks 351 if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil { 352 return err 353 } 354 // All basic checks passed, verify cascading fields 355 return d.verifyCascadingFields(chain, header, parents) 356 } 357 358 // verifyCascadingFields verifies all the header fields that are not standalone, 359 // rather depend on a batch of previous headers. The caller may optionally pass 360 // in a batch of parents (ascending order) to avoid looking those up from the 361 // database. This is useful for concurrently verifying a batch of new headers. 362 func (d *Dpos) verifyCascadingFields(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { 363 // The genesis block is the always valid dead-end 364 number := header.Number.Uint64() 365 if number == 0 { 366 return nil 367 } 368 369 var parent *types.Header 370 if len(parents) > 0 { 371 parent = parents[len(parents)-1] 372 } else { 373 parent = chain.GetHeader(header.ParentHash, number-1) 374 } 375 if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { 376 return consensus.ErrUnknownAncestor 377 } 378 379 if parent.Time+d.config.Period > header.Time { 380 return ErrInvalidTimestamp 381 } 382 383 // Verify that the gasUsed is <= gasLimit 384 if header.GasUsed > header.GasLimit { 385 return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) 386 } 387 if !chain.Config().IsLondon(header.Number) { 388 // Verify BaseFee not present before EIP-1559 fork. 389 if header.BaseFee != nil { 390 return fmt.Errorf("invalid baseFee before fork: have %d, want <nil>", header.BaseFee) 391 } 392 if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil { 393 return err 394 } 395 } else if err := misc.VerifyEip1559Header(chain.Config(), parent, header); err != nil { 396 // Verify the header's EIP-1559 attributes. 397 return err 398 } 399 400 // All basic checks passed, verify the seal and return 401 return d.verifySeal(chain, header, parents) 402 } 403 404 // snapshot retrieves the authorization snapshot at a given point in time. 405 func (d *Dpos) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) { 406 // Search for a snapshot in memory or on disk for checkpoints 407 var ( 408 headers []*types.Header 409 snap *Snapshot 410 ) 411 for snap == nil { 412 // If an in-memory snapshot was found, use that 413 if s, ok := d.recents.Get(hash); ok { 414 snap = s.(*Snapshot) 415 break 416 } 417 // If an on-disk checkpoint snapshot can be found, use that 418 if number%checkpointInterval == 0 { 419 if s, err := loadSnapshot(d.config, d.signatures, d.db, hash); err == nil { 420 log.Trace("Loaded voting snapshot from disk", "number", number, "hash", hash) 421 snap = s 422 break 423 } 424 } 425 // If we're at the genesis, snapshot the initial state. Alternatively if we're 426 // at a checkpoint block without a parent (light client CHT), or we have piled 427 // up more headers than allowed to be reorged (chain reinit from a freezer), 428 // consider the checkpoint trusted and snapshot it. 429 if number == 0 || (number%d.config.Epoch == 0 && (len(headers) > params.FullImmutabilityThreshold || chain.GetHeaderByNumber(number-1) == nil)) { 430 checkpoint := chain.GetHeaderByNumber(number) 431 if checkpoint != nil { 432 hash := checkpoint.Hash() 433 434 validators := make([]common.Address, (len(checkpoint.Extra)-extraVanity-extraSeal)/common.AddressLength) 435 for i := 0; i < len(validators); i++ { 436 copy(validators[i][:], checkpoint.Extra[extraVanity+i*common.AddressLength:]) 437 } 438 snap = newSnapshot(d.config, d.signatures, number, hash, validators) 439 if err := snap.store(d.db); err != nil { 440 return nil, err 441 } 442 log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash) 443 break 444 } 445 } 446 // No snapshot for this header, gather the header and move backward 447 var header *types.Header 448 if len(parents) > 0 { 449 // If we have explicit parents, pick from there (enforced) 450 header = parents[len(parents)-1] 451 if header.Hash() != hash || header.Number.Uint64() != number { 452 return nil, consensus.ErrUnknownAncestor 453 } 454 parents = parents[:len(parents)-1] 455 } else { 456 // No explicit parents (or no more left), reach out to the database 457 header = chain.GetHeader(hash, number) 458 if header == nil { 459 return nil, consensus.ErrUnknownAncestor 460 } 461 } 462 headers = append(headers, header) 463 number, hash = number-1, header.ParentHash 464 } 465 // Previous snapshot found, apply any pending headers on top of it 466 for i := 0; i < len(headers)/2; i++ { 467 headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i] 468 } 469 snap, err := snap.apply(headers, chain, parents) 470 if err != nil { 471 return nil, err 472 } 473 d.recents.Add(snap.Hash, snap) 474 475 // If we've generated a new checkpoint snapshot, save to disk 476 if snap.Number%checkpointInterval == 0 && len(headers) > 0 { 477 if err = snap.store(d.db); err != nil { 478 return nil, err 479 } 480 log.Trace("Stored voting snapshot to disk", "number", snap.Number, "hash", snap.Hash) 481 } 482 return snap, err 483 } 484 485 // VerifyUncles implements consensus.Engine, always returning an error for any 486 // uncles as this consensus mechanism doesn't permit uncles. 487 func (d *Dpos) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { 488 if len(block.Uncles()) > 0 { 489 return errors.New("uncles not allowed") 490 } 491 return nil 492 } 493 494 // VerifySeal implements consensus.Engine, checking whether the signature contained 495 // in the header satisfies the consensus protocol requirements. 496 func (d *Dpos) VerifySeal(chain consensus.ChainHeaderReader, header *types.Header) error { 497 return d.verifySeal(chain, header, nil) 498 } 499 500 // verifySeal checks whether the signature contained in the header satisfies the 501 // consensus protocol requirements. The method accepts an optional list of parent 502 // headers that aren't yet part of the local blockchain to generate the snapshots 503 // from. 504 func (d *Dpos) verifySeal(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { 505 // Verifying the genesis block is not supported 506 number := header.Number.Uint64() 507 if number == 0 { 508 return errUnknownBlock 509 } 510 // Retrieve the snapshot needed to verify this header and cache it 511 snap, err := d.snapshot(chain, number-1, header.ParentHash, parents) 512 if err != nil { 513 return err 514 } 515 516 // Resolve the authorization key and check against validators 517 signer, err := ecrecover(header, d.signatures) 518 if err != nil { 519 return err 520 } 521 if signer != header.Coinbase { 522 return errInvalidCoinbase 523 } 524 525 if _, ok := snap.Validators[signer]; !ok { 526 return errUnauthorizedValidator 527 } 528 529 for seen, recent := range snap.Recents { 530 if recent == signer { 531 // Validator is among recents, only fail if the current block doesn't shift it out 532 if limit := uint64(len(snap.Validators)/2 + 1); seen > number-limit { 533 return errRecentlySigned 534 } 535 } 536 } 537 538 // Ensure that the difficulty corresponds to the turn-ness of the signer 539 if !d.fakeDiff { 540 inturn := snap.inturn(header.Number.Uint64(), signer) 541 if inturn && header.Difficulty.Cmp(diffInTurn) != 0 { 542 return errWrongDifficulty 543 } 544 if !inturn && header.Difficulty.Cmp(diffNoTurn) != 0 { 545 return errWrongDifficulty 546 } 547 } 548 549 return nil 550 } 551 552 // Prepare implements consensus.Engine, preparing all the consensus fields of the 553 // header for running the transactions on top. 554 func (d *Dpos) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { 555 // If the block isn't a checkpoint, cast a random vote (good enough for now) 556 header.Coinbase = d.validator 557 header.Nonce = types.BlockNonce{} 558 559 number := header.Number.Uint64() 560 snap, err := d.snapshot(chain, number-1, header.ParentHash, nil) 561 if err != nil { 562 return err 563 } 564 565 // Set the correct difficulty 566 header.Difficulty = calcDifficulty(snap, d.validator) 567 568 // Ensure the extra data has all its components 569 if len(header.Extra) < extraVanity { 570 header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...) 571 } 572 header.Extra = header.Extra[:extraVanity] 573 574 parent := chain.GetHeader(header.ParentHash, number-1) 575 if parent == nil { 576 return consensus.ErrUnknownAncestor 577 } 578 579 statedb, err := d.stateFn(parent.Root) 580 if err != nil { 581 return err 582 } 583 584 if number%d.config.Epoch == 0 { 585 newValidators, err := d.getCurEpochValidators(chain, header, statedb) 586 if err != nil { 587 return err 588 } 589 590 for _, validator := range newValidators { 591 header.Extra = append(header.Extra, validator.Bytes()...) 592 } 593 } 594 header.Extra = append(header.Extra, make([]byte, extraSeal)...) 595 596 // Mix digest is reserved for now, set to empty 597 header.MixDigest = common.Hash{} 598 599 // Ensure the timestamp has the correct delay 600 header.Time = parent.Time + d.config.Period 601 if header.Time < uint64(time.Now().Unix()) { 602 header.Time = uint64(time.Now().Unix()) 603 } 604 return nil 605 } 606 607 // Finalize implements consensus.Engine, ensuring no uncles are set, nor block 608 // rewards given. 609 func (d *Dpos) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, uncles []*types.Header, receipts *[]*types.Receipt, systemTxs []*types.Transaction) error { 610 // Initialize all system contracts at block 1. 611 if header.Number.Cmp(common.Big1) == 0 { 612 if err := d.initializeSystemContracts(chain, header, state); err != nil { 613 log.Error("Initialize system contracts failed", "err", err) 614 return err 615 } 616 } 617 618 if header.Difficulty.Cmp(diffInTurn) != 0 { 619 if err := d.tryPunishValidator(chain, header, state); err != nil { 620 return err 621 } 622 } 623 624 // avoid nil pointer 625 if txs == nil { 626 s := make([]*types.Transaction, 0) 627 txs = &s 628 } 629 if receipts == nil { 630 rs := make([]*types.Receipt, 0) 631 receipts = &rs 632 } 633 634 // deposit block reward 635 if err := d.trySendBlockReward(chain, header, state); err != nil { 636 return err 637 } 638 639 // do epoch thing at the end, because it will update active validators 640 if header.Number.Uint64()%d.config.Epoch == 0 { 641 642 newEpochValidators, err := d.getCurEpochValidators(chain, header, state) 643 if err != nil { 644 return err 645 } 646 log.Info("New Epoch", "header", header.Number.Uint64(), "epoch", header.Number.Uint64()/d.config.Epoch) 647 648 validatorsBytes := make([]byte, len(newEpochValidators)*common.AddressLength) 649 for i, validator := range newEpochValidators { 650 copy(validatorsBytes[i*common.AddressLength:], validator.Bytes()) 651 } 652 653 extraSuffix := len(header.Extra) - extraSeal 654 if !bytes.Equal(header.Extra[extraVanity:extraSuffix], validatorsBytes) { 655 return errInvalidExtraValidators 656 } 657 } 658 659 //handle system governance Proposal 660 if chain.Config().IsRedCoast(header.Number) { 661 proposalCount, err := d.getPassedProposalCount(chain, header, state) 662 if err != nil { 663 return err 664 } 665 if proposalCount != uint32(len(systemTxs)) { 666 return errInvalidSysGovCount 667 } 668 // Due to the logics of the finish operation of contract `governance`, when finishing a proposal which 669 // is not the last passed proposal, it will change the sequence. So in here we must first executes all 670 // passed proposals, and then finish then all. 671 pIds := make([]*big.Int, 0, proposalCount) 672 for i := uint32(0); i < proposalCount; i++ { 673 prop, err := d.getPassedProposalByIndex(chain, header, state, i) 674 if err != nil { 675 return err 676 } 677 // execute the system governance Proposal 678 tx := systemTxs[int(i)] 679 receipt, err := d.replayProposal(chain, header, state, prop, len(*txs), tx) 680 if err != nil { 681 return err 682 } 683 *txs = append(*txs, tx) 684 *receipts = append(*receipts, receipt) 685 // set 686 pIds = append(pIds, prop.Id) 687 } 688 // Finish all proposal 689 for i := uint32(0); i < proposalCount; i++ { 690 err = d.finishProposalById(chain, header, state, pIds[i]) 691 if err != nil { 692 return err 693 } 694 } 695 } 696 697 // No block rewards in PoA, so the state remains as is and uncles are dropped 698 header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) 699 header.UncleHash = types.CalcUncleHash(nil) 700 701 return nil 702 } 703 704 // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, 705 // nor block rewards given, and returns the final block. 706 func (d *Dpos) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (b *types.Block, rs []*types.Receipt, err error) { 707 defer func() { 708 if err != nil { 709 log.Warn("FinalizeAndAssemble failed", "err", err) 710 } 711 }() 712 // Initialize all system contracts at block 1. 713 if header.Number.Cmp(common.Big1) == 0 { 714 if err := d.initializeSystemContracts(chain, header, state); err != nil { 715 panic(err) 716 } 717 } 718 719 // punish validator if necessary 720 if header.Difficulty.Cmp(diffInTurn) != 0 { 721 err := d.tryPunishValidator(chain, header, state) 722 if err != nil { 723 panic(err) 724 } 725 } 726 727 // deposit block reward 728 if err := d.trySendBlockReward(chain, header, state); err != nil { 729 panic(err) 730 } 731 732 // do something at the epoch end 733 if header.Number.Uint64()%d.config.Epoch == 0 { 734 735 newEpochValidators, err := d.getCurEpochValidators(chain, header, state) 736 if err != nil { 737 panic(err) 738 } 739 log.Info("New Epoch", "header", header.Number.Uint64(), "epoch", header.Number.Uint64()/d.config.Epoch, "count", len(newEpochValidators), "newEpochValidators", newEpochValidators) 740 } 741 742 //handle system governance Proposal 743 // 744 // Note: 745 // Even if the miner is not `running`, it's still working, 746 // the 'miner.worker' will try to FinalizeAndAssemble a block, 747 // in this case, the signTxFn is not set. A `non-miner node` can't execute system governance proposal. 748 if d.signTxFn != nil && chain.Config().IsRedCoast(header.Number) { 749 proposalCount, err := d.getPassedProposalCount(chain, header, state) 750 if err != nil { 751 return nil, nil, err 752 } 753 754 // Due to the logics of the finish operation of contract `governance`, when finishing a proposal which 755 // is not the last passed proposal, it will change the sequence. So in here we must first executes all 756 // passed proposals, and then finish then all. 757 pIds := make([]*big.Int, 0, proposalCount) 758 for i := uint32(0); i < proposalCount; i++ { 759 prop, err := d.getPassedProposalByIndex(chain, header, state, i) 760 if err != nil { 761 return nil, nil, err 762 } 763 // execute the system governance Proposal 764 tx, receipt, err := d.executeProposal(chain, header, state, prop, len(txs)) 765 if err != nil { 766 return nil, nil, err 767 } 768 txs = append(txs, tx) 769 receipts = append(receipts, receipt) 770 // set 771 pIds = append(pIds, prop.Id) 772 } 773 // Finish all proposal 774 for i := uint32(0); i < proposalCount; i++ { 775 err = d.finishProposalById(chain, header, state, pIds[i]) 776 if err != nil { 777 return nil, nil, err 778 } 779 } 780 } 781 782 // No block rewards in PoA, so the state remains as is and uncles are dropped 783 header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) 784 header.UncleHash = types.CalcUncleHash(nil) 785 786 // Assemble and return the final block for sealing 787 return types.NewBlock(header, txs, nil, receipts, new(trie.Trie)), receipts, nil 788 } 789 790 func (d *Dpos) trySendBlockReward(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB) error { 791 if header.Coinbase == common.BigToAddress(big.NewInt(0)) { 792 return nil 793 } 794 795 blockRewardEpoch := new(big.Int).Div(header.Number, new(big.Int).SetUint64(d.config.Epoch)) 796 797 s := systemcontract.NewSystemRewards() 798 // get Block Reward 799 epochInfo, err := s.GetEpochInfo(state, header, newChainContext(chain, d), d.chainConfig, blockRewardEpoch) 800 if err != nil { 801 log.Error("GetEpochInfo error ", "error", err) 802 return err 803 } 804 805 totalReward := new(big.Int).Add(epochInfo.BlockReward, state.GetBalance(consensus.FeeRecoder)) 806 rewardToFoundation := new(big.Int).Div(new(big.Int).Mul(totalReward, big.NewInt(5)), big.NewInt(100)) 807 rewardToMiner := new(big.Int).Sub(totalReward, rewardToFoundation) 808 809 state.AddBalance(foundationAddress, rewardToFoundation) 810 state.AddBalance(systemcontract.SystemRewardsContractAddr, rewardToMiner) 811 812 // reset tx fee recoder balance 813 state.SetBalance(consensus.FeeRecoder, common.Big0) 814 815 method := "distributeBlockReward" 816 data, err := d.abi[systemcontract.SystemRewardsContractName].Pack(method, rewardToMiner) 817 if err != nil { 818 log.Error("Can't pack data for distributeBlockReward", "err", err) 819 return err 820 } 821 822 nonce := state.GetNonce(header.Coinbase) 823 msg := vmcaller.NewLegacyMessage(header.Coinbase, &systemcontract.SystemRewardsContractAddr, nonce, new(big.Int), math.MaxUint64, new(big.Int), data, true) 824 825 if _, err := vmcaller.ExecuteMsg(msg, state, header, newChainContext(chain, d), d.chainConfig); err != nil { 826 return err 827 } 828 829 return nil 830 } 831 832 func (d *Dpos) tryPunishValidator(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB) error { 833 number := header.Number.Uint64() 834 snap, err := d.snapshot(chain, number-1, header.ParentHash, nil) 835 if err != nil { 836 return err 837 } 838 839 validators := snap.validators() 840 outTurnValidator := validators[number%uint64(len(validators))] 841 // check sigend recently or not 842 signedRecently := false 843 for _, recent := range snap.Recents { 844 if recent == outTurnValidator { 845 signedRecently = true 846 break 847 } 848 } 849 if !signedRecently { 850 return d.punishValidator(outTurnValidator, chain, header, state) 851 } 852 853 return nil 854 } 855 856 // punishValidator punish validator when not mining in turn 857 func (d *Dpos) punishValidator(validator common.Address, chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB) error { 858 859 method := "punish" 860 data, err := d.abi[systemcontract.SystemRewardsContractName].Pack(method, validator) 861 if err != nil { 862 log.Error("punish failed", "error", err) 863 return err 864 } 865 nonce := state.GetNonce(header.Coinbase) 866 msg := vmcaller.NewLegacyMessage(header.Coinbase, &systemcontract.SystemRewardsContractAddr, nonce, new(big.Int), math.MaxUint64, new(big.Int), data, true) 867 // use parent 868 _, err = vmcaller.ExecuteMsg(msg, state, header, newChainContext(chain, d), d.chainConfig) 869 if err != nil { 870 return err 871 } 872 873 return nil 874 } 875 876 // doSomethingAtEpoch tryElect new epoch validators 877 func (d *Dpos) doSomethingAtEpoch(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB) error { 878 if header.Coinbase == common.BigToAddress(common.Big0) { 879 return nil 880 } 881 882 data, err := d.abi[systemcontract.ValidatorsContractName].Pack("tryElect") 883 if err != nil { 884 log.Error("tryElect Pack error", "error", err) 885 return err 886 } 887 888 nonce := state.GetNonce(header.Coinbase) 889 msg := vmcaller.NewLegacyMessage(header.Coinbase, &systemcontract.ValidatorsContractAddr, nonce, new(big.Int), math.MaxInt64, new(big.Int), data, true) 890 if _, err := vmcaller.ExecuteMsg(msg, state, header, newChainContext(chain, d), d.chainConfig); err != nil { 891 log.Error("tryElect execute error", "error", err) 892 return err 893 } 894 895 return nil 896 } 897 898 // initializeSystemContracts initializes all genesis system contracts. 899 func (d *Dpos) initializeSystemContracts(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB) error { 900 if header.Coinbase == common.BigToAddress(big.NewInt(0)) { 901 return nil 902 } 903 904 snap, err := d.snapshot(chain, 0, header.ParentHash, nil) 905 if err != nil { 906 return err 907 } 908 909 genesisValidators := snap.validators() 910 if len(genesisValidators) != 1 { 911 return errInvalidValidatorsLength 912 } 913 914 initMigrateAddrs, initMigrateBals := systemcontract.InitMigrateAddrBalance() 915 916 method := "initialize" 917 contracts := []struct { 918 addr common.Address 919 packFun func() ([]byte, error) 920 }{ 921 {systemcontract.ValidatorProposalsContractAddr, func() ([]byte, error) { 922 return d.abi[systemcontract.ValidatorProposalsContractName].Pack(method, systemcontract.ValidatorsContractAddr) 923 }}, 924 {systemcontract.SystemRewardsContractAddr, func() ([]byte, error) { 925 return d.abi[systemcontract.SystemRewardsContractName].Pack(method, systemcontract.ValidatorsContractAddr, systemcontract.NodeVotesContractAddr) 926 }}, 927 {systemcontract.ValidatorsContractAddr, func() ([]byte, error) { 928 return d.abi[systemcontract.ValidatorsContractName].Pack(method, systemcontract.ValidatorProposalsContractAddr, systemcontract.SystemRewardsContractAddr, systemcontract.NodeVotesContractAddr, genesisValidators[0], systemcontract.InitDeposit, systemcontract.InitRate, systemcontract.InitName, systemcontract.InitDetails) 929 }}, 930 {systemcontract.NodeVotesContractAddr, func() ([]byte, error) { 931 return d.abi[systemcontract.NodeVotesContractName].Pack(method, systemcontract.ValidatorsContractAddr, systemcontract.SystemRewardsContractAddr) 932 }}, 933 {systemcontract.MigrateContractAddr, func() ([]byte, error) { 934 return d.abi[systemcontract.MigrateContractName].Pack(method, systemcontract.MigrateOwner, initMigrateAddrs, initMigrateBals) 935 }}, 936 {systemcontract.AddressListContractAddr, func() ([]byte, error) { 937 return d.abi[systemcontract.AddressListContractName].Pack(method, systemcontract.DevAdmin) 938 }}, 939 {systemcontract.AddressListContractAddr, func() ([]byte, error) { 940 return d.abi[systemcontract.AddressListContractName].Pack("initializeV2") 941 }}, 942 {systemcontract.ProposalsContractAddr, func() ([]byte, error) { 943 return d.abi[systemcontract.ProposalsContractName].Pack(method, genesisValidators) 944 }}, 945 } 946 947 for _, contract := range contracts { 948 data, err := contract.packFun() 949 if err != nil { 950 return err 951 } 952 nonce := state.GetNonce(genesisValidators[0]) 953 954 var msg types.Message 955 956 if contract.addr == systemcontract.ValidatorsContractAddr { 957 msg = vmcaller.NewLegacyMessage(genesisValidators[0], &contract.addr, nonce, systemcontract.InitDeposit, math.MaxUint64, new(big.Int), data, true) 958 } else { 959 msg = vmcaller.NewLegacyMessage(genesisValidators[0], &contract.addr, nonce, new(big.Int), math.MaxUint64, new(big.Int), data, true) 960 } 961 962 if _, err := vmcaller.ExecuteMsg(msg, state, header, newChainContext(chain, d), d.chainConfig); err != nil { 963 log.Error("initializeSystemContracts execute error", "contract", contract.addr.String()) 964 return err 965 } 966 } 967 968 return nil 969 } 970 971 // get current epoch validators after try elect 972 func (d *Dpos) getCurEpochValidators(chain consensus.ChainHeaderReader, header *types.Header, statedb *state.StateDB) ([]common.Address, error) { 973 974 method := "getCurEpochValidators" 975 data, err := d.abi[systemcontract.ValidatorsContractName].Pack(method) 976 if err != nil { 977 log.Error("Can't pack data for curEpochValidators", "error", err) 978 return []common.Address{}, err 979 } 980 981 msg := vmcaller.NewLegacyMessage(header.Coinbase, &systemcontract.ValidatorsContractAddr, 0, new(big.Int), math.MaxUint64, new(big.Int), data, false) 982 result, err := vmcaller.ExecuteMsg(msg, statedb, header, newChainContext(chain, d), d.chainConfig) 983 if err != nil { 984 return []common.Address{}, err 985 } 986 987 // unpack data 988 ret, err := d.abi[systemcontract.ValidatorsContractName].Unpack(method, result) 989 if err != nil { 990 return []common.Address{}, err 991 } 992 if len(ret) != 1 { 993 return []common.Address{}, errors.New("invalid params length") 994 } 995 validators, ok := ret[0].([]common.Address) 996 if !ok { 997 return []common.Address{}, errors.New("invalid validators format") 998 } 999 return validators, err 1000 } 1001 1002 // Authorize injects a private key into the consensus engine to mint new blocks 1003 // with. 1004 func (d *Dpos) Authorize(validator common.Address, signFn ValidatorFn, signTxFn SignTxFn) { 1005 d.lock.Lock() 1006 defer d.lock.Unlock() 1007 1008 d.validator = validator 1009 d.signFn = signFn 1010 d.signTxFn = signTxFn 1011 } 1012 1013 // Seal implements consensus.Engine, attempting to create a sealed block using 1014 // the local signing credentials. 1015 func (d *Dpos) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { 1016 header := block.Header() 1017 1018 // Sealing the genesis block is not supported 1019 number := header.Number.Uint64() 1020 if number == 0 { 1021 return errUnknownBlock 1022 } 1023 // For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing) 1024 if d.config.Period == 0 && len(block.Transactions()) == 0 { 1025 log.Info("Sealing paused, waiting for transactions") 1026 return nil 1027 } 1028 // Don't hold the val fields for the entire sealing procedure 1029 d.lock.RLock() 1030 val, signFn := d.validator, d.signFn 1031 d.lock.RUnlock() 1032 1033 // Bail out if we're unauthorized to sign a block 1034 snap, err := d.snapshot(chain, number-1, header.ParentHash, nil) 1035 if err != nil { 1036 return err 1037 } 1038 if _, authorized := snap.Validators[val]; !authorized { 1039 return errUnauthorizedValidator 1040 } 1041 // If we're amongst the recent validators, wait for the next block 1042 for seen, recent := range snap.Recents { 1043 if recent == val { 1044 // Validator is among recents, only wait if the current block doesn't shift it out 1045 if limit := uint64(len(snap.Validators)/2 + 1); number < limit || seen > number-limit { 1046 log.Info("Signed recently, must wait for others") 1047 return nil 1048 } 1049 } 1050 } 1051 1052 // Sweet, the protocol permits us to sign the block, wait for our time 1053 delay := time.Unix(int64(header.Time), 0).Sub(time.Now()) // nolint: gosimple 1054 if header.Difficulty.Cmp(diffNoTurn) == 0 { 1055 // It's not our turn explicitly to sign, delay it a bit 1056 wiggle := time.Duration(len(snap.Validators)/2+1) * wiggleTime 1057 delay += time.Duration(rand.Int63n(int64(wiggle))) 1058 1059 log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle)) 1060 } 1061 // Sign all the things! 1062 sighash, err := signFn(accounts.Account{Address: val}, accounts.MimetypeDpos, DposRLP(header)) 1063 if err != nil { 1064 return err 1065 } 1066 copy(header.Extra[len(header.Extra)-extraSeal:], sighash) 1067 // Wait until sealing is terminated or delay timeout. 1068 log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay)) 1069 go func() { 1070 select { 1071 case <-stop: 1072 return 1073 case <-time.After(delay): 1074 } 1075 1076 select { 1077 case results <- block.WithSeal(header): 1078 default: 1079 log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header)) 1080 } 1081 }() 1082 1083 return nil 1084 } 1085 1086 // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty 1087 // that a new block should have: 1088 // * DIFF_NOTURN(2) if BLOCK_NUMBER % validator_COUNT != validator_INDEX 1089 // * DIFF_INTURN(1) if BLOCK_NUMBER % validator_COUNT == validator_INDEX 1090 func (d *Dpos) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { 1091 snap, err := d.snapshot(chain, parent.Number.Uint64(), parent.Hash(), nil) 1092 if err != nil { 1093 return nil 1094 } 1095 return calcDifficulty(snap, d.validator) 1096 } 1097 1098 func calcDifficulty(snap *Snapshot, validator common.Address) *big.Int { 1099 if snap.inturn(snap.Number+1, validator) { 1100 return new(big.Int).Set(diffInTurn) 1101 } 1102 return new(big.Int).Set(diffNoTurn) 1103 } 1104 1105 // SealHash returns the hash of a block prior to it being sealed. 1106 func (d *Dpos) SealHash(header *types.Header) common.Hash { 1107 return SealHash(header) 1108 } 1109 1110 // Close implements consensus.Engine. It's a noop for dpos as there are no background threads. 1111 func (d *Dpos) Close() error { 1112 return nil 1113 } 1114 1115 // APIs implements consensus.Engine, returning the user facing RPC API to allow 1116 // controlling the validator voting. 1117 func (d *Dpos) APIs(chain consensus.ChainHeaderReader) []rpc.API { 1118 return []rpc.API{{ 1119 Namespace: "dpos", 1120 Version: "1.0", 1121 Service: &API{chain: chain, dpos: d}, 1122 Public: false, 1123 }} 1124 } 1125 1126 // SealHash returns the hash of a block prior to it being sealed. 1127 func SealHash(header *types.Header) (hash common.Hash) { 1128 hasher := sha3.NewLegacyKeccak256() 1129 encodeSigHeader(hasher, header) 1130 hasher.Sum(hash[:0]) 1131 return hash 1132 } 1133 1134 // DposRLP returns the rlp bytes which needs to be signed for the proof-of-stake-authority 1135 // sealing. The RLP to sign consists of the entire header apart from the 65 byte signature 1136 // contained at the end of the extra data. 1137 // 1138 // Note, the method requires the extra data to be at least 65 bytes, otherwise it 1139 // panics. This is done to avoid accidentally using both forms (signature present 1140 // or not), which could be abused to produce different hashes for the same header. 1141 func DposRLP(header *types.Header) []byte { 1142 b := new(bytes.Buffer) 1143 encodeSigHeader(b, header) 1144 return b.Bytes() 1145 } 1146 1147 func encodeSigHeader(w io.Writer, header *types.Header) { 1148 err := rlp.Encode(w, []interface{}{ 1149 header.ParentHash, 1150 header.UncleHash, 1151 header.Coinbase, 1152 header.Root, 1153 header.TxHash, 1154 header.ReceiptHash, 1155 header.Bloom, 1156 header.Difficulty, 1157 header.Number, 1158 header.GasLimit, 1159 header.GasUsed, 1160 header.Time, 1161 header.Extra[:len(header.Extra)-crypto.SignatureLength], // Yes, this will panic if extra is too short 1162 header.MixDigest, 1163 header.Nonce, 1164 }) 1165 if err != nil { 1166 panic("can't encode: " + err.Error()) 1167 } 1168 } 1169 1170 func (d *Dpos) PreHandle(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB) error { 1171 return nil 1172 } 1173 1174 // IsSysTransaction checks whether a specific transaction is a system transaction. 1175 func (d *Dpos) IsSysTransaction(sender common.Address, tx *types.Transaction, header *types.Header) (bool, error) { 1176 if tx.To() == nil { 1177 return false, nil 1178 } 1179 1180 to := tx.To() 1181 if sender == header.Coinbase && *to == systemcontract.SysGovToAddr && tx.GasPrice().Sign() == 0 { 1182 return true, nil 1183 } 1184 // Make sure the miner can NOT call the system contract through a normal transaction. 1185 if sender == header.Coinbase && *to == systemcontract.SysGovContractAddr { 1186 return true, nil 1187 } 1188 return false, nil 1189 } 1190 1191 // CanCreate determines where a given address can create a new contract. 1192 // 1193 // This will query the system Developers contract, by DIRECTLY to get the target slot value of the contract, 1194 // it means that it's strongly relative to the layout of the Developers contract's state variables 1195 func (d *Dpos) CanCreate(state consensus.StateReader, addr common.Address, height *big.Int) bool { 1196 if d.chainConfig.IsRedCoast(height) && d.config.EnableDevVerification { 1197 if isDeveloperVerificationEnabled(state) { 1198 slot := calcSlotOfDevMappingKey(addr) 1199 valueHash := state.GetState(systemcontract.AddressListContractAddr, slot) 1200 // none zero value means true 1201 return valueHash.Big().Sign() > 0 1202 } 1203 } 1204 return true 1205 } 1206 1207 // ValidateTx do a consensus-related validation on the given transaction at the given header and state. 1208 // the parentState must be the state of the header's parent block. 1209 func (d *Dpos) ValidateTx(sender common.Address, tx *types.Transaction, header *types.Header, parentState *state.StateDB) error { 1210 // Must use the parent state for current validation, 1211 // so we must start the validation after redCoastBlock 1212 if d.chainConfig.RedCoastBlock != nil && d.chainConfig.RedCoastBlock.Cmp(header.Number) < 0 { 1213 m, err := d.getBlacklist(header, parentState) 1214 if err != nil { 1215 return err 1216 } 1217 if d, exist := m[sender]; exist && (d != DirectionTo) { 1218 log.Trace("Hit blacklist", "tx", tx.Hash().String(), "addr", sender.String(), "direction", d) 1219 return types.ErrAddressDenied 1220 } 1221 if to := tx.To(); to != nil { 1222 if d, exist := m[*to]; exist && (d != DirectionFrom) { 1223 log.Trace("Hit blacklist", "tx", tx.Hash().String(), "addr", to.String(), "direction", d) 1224 return types.ErrAddressDenied 1225 } 1226 } 1227 } 1228 return nil 1229 } 1230 1231 func (d *Dpos) getBlacklist(header *types.Header, parentState *state.StateDB) (map[common.Address]blacklistDirection, error) { 1232 defer func(start time.Time) { 1233 getblacklistTimer.UpdateSince(start) 1234 }(time.Now()) 1235 1236 if v, ok := d.blacklists.Get(header.ParentHash); ok { 1237 return v.(map[common.Address]blacklistDirection), nil 1238 } 1239 1240 d.blLock.Lock() 1241 defer d.blLock.Unlock() 1242 if v, ok := d.blacklists.Get(header.ParentHash); ok { 1243 return v.(map[common.Address]blacklistDirection), nil 1244 } 1245 1246 // if the last updates is long ago, we don't need to get blacklist from the contract. 1247 if d.chainConfig.SophonBlock != nil && header.Number.Cmp(d.chainConfig.SophonBlock) > 0 { 1248 num := header.Number.Uint64() 1249 lastUpdated := lastBlacklistUpdatedNumber(parentState) 1250 if num >= 2 && num > lastUpdated+1 { 1251 parent := d.chain.GetHeader(header.ParentHash, num-1) 1252 if parent != nil { 1253 if v, ok := d.blacklists.Get(parent.ParentHash); ok { 1254 m := v.(map[common.Address]blacklistDirection) 1255 d.blacklists.Add(header.ParentHash, m) 1256 return m, nil 1257 } 1258 } else { 1259 log.Error("Unexpected error when getBlacklist, can not get parent from chain", "number", num, "blockHash", header.Hash(), "parentHash", header.ParentHash) 1260 } 1261 } 1262 } 1263 1264 // can't get blacklist from cache, try to call the contract 1265 alABI := d.abi[systemcontract.AddressListContractName] 1266 get := func(method string) ([]common.Address, error) { 1267 ret, err := d.commonCallContract(header, parentState, alABI, systemcontract.AddressListContractAddr, method, 1) 1268 if err != nil { 1269 log.Error(fmt.Sprintf("%s failed", method), "err", err) 1270 return nil, err 1271 } 1272 1273 blacks, ok := ret[0].([]common.Address) 1274 if !ok { 1275 return []common.Address{}, errors.New("invalid blacklist format") 1276 } 1277 return blacks, nil 1278 } 1279 froms, err := get("getBlacksFrom") 1280 if err != nil { 1281 return nil, err 1282 } 1283 tos, err := get("getBlacksTo") 1284 if err != nil { 1285 return nil, err 1286 } 1287 1288 m := make(map[common.Address]blacklistDirection) 1289 for _, from := range froms { 1290 m[from] = DirectionFrom 1291 } 1292 for _, to := range tos { 1293 if _, exist := m[to]; exist { 1294 m[to] = DirectionBoth 1295 } else { 1296 m[to] = DirectionTo 1297 } 1298 } 1299 d.blacklists.Add(header.ParentHash, m) 1300 return m, nil 1301 } 1302 1303 func (d *Dpos) CreateEvmExtraValidator(header *types.Header, parentState *state.StateDB) types.EvmExtraValidator { 1304 if d.chainConfig.SophonBlock != nil && d.chainConfig.SophonBlock.Cmp(header.Number) < 0 { 1305 blacks, err := d.getBlacklist(header, parentState) 1306 if err != nil { 1307 log.Error("getBlacklist failed", "err", err) 1308 return nil 1309 } 1310 rules, err := d.getEventCheckRules(header, parentState) 1311 if err != nil { 1312 log.Error("getEventCheckRules failed", "err", err) 1313 return nil 1314 } 1315 return &blacklistValidator{ 1316 blacks: blacks, 1317 rules: rules, 1318 } 1319 } 1320 return nil 1321 } 1322 1323 func (d *Dpos) getEventCheckRules(header *types.Header, parentState *state.StateDB) (map[common.Hash]*EventCheckRule, error) { 1324 defer func(start time.Time) { 1325 getRulesTimer.UpdateSince(start) 1326 }(time.Now()) 1327 1328 if v, ok := d.eventCheckRules.Get(header.ParentHash); ok { 1329 return v.(map[common.Hash]*EventCheckRule), nil 1330 } 1331 1332 d.rulesLock.Lock() 1333 defer d.rulesLock.Unlock() 1334 if v, ok := d.eventCheckRules.Get(header.ParentHash); ok { 1335 return v.(map[common.Hash]*EventCheckRule), nil 1336 } 1337 1338 // if the last updates is long ago, we don't need to get blacklist from the contract. 1339 num := header.Number.Uint64() 1340 lastUpdated := lastRulesUpdatedNumber(parentState) 1341 if num >= 2 && num > lastUpdated+1 { 1342 parent := d.chain.GetHeader(header.ParentHash, num-1) 1343 if parent != nil { 1344 if v, ok := d.eventCheckRules.Get(parent.ParentHash); ok { 1345 m := v.(map[common.Hash]*EventCheckRule) 1346 d.eventCheckRules.Add(header.ParentHash, m) 1347 return m, nil 1348 } 1349 } else { 1350 log.Error("Unexpected error when getEventCheckRules, can not get parent from chain", "number", num, "blockHash", header.Hash(), "parentHash", header.ParentHash) 1351 } 1352 } 1353 1354 // can't get blacklist from cache, try to call the contract 1355 alABI := d.abi[systemcontract.AddressListContractName] 1356 method := "getRuleByIndex" 1357 get := func(i uint32) (common.Hash, int, common.AddressCheckType, error) { 1358 ret, err := d.commonCallContract(header, parentState, alABI, systemcontract.AddressListContractAddr, method, 3, i) 1359 if err != nil { 1360 return common.Hash{}, 0, common.CheckNone, err 1361 } 1362 sig := ret[0].([32]byte) 1363 idx := ret[1].(*big.Int).Uint64() 1364 ct := ret[2].(uint8) 1365 1366 return sig, int(idx), common.AddressCheckType(ct), nil 1367 } 1368 1369 cnt, err := d.getEventCheckRulesLen(header, parentState) 1370 if err != nil { 1371 log.Error("getEventCheckRulesLen failed", "err", err) 1372 return nil, err 1373 } 1374 rules := make(map[common.Hash]*EventCheckRule) 1375 for i := 0; i < cnt; i++ { 1376 sig, idx, ct, err := get(uint32(i)) 1377 if err != nil { 1378 log.Error("getRuleByIndex failed", "index", i, "number", num, "blockHash", header.Hash(), "err", err) 1379 return nil, err 1380 } 1381 rule, exist := rules[sig] 1382 if !exist { 1383 rule = &EventCheckRule{ 1384 EventSig: sig, 1385 Checks: make(map[int]common.AddressCheckType), 1386 } 1387 rules[sig] = rule 1388 } 1389 rule.Checks[idx] = ct 1390 } 1391 1392 d.eventCheckRules.Add(header.ParentHash, rules) 1393 return rules, nil 1394 } 1395 1396 func (d *Dpos) getEventCheckRulesLen(header *types.Header, parentState *state.StateDB) (int, error) { 1397 ret, err := d.commonCallContract(header, parentState, d.abi[systemcontract.AddressListContractName], systemcontract.AddressListContractAddr, "rulesLen", 1) 1398 if err != nil { 1399 return 0, err 1400 } 1401 ln, ok := ret[0].(uint32) 1402 if !ok { 1403 return 0, fmt.Errorf("unexpected output type, value: %v", ret[0]) 1404 } 1405 return int(ln), nil 1406 } 1407 1408 func (d *Dpos) commonCallContract(header *types.Header, statedb *state.StateDB, contractABI abi.ABI, addr common.Address, method string, expectResultLen int, args ...interface{}) ([]interface{}, error) { 1409 data, err := contractABI.Pack(method, args...) 1410 if err != nil { 1411 log.Error("Can't pack data ", "method", method, "err", err) 1412 return nil, err 1413 } 1414 1415 msg := vmcaller.NewLegacyMessage(header.Coinbase, &addr, 0, new(big.Int), math.MaxUint64, new(big.Int), data, false) 1416 1417 // Note: It's safe to use minimalChainContext for executing AddressListContract 1418 result, err := vmcaller.ExecuteMsg(msg, statedb, header, newMinimalChainContext(d), d.chainConfig) 1419 if err != nil { 1420 return nil, err 1421 } 1422 1423 // unpack data 1424 ret, err := contractABI.Unpack(method, result) 1425 if err != nil { 1426 return nil, err 1427 } 1428 if len(ret) != expectResultLen { 1429 return nil, errors.New("invalid result length") 1430 } 1431 return ret, nil 1432 } 1433 1434 // Since the state variables are as follows: 1435 // bool public initialized; 1436 // bool public enabled; 1437 // address public admin; 1438 // address public pendingAdmin; 1439 // mapping(address => bool) private devs; 1440 // 1441 // according to [Layout of State Variables in Storage](https://docs.soliditylang.org/en/v0.8.4/internals/layout_in_storage.html), 1442 // and after optimizer enabled, the `initialized`, `enabled` and `admin` will be packed, and stores at slot 0, 1443 // `pendingAdmin` stores at slot 1, and the position for `devs` is 2. 1444 func isDeveloperVerificationEnabled(state consensus.StateReader) bool { 1445 compactValue := state.GetState(systemcontract.AddressListContractAddr, common.Hash{}) 1446 // Layout of slot 0: 1447 // [0 - 9][10-29][ 30 ][ 31 ] 1448 // [zero bytes][admin][enabled][initialized] 1449 enabledByte := compactValue.Bytes()[common.HashLength-2] 1450 return enabledByte == 0x01 1451 } 1452 1453 func calcSlotOfDevMappingKey(addr common.Address) common.Hash { 1454 p := make([]byte, common.HashLength) 1455 binary.BigEndian.PutUint16(p[common.HashLength-2:], uint16(systemcontract.DevMappingPosition)) 1456 return crypto.Keccak256Hash(addr.Hash().Bytes(), p) 1457 } 1458 1459 func lastBlacklistUpdatedNumber(state consensus.StateReader) uint64 { 1460 value := state.GetState(systemcontract.AddressListContractAddr, systemcontract.BlackLastUpdatedNumberPosition) 1461 return value.Big().Uint64() 1462 } 1463 1464 func lastRulesUpdatedNumber(state consensus.StateReader) uint64 { 1465 value := state.GetState(systemcontract.AddressListContractAddr, systemcontract.RulesLastUpdatedNumberPosition) 1466 return value.Big().Uint64() 1467 }