github.com/Aodurkeen/go-ubiq@v2.3.0+incompatible/consensus/ubqhash/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 ubqhash 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/ubiq/go-ubiq/common" 29 "github.com/ubiq/go-ubiq/consensus" 30 "github.com/ubiq/go-ubiq/consensus/misc" 31 "github.com/ubiq/go-ubiq/core/state" 32 "github.com/ubiq/go-ubiq/core/types" 33 "github.com/ubiq/go-ubiq/log" 34 "github.com/ubiq/go-ubiq/params" 35 "github.com/ubiq/go-ubiq/rlp" 36 "golang.org/x/crypto/sha3" 37 ) 38 39 // Ubqhash proof-of-work protocol constants. 40 var ( 41 blockReward *big.Int = big.NewInt(8e+18) // Block reward in wei for successfully mining a block 42 maxUncles = 2 // Maximum number of uncles allowed in a single block 43 allowedFutureBlockTime = 15 * time.Second // Max time from current time allowed for blocks, before they're considered future blocks 44 ) 45 46 // Diff algo constants. 47 var ( 48 big88 = big.NewInt(88) 49 bigMinus99 = big.NewInt(-99) 50 nPowAveragingWindow = big.NewInt(21) 51 nPowMaxAdjustDown = big.NewInt(16) // 16% adjustment down 52 nPowMaxAdjustUp = big.NewInt(8) // 8% adjustment up 53 54 diffChangeBlock = big.NewInt(4088) 55 nPowAveragingWindow88 = big.NewInt(88) 56 nPowMaxAdjustDown2 = big.NewInt(3) // 3% adjustment down 57 nPowMaxAdjustUp2 = big.NewInt(2) // 2% adjustment up 58 59 // Flux 60 fluxChangeBlock = big.NewInt(8000) 61 nPowMaxAdjustDownFlux = big.NewInt(5) // 0.5% adjustment down 62 nPowMaxAdjustUpFlux = big.NewInt(3) // 0.3% adjustment up 63 nPowDampFlux = big.NewInt(1) // 0.1% 64 ) 65 66 // Various error messages to mark blocks invalid. These should be private to 67 // prevent engine specific errors from being referenced in the remainder of the 68 // codebase, inherently breaking if the engine is swapped out. Please put common 69 // error types into the consensus package. 70 var ( 71 errLargeBlockTime = errors.New("timestamp too big") 72 errZeroBlockTime = errors.New("timestamp equals parent's") 73 errTooManyUncles = errors.New("too many uncles") 74 errDuplicateUncle = errors.New("duplicate uncle") 75 errUncleIsAncestor = errors.New("uncle is ancestor") 76 errDanglingUncle = errors.New("uncle's parent is not ancestor") 77 errNonceOutOfRange = errors.New("nonce out of range") 78 errInvalidDifficulty = errors.New("non-positive difficulty") 79 errInvalidMixDigest = errors.New("invalid mix digest") 80 errInvalidPoW = errors.New("invalid proof-of-work") 81 ) 82 83 // Author implements consensus.Engine, returning the header's coinbase as the 84 // proof-of-work verified author of the block. 85 func (ubqhash *Ubqhash) Author(header *types.Header) (common.Address, error) { 86 return header.Coinbase, nil 87 } 88 89 // VerifyHeader checks whether a header conforms to the consensus rules of the 90 // stock Ethereum ubqhash engine. 91 func (ubqhash *Ubqhash) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { 92 // If we're running a full engine faking, accept any input as valid 93 if ubqhash.config.PowMode == ModeFullFake { 94 return nil 95 } 96 // Short circuit if the header is known, or it's parent not 97 number := header.Number.Uint64() 98 if chain.GetHeader(header.Hash(), number) != nil { 99 return nil 100 } 101 parent := chain.GetHeader(header.ParentHash, number-1) 102 if parent == nil { 103 return consensus.ErrUnknownAncestor 104 } 105 // Sanity checks passed, do a proper verification 106 return ubqhash.verifyHeader(chain, header, parent, false, seal) 107 } 108 109 // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers 110 // concurrently. The method returns a quit channel to abort the operations and 111 // a results channel to retrieve the async verifications. 112 func (ubqhash *Ubqhash) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { 113 // If we're running a full engine faking, accept any input as valid 114 if ubqhash.config.PowMode == ModeFullFake || len(headers) == 0 { 115 abort, results := make(chan struct{}), make(chan error, len(headers)) 116 for i := 0; i < len(headers); i++ { 117 results <- nil 118 } 119 return abort, results 120 } 121 122 // Spawn as many workers as allowed threads 123 workers := runtime.GOMAXPROCS(0) 124 if len(headers) < workers { 125 workers = len(headers) 126 } 127 128 // Create a task channel and spawn the verifiers 129 var ( 130 inputs = make(chan int) 131 done = make(chan int, workers) 132 errors = make([]error, len(headers)) 133 abort = make(chan struct{}) 134 ) 135 for i := 0; i < workers; i++ { 136 go func() { 137 for index := range inputs { 138 errors[index] = ubqhash.verifyHeaderWorker(chain, headers, seals, index) 139 done <- index 140 } 141 }() 142 } 143 144 errorsOut := make(chan error, len(headers)) 145 go func() { 146 defer close(inputs) 147 var ( 148 in, out = 0, 0 149 checked = make([]bool, len(headers)) 150 inputs = inputs 151 ) 152 for { 153 select { 154 case inputs <- in: 155 if in++; in == len(headers) { 156 // Reached end of headers. Stop sending to workers. 157 inputs = nil 158 } 159 case index := <-done: 160 for checked[index] = true; checked[out]; out++ { 161 errorsOut <- errors[out] 162 if out == len(headers)-1 { 163 return 164 } 165 } 166 case <-abort: 167 return 168 } 169 } 170 }() 171 return abort, errorsOut 172 } 173 174 func (ubqhash *Ubqhash) verifyHeaderWorker(chain consensus.ChainReader, headers []*types.Header, seals []bool, index int) error { 175 var parent *types.Header 176 if index == 0 { 177 parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1) 178 } else if headers[index-1].Hash() == headers[index].ParentHash { 179 parent = headers[index-1] 180 } 181 if parent == nil { 182 return consensus.ErrUnknownAncestor 183 } 184 if chain.GetHeader(headers[index].Hash(), headers[index].Number.Uint64()) != nil { 185 return nil // known block 186 } 187 return ubqhash.verifyHeader(chain, headers[index], parent, false, seals[index]) 188 } 189 190 // VerifyUncles verifies that the given block's uncles conform to the consensus 191 // rules of the stock Ethereum ubqhash engine. 192 func (ubqhash *Ubqhash) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { 193 // If we're running a full engine faking, accept any input as valid 194 if ubqhash.config.PowMode == ModeFullFake { 195 return nil 196 } 197 // Verify that there are at most 2 uncles included in this block 198 if len(block.Uncles()) > maxUncles { 199 return errTooManyUncles 200 } 201 // Gather the set of past uncles and ancestors 202 uncles, ancestors := mapset.NewSet(), make(map[common.Hash]*types.Header) 203 204 number, parent := block.NumberU64()-1, block.ParentHash() 205 for i := 0; i < 7; i++ { 206 ancestor := chain.GetBlock(parent, number) 207 if ancestor == nil { 208 break 209 } 210 ancestors[ancestor.Hash()] = ancestor.Header() 211 for _, uncle := range ancestor.Uncles() { 212 uncles.Add(uncle.Hash()) 213 } 214 parent, number = ancestor.ParentHash(), number-1 215 } 216 ancestors[block.Hash()] = block.Header() 217 uncles.Add(block.Hash()) 218 219 // Verify each of the uncles that it's recent, but not an ancestor 220 for _, uncle := range block.Uncles() { 221 // Make sure every uncle is rewarded only once 222 hash := uncle.Hash() 223 if uncles.Contains(hash) { 224 return errDuplicateUncle 225 } 226 uncles.Add(hash) 227 228 // Make sure the uncle has a valid ancestry 229 if ancestors[hash] != nil { 230 return errUncleIsAncestor 231 } 232 if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() { 233 return errDanglingUncle 234 } 235 if err := ubqhash.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, true); err != nil { 236 return err 237 } 238 } 239 return nil 240 } 241 242 // verifyHeader checks whether a header conforms to the consensus rules of the 243 // stock Ethereum ubqhash engine. 244 // See YP section 4.3.4. "Block Header Validity" 245 func (ubqhash *Ubqhash) verifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error { 246 // Ensure that the header's extra-data section is of a reasonable size 247 if uint64(len(header.Extra)) > params.MaximumExtraDataSize { 248 return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize) 249 } 250 // Verify the header's timestamp 251 if !uncle { 252 if header.Time > uint64(time.Now().Add(allowedFutureBlockTime).Unix()) { 253 return consensus.ErrFutureBlock 254 } 255 } 256 if header.Time <= parent.Time { 257 return errZeroBlockTime 258 } 259 // Verify the block's difficulty based in it's timestamp and parent's difficulty 260 expected := ubqhash.CalcDifficulty(chain, header.Time, parent) 261 262 if expected.Cmp(header.Difficulty) != 0 { 263 return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected) 264 } 265 // Verify that the gas limit is <= 2^63-1 266 cap := uint64(0x7fffffffffffffff) 267 if header.GasLimit > cap { 268 return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap) 269 } 270 // Verify that the gasUsed is <= gasLimit 271 if header.GasUsed > header.GasLimit { 272 return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) 273 } 274 275 // Verify that the gas limit remains within allowed bounds 276 diff := int64(parent.GasLimit) - int64(header.GasLimit) 277 if diff < 0 { 278 diff *= -1 279 } 280 limit := parent.GasLimit / params.GasLimitBoundDivisor 281 282 if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit { 283 return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit) 284 } 285 // Verify that the block number is parent's +1 286 if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 { 287 return consensus.ErrInvalidNumber 288 } 289 // Verify the engine specific seal securing the block 290 if seal { 291 if err := ubqhash.VerifySeal(chain, header); err != nil { 292 return err 293 } 294 } 295 // If all checks passed, validate any special fields for hard forks 296 if err := misc.VerifyForkHashes(chain.Config(), header, uncle); err != nil { 297 return err 298 } 299 return nil 300 } 301 302 // Difficulty timespans 303 func averagingWindowTimespan() *big.Int { 304 x := new(big.Int) 305 return x.Mul(nPowAveragingWindow, big88) 306 } 307 308 func minActualTimespan() *big.Int { 309 x := new(big.Int) 310 y := new(big.Int) 311 z := new(big.Int) 312 x.Sub(big.NewInt(100), nPowMaxAdjustUp) 313 y.Mul(averagingWindowTimespan(), x) 314 z.Div(y, big.NewInt(100)) 315 return z 316 } 317 318 func maxActualTimespan() *big.Int { 319 x := new(big.Int) 320 y := new(big.Int) 321 z := new(big.Int) 322 x.Add(big.NewInt(100), nPowMaxAdjustDown) 323 y.Mul(averagingWindowTimespan(), x) 324 z.Div(y, big.NewInt(100)) 325 return z 326 } 327 328 func averagingWindowTimespan88() *big.Int { 329 x := new(big.Int) 330 return x.Mul(nPowAveragingWindow88, big88) 331 } 332 333 func minActualTimespan2() *big.Int { 334 x := new(big.Int) 335 y := new(big.Int) 336 z := new(big.Int) 337 x.Sub(big.NewInt(100), nPowMaxAdjustUp2) 338 y.Mul(averagingWindowTimespan88(), x) 339 z.Div(y, big.NewInt(100)) 340 return z 341 } 342 343 func maxActualTimespan2() *big.Int { 344 x := new(big.Int) 345 y := new(big.Int) 346 z := new(big.Int) 347 x.Add(big.NewInt(100), nPowMaxAdjustDown2) 348 y.Mul(averagingWindowTimespan88(), x) 349 z.Div(y, big.NewInt(100)) 350 return z 351 } 352 353 func minActualTimespanFlux(dampen bool) *big.Int { 354 x := new(big.Int) 355 y := new(big.Int) 356 z := new(big.Int) 357 if dampen { 358 x.Sub(big.NewInt(1000), nPowDampFlux) 359 y.Mul(averagingWindowTimespan88(), x) 360 z.Div(y, big.NewInt(1000)) 361 } else { 362 x.Sub(big.NewInt(1000), nPowMaxAdjustUpFlux) 363 y.Mul(averagingWindowTimespan88(), x) 364 z.Div(y, big.NewInt(1000)) 365 } 366 return z 367 } 368 369 func maxActualTimespanFlux(dampen bool) *big.Int { 370 x := new(big.Int) 371 y := new(big.Int) 372 z := new(big.Int) 373 if dampen { 374 x.Add(big.NewInt(1000), nPowDampFlux) 375 y.Mul(averagingWindowTimespan88(), x) 376 z.Div(y, big.NewInt(1000)) 377 } else { 378 x.Add(big.NewInt(1000), nPowMaxAdjustDownFlux) 379 y.Mul(averagingWindowTimespan88(), x) 380 z.Div(y, big.NewInt(1000)) 381 } 382 return z 383 } 384 385 // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty 386 // that a new block should have when created at time given the parent block's time 387 // and difficulty. 388 func (ubqhash *Ubqhash) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { 389 return CalcDifficulty(chain, time, parent) 390 } 391 392 func CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { 393 parentTime := parent.Time 394 parentNumber := parent.Number 395 parentDiff := parent.Difficulty 396 397 if parentNumber.Cmp(diffChangeBlock) < 0 { 398 return calcDifficultyOrig(chain, parentNumber, parentDiff, parent) 399 } 400 if parentNumber.Cmp(fluxChangeBlock) < 0 { 401 // (chain consensus.ChainReader, parentNumber, parentDiff *big.Int, parent *types.Header) 402 return calcDifficulty2(chain, parentNumber, parentDiff, parent) 403 } else { 404 // (chain consensus.ChainReader, time, parentTime, parentNumber, parentDiff *big.Int, parent *types.Header) 405 return fluxDifficulty(chain, big.NewInt(int64(time)), big.NewInt(int64(parentTime)), parentNumber, parentDiff, parent) 406 } 407 } 408 409 // Some weird constants to avoid constant memory allocs for them. 410 var ( 411 expDiffPeriod = big.NewInt(100000) 412 big10 = big.NewInt(10) 413 ) 414 415 // calcDifficultyLegacy is the difficulty adjustment algorithm. It returns 416 // the difficulty that a new block should have when created at time given the 417 // parent block's time and difficulty. The calculation uses the Legacy rules. 418 func CalcDifficultyLegacy(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int { 419 bigTime := new(big.Int).SetUint64(time) 420 bigParentTime := new(big.Int).SetUint64(parentTime) 421 422 // holds intermediate values to make the algo easier to read & audit 423 x := new(big.Int) 424 y := new(big.Int) 425 426 // 1 - (block_timestamp -parent_timestamp) // 10 427 x.Sub(bigTime, bigParentTime) 428 x.Div(x, big88) 429 x.Sub(common.Big1, x) 430 431 // max(1 - (block_timestamp - parent_timestamp) // 10, -99))) 432 if x.Cmp(bigMinus99) < 0 { 433 x.Set(bigMinus99) 434 } 435 // (parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99)) 436 y.Div(parentDiff, params.DifficultyBoundDivisor) 437 x.Mul(y, x) 438 x.Add(parentDiff, x) 439 440 // minimum difficulty can ever be (before exponential factor) 441 if x.Cmp(params.MinimumDifficulty) < 0 { 442 x.Set(params.MinimumDifficulty) 443 } 444 445 return x 446 } 447 448 // CalcDifficulty is the difficulty adjustment algorithm. It returns 449 // the difficulty that a new block should have when created at time 450 // given the parent block's time and difficulty. 451 // Rewritten to be based on Digibyte's Digishield v3 retargeting 452 func calcDifficultyOrig(chain consensus.ChainReader, parentNumber, parentDiff *big.Int, parent *types.Header) *big.Int { 453 // holds intermediate values to make the algo easier to read & audit 454 x := new(big.Int) 455 nFirstBlock := new(big.Int) 456 nFirstBlock.Sub(parentNumber, nPowAveragingWindow) 457 458 log.Debug(fmt.Sprintf("CalcDifficulty parentNumber: %v parentDiff: %v", parentNumber, parentDiff)) 459 460 // Check we have enough blocks 461 if parentNumber.Cmp(nPowAveragingWindow) < 1 { 462 log.Debug(fmt.Sprintf("CalcDifficulty: parentNumber(%+x) < nPowAveragingWindow(%+x)", parentNumber, nPowAveragingWindow)) 463 x.Set(parentDiff) 464 return x 465 } 466 467 // Limit adjustment step 468 // Use medians to prevent time-warp attacks 469 // nActualTimespan := nLastBlockTime - nFirstBlockTime 470 nLastBlockTime := chain.CalcPastMedianTime(parentNumber.Uint64(), parent) 471 nFirstBlockTime := chain.CalcPastMedianTime(nFirstBlock.Uint64(), parent) 472 nActualTimespan := new(big.Int) 473 nActualTimespan.Sub(nLastBlockTime, nFirstBlockTime) 474 log.Debug(fmt.Sprintf("CalcDifficulty nActualTimespan = %v before dampening", nActualTimespan)) 475 476 // nActualTimespan = AveragingWindowTimespan() + (nActualTimespan-AveragingWindowTimespan())/4 477 y := new(big.Int) 478 y.Sub(nActualTimespan, averagingWindowTimespan()) 479 y.Div(y, big.NewInt(4)) 480 nActualTimespan.Add(y, averagingWindowTimespan()) 481 log.Debug(fmt.Sprintf("CalcDifficulty nActualTimespan = %v before bounds", nActualTimespan)) 482 483 if nActualTimespan.Cmp(minActualTimespan()) < 0 { 484 nActualTimespan.Set(minActualTimespan()) 485 log.Debug("CalcDifficulty Minimum Timespan set") 486 } else if nActualTimespan.Cmp(maxActualTimespan()) > 0 { 487 nActualTimespan.Set(maxActualTimespan()) 488 log.Debug("CalcDifficulty Maximum Timespan set") 489 } 490 491 log.Debug(fmt.Sprintf("CalcDifficulty nActualTimespan = %v final\n", nActualTimespan)) 492 493 // Retarget 494 x.Mul(parentDiff, averagingWindowTimespan()) 495 log.Debug(fmt.Sprintf("CalcDifficulty parentDiff * AveragingWindowTimespan: %v", x)) 496 497 x.Div(x, nActualTimespan) 498 log.Debug(fmt.Sprintf("CalcDifficulty x / nActualTimespan: %v", x)) 499 500 return x 501 } 502 503 func calcDifficulty2(chain consensus.ChainReader, parentNumber, parentDiff *big.Int, parent *types.Header) *big.Int { 504 x := new(big.Int) 505 nFirstBlock := new(big.Int) 506 nFirstBlock.Sub(parentNumber, nPowAveragingWindow88) 507 508 nLastBlockTime := chain.CalcPastMedianTime(parentNumber.Uint64(), parent) 509 nFirstBlockTime := chain.CalcPastMedianTime(nFirstBlock.Uint64(), parent) 510 511 nActualTimespan := new(big.Int) 512 nActualTimespan.Sub(nLastBlockTime, nFirstBlockTime) 513 514 y := new(big.Int) 515 y.Sub(nActualTimespan, averagingWindowTimespan88()) 516 y.Div(y, big.NewInt(4)) 517 nActualTimespan.Add(y, averagingWindowTimespan88()) 518 519 if nActualTimespan.Cmp(minActualTimespan2()) < 0 { 520 nActualTimespan.Set(minActualTimespan2()) 521 } else if nActualTimespan.Cmp(maxActualTimespan2()) > 0 { 522 nActualTimespan.Set(maxActualTimespan2()) 523 } 524 525 x.Mul(parentDiff, averagingWindowTimespan88()) 526 x.Div(x, nActualTimespan) 527 528 if x.Cmp(params.MinimumDifficulty) < 0 { 529 x.Set(params.MinimumDifficulty) 530 } 531 532 return x 533 } 534 535 func fluxDifficulty(chain consensus.ChainReader, time, parentTime, parentNumber, parentDiff *big.Int, parent *types.Header) *big.Int { 536 x := new(big.Int) 537 nFirstBlock := new(big.Int) 538 nFirstBlock.Sub(parentNumber, nPowAveragingWindow88) 539 540 diffTime := new(big.Int) 541 diffTime.Sub(time, parentTime) 542 543 nLastBlockTime := chain.CalcPastMedianTime(parentNumber.Uint64(), parent) 544 nFirstBlockTime := chain.CalcPastMedianTime(nFirstBlock.Uint64(), parent) 545 nActualTimespan := new(big.Int) 546 nActualTimespan.Sub(nLastBlockTime, nFirstBlockTime) 547 548 y := new(big.Int) 549 y.Sub(nActualTimespan, averagingWindowTimespan88()) 550 y.Div(y, big.NewInt(4)) 551 nActualTimespan.Add(y, averagingWindowTimespan88()) 552 553 if nActualTimespan.Cmp(minActualTimespanFlux(false)) < 0 { 554 doubleBig88 := new(big.Int) 555 doubleBig88.Mul(big88, big.NewInt(2)) 556 if diffTime.Cmp(doubleBig88) > 0 { 557 nActualTimespan.Set(minActualTimespanFlux(true)) 558 } else { 559 nActualTimespan.Set(minActualTimespanFlux(false)) 560 } 561 } else if nActualTimespan.Cmp(maxActualTimespanFlux(false)) > 0 { 562 halfBig88 := new(big.Int) 563 halfBig88.Div(big88, big.NewInt(2)) 564 if diffTime.Cmp(halfBig88) < 0 { 565 nActualTimespan.Set(maxActualTimespanFlux(true)) 566 } else { 567 nActualTimespan.Set(maxActualTimespanFlux(false)) 568 } 569 } 570 571 x.Mul(parentDiff, averagingWindowTimespan88()) 572 x.Div(x, nActualTimespan) 573 574 if x.Cmp(params.MinimumDifficulty) < 0 { 575 x.Set(params.MinimumDifficulty) 576 } 577 578 return x 579 } 580 581 // VerifySeal implements consensus.Engine, checking whether the given block satisfies 582 // the PoW difficulty requirements. 583 func (ubqhash *Ubqhash) VerifySeal(chain consensus.ChainReader, header *types.Header) error { 584 return ubqhash.verifySeal(chain, header, false) 585 } 586 587 // verifySeal checks whether a block satisfies the PoW difficulty requirements, 588 // either using the usual ethash cache for it, or alternatively using a full DAG 589 // to make remote mining fast. 590 func (ubqhash *Ubqhash) verifySeal(chain consensus.ChainReader, header *types.Header, fulldag bool) error { 591 // If we're running a fake PoW, accept any seal as valid 592 if ubqhash.config.PowMode == ModeFake || ubqhash.config.PowMode == ModeFullFake { 593 time.Sleep(ubqhash.fakeDelay) 594 if ubqhash.fakeFail == header.Number.Uint64() { 595 return errInvalidPoW 596 } 597 return nil 598 } 599 // If we're running a shared PoW, delegate verification to it 600 if ubqhash.shared != nil { 601 return ubqhash.shared.verifySeal(chain, header, fulldag) 602 } 603 // Ensure that we have a valid difficulty for the block 604 if header.Difficulty.Sign() <= 0 { 605 return errInvalidDifficulty 606 } 607 // Recompute the digest and PoW values 608 number := header.Number.Uint64() 609 610 var ( 611 digest []byte 612 result []byte 613 ) 614 // If fast-but-heavy PoW verification was requested, use an ethash dataset 615 if fulldag { 616 dataset := ubqhash.dataset(number, true) 617 if dataset.generated() { 618 digest, result = hashimotoFull(dataset.dataset, ubqhash.SealHash(header).Bytes(), header.Nonce.Uint64()) 619 620 // Datasets are unmapped in a finalizer. Ensure that the dataset stays alive 621 // until after the call to hashimotoFull so it's not unmapped while being used. 622 runtime.KeepAlive(dataset) 623 } else { 624 // Dataset not yet generated, don't hang, use a cache instead 625 fulldag = false 626 } 627 } 628 // If slow-but-light PoW verification was requested (or DAG not yet ready), use an ethash cache 629 if !fulldag { 630 cache := ubqhash.cache(number) 631 632 size := datasetSize(number) 633 if ubqhash.config.PowMode == ModeTest { 634 size = 32 * 1024 635 } 636 digest, result = hashimotoLight(size, cache.cache, ubqhash.SealHash(header).Bytes(), header.Nonce.Uint64()) 637 638 // Caches are unmapped in a finalizer. Ensure that the cache stays alive 639 // until after the call to hashimotoLight so it's not unmapped while being used. 640 runtime.KeepAlive(cache) 641 } 642 // Verify the calculated values against the ones provided in the header 643 if !bytes.Equal(header.MixDigest[:], digest) { 644 return errInvalidMixDigest 645 } 646 target := new(big.Int).Div(two256, header.Difficulty) 647 if new(big.Int).SetBytes(result).Cmp(target) > 0 { 648 return errInvalidPoW 649 } 650 return nil 651 } 652 653 // Prepare implements consensus.Engine, initializing the difficulty field of a 654 // header to conform to the ubqhash protocol. The changes are done inline. 655 func (ubqhash *Ubqhash) Prepare(chain consensus.ChainReader, header *types.Header) error { 656 parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) 657 if parent == nil { 658 return consensus.ErrUnknownAncestor 659 } 660 header.Difficulty = CalcDifficulty(chain, header.Time, parent) 661 662 return nil 663 } 664 665 // Finalize implements consensus.Engine, accumulating the block and uncle rewards, 666 // setting the final state and assembling the block. 667 func (ubqhash *Ubqhash) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { 668 // Accumulate any block and uncle rewards and commit the final state root 669 accumulateRewards(state, header, uncles) 670 header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) 671 672 // Header seems complete, assemble into a block and return 673 return types.NewBlock(header, txs, uncles, receipts), nil 674 } 675 676 // Some weird constants to avoid constant memory allocs for them. 677 var ( 678 big2 = big.NewInt(2) 679 big8 = big.NewInt(8) 680 big32 = big.NewInt(32) 681 ) 682 683 // SealHash returns the hash of a block prior to it being sealed. 684 func (ubqhash *Ubqhash) SealHash(header *types.Header) (hash common.Hash) { 685 hasher := sha3.NewLegacyKeccak256() 686 687 rlp.Encode(hasher, []interface{}{ 688 header.ParentHash, 689 header.UncleHash, 690 header.Coinbase, 691 header.Root, 692 header.TxHash, 693 header.ReceiptHash, 694 header.Bloom, 695 header.Difficulty, 696 header.Number, 697 header.GasLimit, 698 header.GasUsed, 699 header.Time, 700 header.Extra, 701 }) 702 hasher.Sum(hash[:0]) 703 return hash 704 } 705 706 // AccumulateRewards credits the coinbase of the given block with the mining 707 // reward. The total reward consists of the static block reward and rewards for 708 // included uncles. The coinbase of each uncle block is also rewarded. 709 func accumulateRewards(state *state.StateDB, header *types.Header, uncles []*types.Header) { 710 reward := new(big.Int).Set(blockReward) 711 712 if header.Number.Cmp(big.NewInt(358363)) > 0 { 713 reward = big.NewInt(7e+18) 714 } 715 if header.Number.Cmp(big.NewInt(716727)) > 0 { 716 reward = big.NewInt(6e+18) 717 } 718 if header.Number.Cmp(big.NewInt(1075090)) > 0 { 719 reward = big.NewInt(5e+18) 720 } 721 if header.Number.Cmp(big.NewInt(1433454)) > 0 { 722 reward = big.NewInt(4e+18) 723 } 724 if header.Number.Cmp(big.NewInt(1791818)) > 0 { 725 reward = big.NewInt(3e+18) 726 } 727 if header.Number.Cmp(big.NewInt(2150181)) > 0 { 728 reward = big.NewInt(2e+18) 729 } 730 if header.Number.Cmp(big.NewInt(2508545)) > 0 { 731 reward = big.NewInt(1e+18) 732 } 733 734 r := new(big.Int) 735 for _, uncle := range uncles { 736 r.Add(uncle.Number, big2) 737 r.Sub(r, header.Number) 738 r.Mul(r, blockReward) 739 r.Div(r, big2) 740 741 if header.Number.Cmp(big.NewInt(10)) < 0 { 742 state.AddBalance(uncle.Coinbase, r) 743 r.Div(blockReward, big32) 744 if r.Cmp(big.NewInt(0)) < 0 { 745 r = big.NewInt(0) 746 } 747 } else { 748 if r.Cmp(big.NewInt(0)) < 0 { 749 r = big.NewInt(0) 750 } 751 state.AddBalance(uncle.Coinbase, r) 752 r.Div(blockReward, big32) 753 } 754 755 reward.Add(reward, r) 756 } 757 state.AddBalance(header.Coinbase, reward) 758 }