github.com/marconiprotocol/go-methereum-lite@v0.0.0-20190918214227-3cd8b06fcf99/consensus/ethash/consensus.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 ethash 18 19 import ( 20 "bytes" 21 "errors" 22 "fmt" 23 "math/big" 24 "runtime" 25 "time" 26 27 mapset "github.com/deckarep/golang-set" 28 "github.com/MarconiProtocol/go-methereum-lite/common" 29 "github.com/MarconiProtocol/go-methereum-lite/common/math" 30 "github.com/MarconiProtocol/go-methereum-lite/consensus" 31 "github.com/MarconiProtocol/go-methereum-lite/consensus/misc" 32 "github.com/MarconiProtocol/go-methereum-lite/core/state" 33 "github.com/MarconiProtocol/go-methereum-lite/core/types" 34 "github.com/MarconiProtocol/go-methereum-lite/log" 35 "github.com/MarconiProtocol/go-methereum-lite/params" 36 "github.com/MarconiProtocol/go-methereum-lite/rlp" 37 "golang.org/x/crypto/sha3" 38 "github.com/MarconiProtocol/marconi-cryptonight" 39 ) 40 41 // Ethash proof-of-work protocol constants. 42 var ( 43 SoftLaunchBlockReward = big.NewInt(1e+18) // Block reward in wei for successfully mining a block during the soft launch period 44 MIP1BlockReward = big.NewInt(2e+18) // Block reward in wei for successfully mining a block upward from MIP1Block 45 MIP2BlockReward = big.NewInt(5e+18) // Block reward in wei for successfully mining a block upward from MIP2Block 46 // Note: big.NewInt(int64) overflows for higher digits, use SetString for 10 or higher block rewards 47 MIP3BlockReward, _ = new(big.Int).SetString("10000000000000000000", 10) // Block reward in wei for successfully mining a block upward from MIP3Block 48 MIP4BlockReward = big.NewInt(5e+18) // Block reward in wei for successfully mining a block upward from MIP4Block 49 DefaultBlockReward = big.NewInt(3e+18) // Default block reward 50 maxUncles = 2 // Maximum number of uncles allowed in a single block 51 allowedFutureBlockTime = 15 * time.Second // Max time from current time allowed for blocks, before they're considered future blocks 52 ) 53 54 // Various error messages to mark blocks invalid. These should be private to 55 // prevent engine specific errors from being referenced in the remainder of the 56 // codebase, inherently breaking if the engine is swapped out. Please put common 57 // error types into the consensus package. 58 var ( 59 errLargeBlockTime = errors.New("timestamp too big") 60 errZeroBlockTime = errors.New("timestamp equals parent's") 61 errTooManyUncles = errors.New("too many uncles") 62 errDuplicateUncle = errors.New("duplicate uncle") 63 errUncleIsAncestor = errors.New("uncle is ancestor") 64 errDanglingUncle = errors.New("uncle's parent is not ancestor") 65 errInvalidDifficulty = errors.New("non-positive difficulty") 66 errInvalidMixDigest = errors.New("invalid mix digest") 67 errInvalidPoW = errors.New("invalid proof-of-work") 68 ) 69 70 // Author implements consensus.Engine, returning the header's coinbase as the 71 // proof-of-work verified author of the block. 72 func (ethash *Ethash) Author(header *types.Header) (common.Address, error) { 73 return header.Coinbase, nil 74 } 75 76 // VerifyHeader checks whether a header conforms to the consensus rules of the 77 // stock Ethereum ethash engine. 78 func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { 79 // If we're running a full engine faking, accept any input as valid 80 if ethash.config.PowMode == ModeFullFake { 81 return nil 82 } 83 // Short circuit if the header is known, or it's parent not 84 number := header.Number.Uint64() 85 if chain.GetHeader(header.Hash(), number) != nil { 86 return nil 87 } 88 parent := chain.GetHeader(header.ParentHash, number-1) 89 if parent == nil { 90 return consensus.ErrUnknownAncestor 91 } 92 // Sanity checks passed, do a proper verification 93 return ethash.verifyHeader(chain, header, parent, false, seal) 94 } 95 96 // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers 97 // concurrently. The method returns a quit channel to abort the operations and 98 // a results channel to retrieve the async verifications. 99 func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { 100 // If we're running a full engine faking, accept any input as valid 101 if ethash.config.PowMode == ModeFullFake || len(headers) == 0 { 102 abort, results := make(chan struct{}), make(chan error, len(headers)) 103 for i := 0; i < len(headers); i++ { 104 results <- nil 105 } 106 return abort, results 107 } 108 109 // Spawn as many workers as allowed threads 110 workers := runtime.GOMAXPROCS(0) 111 if len(headers) < workers { 112 workers = len(headers) 113 } 114 115 // Create a task channel and spawn the verifiers 116 var ( 117 inputs = make(chan int) 118 done = make(chan int, workers) 119 errors = make([]error, len(headers)) 120 abort = make(chan struct{}) 121 ) 122 for i := 0; i < workers; i++ { 123 go func() { 124 for index := range inputs { 125 errors[index] = ethash.verifyHeaderWorker(chain, headers, seals, index) 126 done <- index 127 } 128 }() 129 } 130 131 errorsOut := make(chan error, len(headers)) 132 go func() { 133 defer close(inputs) 134 var ( 135 in, out = 0, 0 136 checked = make([]bool, len(headers)) 137 inputs = inputs 138 ) 139 for { 140 select { 141 case inputs <- in: 142 if in++; in == len(headers) { 143 // Reached end of headers. Stop sending to workers. 144 inputs = nil 145 } 146 case index := <-done: 147 for checked[index] = true; checked[out]; out++ { 148 errorsOut <- errors[out] 149 if out == len(headers)-1 { 150 return 151 } 152 } 153 case <-abort: 154 return 155 } 156 } 157 }() 158 return abort, errorsOut 159 } 160 161 func (ethash *Ethash) verifyHeaderWorker(chain consensus.ChainReader, headers []*types.Header, seals []bool, index int) error { 162 var parent *types.Header 163 if index == 0 { 164 parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1) 165 } else if headers[index-1].Hash() == headers[index].ParentHash { 166 parent = headers[index-1] 167 } 168 if parent == nil { 169 return consensus.ErrUnknownAncestor 170 } 171 if chain.GetHeader(headers[index].Hash(), headers[index].Number.Uint64()) != nil { 172 return nil // known block 173 } 174 return ethash.verifyHeader(chain, headers[index], parent, false, seals[index]) 175 } 176 177 // VerifyUncles verifies that the given block's uncles conform to the consensus 178 // rules of the stock Ethereum ethash engine. 179 func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { 180 // If we're running a full engine faking, accept any input as valid 181 if ethash.config.PowMode == ModeFullFake { 182 return nil 183 } 184 // Verify that there are at most 2 uncles included in this block 185 if len(block.Uncles()) > maxUncles { 186 return errTooManyUncles 187 } 188 // Gather the set of past uncles and ancestors 189 uncles, ancestors := mapset.NewSet(), make(map[common.Hash]*types.Header) 190 191 number, parent := block.NumberU64()-1, block.ParentHash() 192 for i := 0; i < 7; i++ { 193 ancestor := chain.GetBlock(parent, number) 194 if ancestor == nil { 195 break 196 } 197 ancestors[ancestor.Hash()] = ancestor.Header() 198 for _, uncle := range ancestor.Uncles() { 199 uncles.Add(uncle.Hash()) 200 } 201 parent, number = ancestor.ParentHash(), number-1 202 } 203 ancestors[block.Hash()] = block.Header() 204 uncles.Add(block.Hash()) 205 206 // Verify each of the uncles that it's recent, but not an ancestor 207 for _, uncle := range block.Uncles() { 208 // Make sure every uncle is rewarded only once 209 hash := uncle.Hash() 210 if uncles.Contains(hash) { 211 return errDuplicateUncle 212 } 213 uncles.Add(hash) 214 215 // Make sure the uncle has a valid ancestry 216 if ancestors[hash] != nil { 217 return errUncleIsAncestor 218 } 219 if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() { 220 return errDanglingUncle 221 } 222 if err := ethash.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, true); err != nil { 223 return err 224 } 225 } 226 return nil 227 } 228 229 // verifyHeader checks whether a header conforms to the consensus rules of the 230 // stock Ethereum ethash engine. 231 // See YP section 4.3.4. "Block Header Validity" 232 func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error { 233 // Ensure that the header's extra-data section is of a reasonable size 234 if uint64(len(header.Extra)) > params.MaximumExtraDataSize { 235 return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize) 236 } 237 // Verify the header's timestamp 238 if uncle { 239 if header.Time.Cmp(math.MaxBig256) > 0 { 240 return errLargeBlockTime 241 } 242 } else { 243 if header.Time.Cmp(big.NewInt(time.Now().Add(allowedFutureBlockTime).Unix())) > 0 { 244 return consensus.ErrFutureBlock 245 } 246 } 247 if header.Time.Cmp(parent.Time) <= 0 { 248 return errZeroBlockTime 249 } 250 // Verify the block's difficulty based in it's timestamp and parent's difficulty 251 expected := ethash.CalcDifficulty(chain, header.Time.Uint64(), parent) 252 253 if expected.Cmp(header.Difficulty) != 0 { 254 return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected) 255 } 256 // Verify that the gas limit is <= 2^63-1 257 cap := uint64(0x7fffffffffffffff) 258 if header.GasLimit > cap { 259 return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap) 260 } 261 // Verify that the gasUsed is <= gasLimit 262 if header.GasUsed > header.GasLimit { 263 return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) 264 } 265 266 // Verify that the gas limit remains within allowed bounds 267 diff := int64(parent.GasLimit) - int64(header.GasLimit) 268 if diff < 0 { 269 diff *= -1 270 } 271 limit := parent.GasLimit / params.GasLimitBoundDivisor 272 273 if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit { 274 return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit) 275 } 276 // Verify that the block number is parent's +1 277 if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 { 278 return consensus.ErrInvalidNumber 279 } 280 // Verify the engine specific seal securing the block 281 if seal { 282 if err := ethash.VerifySeal(chain, header); err != nil { 283 return err 284 } 285 } 286 // If all checks passed, validate any special fields for hard forks 287 if err := misc.VerifyDAOHeaderExtraData(chain.Config(), header); err != nil { 288 return err 289 } 290 if err := misc.VerifyForkHashes(chain.Config(), header, uncle); err != nil { 291 return err 292 } 293 return nil 294 } 295 296 // CalcDifficulty is the difficulty adjustment algorithm. It returns 297 // the difficulty that a new block should have when created at time 298 // given the parent block's time and difficulty. 299 func (ethash *Ethash) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { 300 return CalcDifficulty(chain.Config(), time, parent) 301 } 302 303 // CalcDifficulty is the difficulty adjustment algorithm. It returns 304 // the difficulty that a new block should have when created at time 305 // given the parent block's time and difficulty. 306 func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int { 307 next := new(big.Int).Add(parent.Number, big1) 308 switch { 309 case config.IsByzantium(next): 310 return calcDifficultyByzantium(time, parent) 311 default: 312 // still use Byzantium's algorithm, but log an warning 313 log.Warn("CalcDifficulty found unknown release version in ChainConfig") 314 return calcDifficultyByzantium(time, parent) 315 } 316 } 317 318 // Some weird constants to avoid constant memory allocs for them. 319 var ( 320 big1 = big.NewInt(1) 321 big3 = big.NewInt(3) 322 big4 = big.NewInt(4) 323 big9 = big.NewInt(9) 324 bigMinus99 = big.NewInt(-99) 325 ) 326 327 // calcDifficultyByzantium is the difficulty adjustment algorithm. It returns 328 // the difficulty that a new block should have when created at time given the 329 // parent block's time and difficulty. The calculation uses the Byzantium rules. 330 func calcDifficultyByzantium(time uint64, parent *types.Header) *big.Int { 331 // The goal of this difficulty calculation is to stabilize the 332 // average block time even as hash power is added or removed from 333 // the network. Let T be the time between the new block and 334 // previous block. If T is short enough, we assume this indicates 335 // hashing power was added, so we increase the difficulty to make 336 // blocks take longer. If T is already close to our desired 337 // average block time, we leave the difficulty unchanged. If T is 338 // too long, then hashing power might have been removed, so we 339 // decrease the difficulty to get back to the desired average 340 // block time. 341 // 342 // Ethereum targets a ~14 second block time, while Marconi targets 343 // a ~32 second block time. Here's how the difficulty changes for 344 // Marconi: 345 // 346 // If block time is: then difficulty change is: 347 // 0 to 8 sec ~0.15% increase 348 // 9 to 17 sec ~0.10% increase 349 // 18 to 26 sec ~0.05% increase 350 // 27 to 35 sec no change 351 // 36 to 44 sec ~0.05% decrease 352 // 45 to 53 sec ~0.10% decrease 353 // ... ... 354 // >= 918 sec ~5.00% decrease 355 // 356 // Except in the case of uncles. When an uncle is present in the 357 // parent block, we shift the above buckets by 1 position so that 358 // it's more likely that the difficulty will increase. See 359 // https://gitlab.neji.vm.tc/marconi/EIPs/issues/100 for why the formula 360 // takes uncles into account. 361 // 362 // If we ignore uncles and the cap on decrease amount, the 363 // simplified mathematical formula is: 364 // 365 // difficulty = parent_difficulty + (3 - T/9) * parent_difficulty / 2048 366 // 367 // The full formula is: 368 // 369 // difficulty = parent_difficulty + 370 // max(-99, (4 if uncles else 3) - T/9) * parent_difficulty / 2048 371 372 bigTime := new(big.Int).SetUint64(time) 373 bigParentTime := new(big.Int).Set(parent.Time) 374 375 // Holders for intermediate values. 376 x := new(big.Int) 377 y := new(big.Int) 378 379 // T/9 380 x.Sub(bigTime, bigParentTime) 381 x.Div(x, big9) 382 // (4 if uncles else 3) - T/9 383 if parent.UncleHash == types.EmptyUncleHash { 384 x.Sub(big3, x) 385 } else { 386 x.Sub(big4, x) 387 } 388 // max(-99, (4 if uncles else 3) - T/9) 389 if x.Cmp(bigMinus99) < 0 { 390 x.Set(bigMinus99) 391 } 392 // parent_difficulty + max(-99, (4 if uncles else 3) - T/9) * parent_difficulty / 2048 393 y.Div(parent.Difficulty, params.DifficultyBoundDivisor) 394 x.Mul(y, x) 395 x.Add(parent.Difficulty, x) 396 397 // Minimum the difficulty can ever be. 398 if x.Cmp(params.MinimumDifficulty) < 0 { 399 x.Set(params.MinimumDifficulty) 400 } 401 402 // TODO: determine if we need to have ice age logic which 403 // exponentially jacks up the difficulty after a certain number of 404 // blocks. Ice age is used in Ethereum to encourage users to 405 // moving to new hard forks. Adding the logic is simple, however 406 // it might be more preferable to incentivize upgrades in other 407 // ways. 408 409 return x 410 } 411 412 // VerifySeal implements consensus.Engine, checking whether the given block satisfies 413 // the PoW difficulty requirements. 414 func (ethash *Ethash) VerifySeal(chain consensus.ChainReader, header *types.Header) error { 415 return ethash.verifySeal(chain, header, false) 416 } 417 418 // verifySeal checks whether a block satisfies the PoW difficulty requirements, 419 // either using the usual ethash cache for it, or alternatively using a full DAG 420 // to make remote mining fast. 421 func (ethash *Ethash) verifySeal(chain consensus.ChainReader, header *types.Header, fulldag bool) error { 422 // If we're running a fake PoW, accept any seal as valid 423 if ethash.config.PowMode == ModeFake || ethash.config.PowMode == ModeFullFake { 424 time.Sleep(ethash.fakeDelay) 425 if ethash.fakeFail == header.Number.Uint64() { 426 return errInvalidPoW 427 } 428 return nil 429 } 430 // If we're running a shared PoW, delegate verification to it 431 if ethash.shared != nil { 432 return ethash.shared.verifySeal(chain, header, fulldag) 433 } 434 // Ensure that we have a valid difficulty for the block 435 if header.Difficulty.Sign() <= 0 { 436 return errInvalidDifficulty 437 } 438 // Recompute the digest and PoW value and verify against the header 439 var digest []byte 440 var result []byte 441 if ethash.config.PowMode == ModeQuickTest { 442 digest, result = quickHash(ethash.SealHash(header).Bytes(), header.Nonce.Uint64()) 443 } else if ethash.config.PowMode == ModeCryptonight { 444 digest, result = cryptonight.HashVariant4ForEthereumHeader( 445 ethash.SealHash(header).Bytes(), header.Nonce.Uint64(), header.Number.Uint64()) 446 } else { 447 number := header.Number.Uint64() 448 449 // If fast-but-heavy PoW verification was requested, use an ethash dataset 450 if fulldag { 451 dataset := ethash.dataset(number, true) 452 if dataset.generated() { 453 digest, result = hashimotoFull(dataset.dataset, ethash.SealHash(header).Bytes(), header.Nonce.Uint64()) 454 455 // Datasets are unmapped in a finalizer. Ensure that the dataset stays alive 456 // until after the call to hashimotoFull so it's not unmapped while being used. 457 runtime.KeepAlive(dataset) 458 } else { 459 // Dataset not yet generated, don't hang, use a cache instead 460 fulldag = false 461 } 462 } 463 // If slow-but-light PoW verification was requested (or DAG not yet ready), use an ethash cache 464 if !fulldag { 465 cache := ethash.cache(number) 466 size := datasetSize(number) 467 if ethash.config.PowMode == ModeTest { 468 size = 32 * 1024 469 } 470 digest, result = hashimotoLight(size, cache.cache, ethash.SealHash(header).Bytes(), header.Nonce.Uint64()) 471 472 // Caches are unmapped in a finalizer. Ensure that the cache stays alive 473 // until after the call to hashimotoLight so it's not unmapped while being used. 474 runtime.KeepAlive(cache) 475 } 476 } 477 // Verify the calculated values against the ones provided in the header 478 if !bytes.Equal(header.MixDigest[:], digest) { 479 return errInvalidMixDigest 480 } 481 target := new(big.Int).Div(two256, header.Difficulty) 482 if new(big.Int).SetBytes(result).Cmp(target) > 0 { 483 return errInvalidPoW 484 } 485 return nil 486 } 487 488 // Prepare implements consensus.Engine, initializing the difficulty field of a 489 // header to conform to the ethash protocol. The changes are done inline. 490 func (ethash *Ethash) Prepare(chain consensus.ChainReader, header *types.Header) error { 491 parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) 492 if parent == nil { 493 return consensus.ErrUnknownAncestor 494 } 495 header.Difficulty = ethash.CalcDifficulty(chain, header.Time.Uint64(), parent) 496 return nil 497 } 498 499 // Finalize implements consensus.Engine, accumulating the block and uncle rewards, 500 // setting the final state and assembling the block. 501 func (ethash *Ethash) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { 502 // Accumulate any block and uncle rewards and commit the final state root 503 accumulateRewards(chain.Config(), state, header, uncles) 504 header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) 505 506 // Header seems complete, assemble into a block and return 507 return types.NewBlock(header, txs, uncles, receipts), nil 508 } 509 510 // SealHash returns the hash of a block prior to it being sealed. 511 func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) { 512 hasher := sha3.NewLegacyKeccak256() 513 514 rlp.Encode(hasher, []interface{}{ 515 header.ParentHash, 516 header.UncleHash, 517 header.Coinbase, 518 header.Root, 519 header.TxHash, 520 header.ReceiptHash, 521 header.Bloom, 522 header.Difficulty, 523 header.Number, 524 header.GasLimit, 525 header.GasUsed, 526 header.Time, 527 header.Extra, 528 }) 529 hasher.Sum(hash[:0]) 530 return hash 531 } 532 533 // Some weird constants to avoid constant memory allocs for them. 534 var ( 535 big8 = big.NewInt(8) 536 big32 = big.NewInt(32) 537 ) 538 539 // AccumulateRewards credits the coinbase of the given block with the mining 540 // reward. The total reward consists of the static block reward and rewards for 541 // included uncles. The coinbase of each uncle block is also rewarded. 542 func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) { 543 // Select the correct block reward based on chain progression 544 blockReward := SoftLaunchBlockReward 545 if config.IsMIP5(header.Number) { 546 blockReward = DefaultBlockReward 547 } else if config.IsMIP4(header.Number) { 548 blockReward = MIP4BlockReward 549 } else if config.IsMIP3(header.Number) { 550 blockReward = MIP3BlockReward 551 } else if config.IsMIP2(header.Number) { 552 blockReward = MIP2BlockReward 553 } else if config.IsMIP1(header.Number) { 554 blockReward = MIP1BlockReward 555 } 556 557 // Accumulate the rewards for the miner and any included uncles 558 reward := new(big.Int).Set(blockReward) 559 r := new(big.Int) 560 for _, uncle := range uncles { 561 r.Add(uncle.Number, big8) 562 r.Sub(r, header.Number) 563 r.Mul(r, blockReward) 564 r.Div(r, big8) 565 // TODO pending Token Economy research, if we want to reduce rewards of uncle blocks, the calculations for 'r' needs to be updated 566 state.AddBalance(uncle.Coinbase, r) 567 568 r.Div(blockReward, big32) 569 reward.Add(reward, r) 570 } 571 572 state.AddBalance(header.Coinbase, reward) 573 }