github.com/hhwill/poc-eth@v0.0.0-20240218063348-3bb107c90dbf/consensus/ethpoc/consensus.go (about) 1 package ethpoc 2 3 import ( 4 "errors" 5 "fmt" 6 "math/big" 7 "runtime" 8 "time" 9 10 "encoding/binary" 11 12 "github.com/ethereum/go-ethereum/common" 13 "github.com/ethereum/go-ethereum/common/math" 14 "github.com/ethereum/go-ethereum/consensus" 15 "github.com/ethereum/go-ethereum/consensus/misc" 16 "github.com/ethereum/go-ethereum/core/state" 17 "github.com/ethereum/go-ethereum/core/types" 18 "github.com/ethereum/go-ethereum/params" 19 "github.com/ethereum/go-ethereum/rlp" 20 "github.com/moonfruit/go-shabal" 21 "golang.org/x/crypto/sha3" 22 ) 23 24 // EthPoc proof-of-work protocol constants. 25 var ( 26 FrontierBlockReward = big.NewInt(5e+18) // Block reward in wei for successfully mining a block 27 ByzantiumBlockReward = big.NewInt(3e+18) // Block reward in wei for successfully mining a block upward from Byzantium 28 ConstantinopleBlockReward = big.NewInt(2e+18) // Block reward in wei for successfully mining a block upward from Constantinople 29 maxUncles = 2 // Maximum number of uncles allowed in a single block 30 allowedFutureBlockTime = 15 * time.Second // Max time from current time allowed for blocks, before they're considered future blocks 31 INITIAL_BASE_TARGET uint64 = 18325193796 32 MAX_BASE_TARGET uint64 = 18325193796 33 ADJUST_BLOCK_NUMBER uint64 = 2700 34 BLOCK_INTERVAL uint64 = 60 * 3 35 36 HASH_SIZE = 32 37 HASHES_PER_SCOOP = 2 38 SCOOP_SIZE = HASHES_PER_SCOOP * HASH_SIZE 39 SCOOPS_PER_PLOT = 4096 // original 1MB/plot = 16384 40 PLOT_SIZE = SCOOPS_PER_PLOT * SCOOP_SIZE 41 HASH_CAP = 4096 42 43 YEAR_TIME uint64 = 60 * 60 * 24 * 365 44 EACH_NUMBER_OF_4YEAR = 4 * YEAR_TIME / BLOCK_INTERVAL 45 46 // calcDifficultyConstantinople is the difficulty adjustment algorithm for Constantinople. 47 // It returns the difficulty that a new block should have when created at time given the 48 // parent block's time and difficulty. The calculation uses the Byzantium rules, but with 49 // bomb offset 5M. 50 // Specification EIP-1234: https://eips.ethereum.org/EIPS/eip-1234 51 calcDifficultyConstantinople = makeDifficultyCalculator(big.NewInt(5000000)) 52 53 // calcDifficultyByzantium is the difficulty adjustment algorithm. It returns 54 // the difficulty that a new block should have when created at time given the 55 // parent block's time and difficulty. The calculation uses the Byzantium rules. 56 // Specification EIP-649: https://eips.ethereum.org/EIPS/eip-649 57 calcDifficultyByzantium = makeDifficultyCalculator(big.NewInt(3000000)) 58 ) 59 60 // Various error messages to mark blocks invalid. These should be private to 61 // prevent engine specific errors from being referenced in the remainder of the 62 // codebase, inherently breaking if the engine is swapped out. Please put common 63 // error types into the consensus package. 64 var ( 65 errZeroBlockTime = errors.New("timestamp equals parent's") 66 errTooManyUncles = errors.New("too many uncles") 67 errDuplicateUncle = errors.New("duplicate uncle") 68 errUncleIsAncestor = errors.New("uncle is ancestor") 69 errDanglingUncle = errors.New("uncle's parent is not ancestor") 70 errInvalidDifficulty = errors.New("non-positive difficulty") 71 errInvalidMixDigest = errors.New("invalid mix digest") 72 errInvalidPoW = errors.New("invalid proof-of-work") 73 ) 74 75 // Author implements consensus.Engine, returning the header's coinbase as the 76 // proof-of-work verified author of the block. 77 func (ethPoc *EthPoc) Author(header *types.Header) (common.Address, error) { 78 return header.Coinbase, nil 79 } 80 81 // VerifyHeader checks whether a header conforms to the consensus rules of the 82 // stock Ethereum EthPoc engine. 83 func (ethPoc *EthPoc) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { 84 // If we're running a full engine faking, accept any input as valid 85 if ethPoc.config.PocMode == ModeFullFake { 86 return nil 87 } 88 // Short circuit if the header is known, or it's parent not 89 number := header.Number.Uint64() 90 if chain.GetHeader(header.Hash(), number) != nil { 91 return nil 92 } 93 parent := chain.GetHeader(header.ParentHash, number-1) 94 if parent == nil { 95 return consensus.ErrUnknownAncestor 96 } 97 // Sanity checks passed, do a proper verification 98 return ethPoc.verifyHeader(chain, header, parent, false, seal) 99 } 100 101 // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers 102 // concurrently. The method returns a quit channel to abort the operations and 103 // a results channel to retrieve the async verifications. 104 func (ethPoc *EthPoc) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { 105 // If we're running a full engine faking, accept any input as valid 106 if ethPoc.config.PocMode == ModeFullFake || len(headers) == 0 { 107 abort, results := make(chan struct{}), make(chan error, len(headers)) 108 for i := 0; i < len(headers); i++ { 109 results <- nil 110 } 111 return abort, results 112 } 113 114 // Spawn as many workers as allowed threads 115 workers := runtime.GOMAXPROCS(0) 116 if len(headers) < workers { 117 workers = len(headers) 118 } 119 120 // Create a task channel and spawn the verifiers 121 var ( 122 inputs = make(chan int) 123 done = make(chan int, workers) 124 errors = make([]error, len(headers)) 125 abort = make(chan struct{}) 126 ) 127 for i := 0; i < workers; i++ { 128 go func() { 129 for index := range inputs { 130 errors[index] = ethPoc.verifyHeaderWorker(chain, headers, seals, index) 131 done <- index 132 } 133 }() 134 } 135 136 errorsOut := make(chan error, len(headers)) 137 go func() { 138 defer close(inputs) 139 var ( 140 in, out = 0, 0 141 checked = make([]bool, len(headers)) 142 inputs = inputs 143 ) 144 for { 145 select { 146 case inputs <- in: 147 if in++; in == len(headers) { 148 // Reached end of headers. Stop sending to workers. 149 inputs = nil 150 } 151 case index := <-done: 152 for checked[index] = true; checked[out]; out++ { 153 errorsOut <- errors[out] 154 if out == len(headers)-1 { 155 return 156 } 157 } 158 case <-abort: 159 return 160 } 161 } 162 }() 163 return abort, errorsOut 164 } 165 166 func (ethPoc *EthPoc) verifyHeaderWorker(chain consensus.ChainReader, headers []*types.Header, seals []bool, index int) error { 167 var parent *types.Header 168 if index == 0 { 169 parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1) 170 } else if headers[index-1].Hash() == headers[index].ParentHash { 171 parent = headers[index-1] 172 } 173 if parent == nil { 174 return consensus.ErrUnknownAncestor 175 } 176 if chain.GetHeader(headers[index].Hash(), headers[index].Number.Uint64()) != nil { 177 return nil // known block 178 } 179 return ethPoc.verifyHeader(chain, headers[index], parent, false, seals[index]) 180 } 181 182 // VerifyUncles verifies that the given block's uncles conform to the consensus 183 // rules of the stock Ethereum EthPoc engine. 184 func (ethPoc *EthPoc) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { 185 186 if len(block.Uncles()) > 0 { 187 return errTooManyUncles 188 } 189 return nil 190 } 191 192 // verifyHeader checks whether a header conforms to the consensus rules of the 193 // stock Ethereum EthPoc engine. 194 // See YP section 4.3.4. "Block Header Validity" 195 func (ethPoc *EthPoc) verifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error { 196 // Ensure that the header's extra-data section is of a reasonable size 197 if uint64(len(header.Extra)) > params.MaximumExtraDataSize { 198 return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize) 199 } 200 // Verify the header's timestamp 201 if !uncle { 202 if header.Time > uint64(time.Now().Add(allowedFutureBlockTime).Unix()) { 203 return consensus.ErrFutureBlock 204 } 205 } 206 if header.Time <= parent.Time { 207 return errZeroBlockTime 208 } 209 // Verify the block's difficulty based in it's timestamp and parent's difficulty 210 expected := ethPoc.CalcDifficulty(chain, header.Time, parent) 211 212 if expected.Cmp(header.Difficulty) != 0 { 213 return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected) 214 } 215 // Verify that the gas limit is <= 2^63-1 216 cap := uint64(0x7fffffffffffffff) 217 if header.GasLimit > cap { 218 return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap) 219 } 220 // Verify that the gasUsed is <= gasLimit 221 if header.GasUsed > header.GasLimit { 222 return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) 223 } 224 225 // Verify that the gas limit remains within allowed bounds 226 diff := int64(parent.GasLimit) - int64(header.GasLimit) 227 if diff < 0 { 228 diff *= -1 229 } 230 limit := parent.GasLimit / params.GasLimitBoundDivisor 231 232 if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit { 233 return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit) 234 } 235 // Verify that the block number is parent's +1 236 if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 { 237 return consensus.ErrInvalidNumber 238 } 239 // Verify the engine specific seal securing the block 240 if seal { 241 if err := ethPoc.VerifySeal(chain, header); err != nil { 242 return err 243 } 244 } 245 // If all checks passed, validate any special fields for hard forks 246 if err := misc.VerifyDAOHeaderExtraData(chain.Config(), header); err != nil { 247 return err 248 } 249 if err := misc.VerifyForkHashes(chain.Config(), header, uncle); err != nil { 250 return err 251 } 252 return nil 253 } 254 255 // CalcDifficulty is the difficulty adjustment algorithm. It returns 256 // the difficulty that a new block should have when created at time 257 // given the parent block's time and difficulty. 258 func (ethPoc *EthPoc) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { 259 return CalcDifficulty(chain, chain.Config(), time, parent) 260 } 261 262 // CalcDifficulty is the difficulty adjustment algorithm. It returns 263 // the difficulty that a new block should have when created at time 264 // given the parent block's time and difficulty. 265 func CalcDifficulty(chain consensus.ChainReader, config *params.ChainConfig, time uint64, parent *types.Header) *big.Int { 266 next := new(big.Int).Add(parent.Number, big1) 267 switch { 268 case config.IsConstantinople(next): 269 return calcDifficultyConstantinople(time, parent) 270 case config.IsByzantium(next): 271 return calcDifficultyByzantium(time, parent) 272 case config.IsHomestead(next): 273 return calcDifficultyHomestead(time, parent) 274 default: 275 return calcBaseTarget(chain, time, parent) 276 } 277 } 278 279 // Some weird constants to avoid constant memory allocs for them. 280 var ( 281 expDiffPeriod = big.NewInt(100000) 282 big1 = big.NewInt(1) 283 big2 = big.NewInt(2) 284 big9 = big.NewInt(9) 285 big10 = big.NewInt(10) 286 bigMinus99 = big.NewInt(-99) 287 ) 288 289 // makeDifficultyCalculator creates a difficultyCalculator with the given bomb-delay. 290 // the difficulty is calculated with Byzantium rules, which differs from Homestead in 291 // how uncles affect the calculation 292 func makeDifficultyCalculator(bombDelay *big.Int) func(time uint64, parent *types.Header) *big.Int { 293 // Note, the calculations below looks at the parent number, which is 1 below 294 // the block number. Thus we remove one from the delay given 295 bombDelayFromParent := new(big.Int).Sub(bombDelay, big1) 296 return func(time uint64, parent *types.Header) *big.Int { 297 // https://github.com/ethereum/EIPs/issues/100. 298 // algorithm: 299 // diff = (parent_diff + 300 // (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) 301 // ) + 2^(periodCount - 2) 302 303 bigTime := new(big.Int).SetUint64(time) 304 bigParentTime := new(big.Int).SetUint64(parent.Time) 305 306 // holds intermediate values to make the algo easier to read & audit 307 x := new(big.Int) 308 y := new(big.Int) 309 310 // (2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9 311 x.Sub(bigTime, bigParentTime) 312 x.Div(x, big9) 313 if parent.UncleHash == types.EmptyUncleHash { 314 x.Sub(big1, x) 315 } else { 316 x.Sub(big2, x) 317 } 318 // max((2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9, -99) 319 if x.Cmp(bigMinus99) < 0 { 320 x.Set(bigMinus99) 321 } 322 // parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) 323 y.Div(parent.Difficulty, params.DifficultyBoundDivisor) 324 x.Mul(y, x) 325 x.Add(parent.Difficulty, x) 326 327 // minimum difficulty can ever be (before exponential factor) 328 if x.Cmp(params.MinimumDifficulty) < 0 { 329 x.Set(params.MinimumDifficulty) 330 } 331 // calculate a fake block number for the ice-age delay 332 // Specification: https://eips.ethereum.org/EIPS/eip-1234 333 fakeBlockNumber := new(big.Int) 334 if parent.Number.Cmp(bombDelayFromParent) >= 0 { 335 fakeBlockNumber = fakeBlockNumber.Sub(parent.Number, bombDelayFromParent) 336 } 337 // for the exponential factor 338 periodCount := fakeBlockNumber 339 periodCount.Div(periodCount, expDiffPeriod) 340 341 // the exponential factor, commonly referred to as "the bomb" 342 // diff = diff + 2^(periodCount - 2) 343 if periodCount.Cmp(big1) > 0 { 344 y.Sub(periodCount, big2) 345 y.Exp(big2, y, nil) 346 x.Add(x, y) 347 } 348 return x 349 } 350 } 351 352 // calcDifficultyHomestead is the difficulty adjustment algorithm. It returns 353 // the difficulty that a new block should have when created at time given the 354 // parent block's time and difficulty. The calculation uses the Homestead rules. 355 func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int { 356 // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md 357 // algorithm: 358 // diff = (parent_diff + 359 // (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99)) 360 // ) + 2^(periodCount - 2) 361 362 bigTime := new(big.Int).SetUint64(time) 363 bigParentTime := new(big.Int).SetUint64(parent.Time) 364 365 // holds intermediate values to make the algo easier to read & audit 366 x := new(big.Int) 367 y := new(big.Int) 368 369 // 1 - (block_timestamp - parent_timestamp) // 10 370 x.Sub(bigTime, bigParentTime) 371 x.Div(x, big10) 372 x.Sub(big1, x) 373 374 // max(1 - (block_timestamp - parent_timestamp) // 10, -99) 375 if x.Cmp(bigMinus99) < 0 { 376 x.Set(bigMinus99) 377 } 378 // (parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99)) 379 y.Div(parent.Difficulty, params.DifficultyBoundDivisor) 380 x.Mul(y, x) 381 x.Add(parent.Difficulty, x) 382 383 // minimum difficulty can ever be (before exponential factor) 384 if x.Cmp(params.MinimumDifficulty) < 0 { 385 x.Set(params.MinimumDifficulty) 386 } 387 // for the exponential factor 388 periodCount := new(big.Int).Add(parent.Number, big1) 389 periodCount.Div(periodCount, expDiffPeriod) 390 391 // the exponential factor, commonly referred to as "the bomb" 392 // diff = diff + 2^(periodCount - 2) 393 if periodCount.Cmp(big1) > 0 { 394 y.Sub(periodCount, big2) 395 y.Exp(big2, y, nil) 396 x.Add(x, y) 397 } 398 return x 399 } 400 401 // calcDifficultyFrontier is the difficulty adjustment algorithm. It returns the 402 // difficulty that a new block should have when created at time given the parent 403 // block's time and difficulty. The calculation uses the Frontier rules. 404 func calcDifficultyFrontier(time uint64, parent *types.Header) *big.Int { 405 diff := new(big.Int) 406 adjust := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor) 407 bigTime := new(big.Int) 408 bigParentTime := new(big.Int) 409 410 bigTime.SetUint64(time) 411 bigParentTime.SetUint64(parent.Time) 412 413 if bigTime.Sub(bigTime, bigParentTime).Cmp(params.DurationLimit) < 0 { 414 diff.Add(parent.Difficulty, adjust) 415 } else { 416 diff.Sub(parent.Difficulty, adjust) 417 } 418 if diff.Cmp(params.MinimumDifficulty) < 0 { 419 diff.Set(params.MinimumDifficulty) 420 } 421 422 periodCount := new(big.Int).Add(parent.Number, big1) 423 periodCount.Div(periodCount, expDiffPeriod) 424 if periodCount.Cmp(big1) > 0 { 425 // diff = diff + 2^(periodCount - 2) 426 expDiff := periodCount.Sub(periodCount, big2) 427 expDiff.Exp(big2, expDiff, nil) 428 diff.Add(diff, expDiff) 429 diff = math.BigMax(diff, params.MinimumDifficulty) 430 } 431 return diff 432 } 433 434 func calcBaseTarget(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { 435 number := parent.Number.Uint64() 436 if number < 4 { 437 return new(big.Int).SetUint64(INITIAL_BASE_TARGET) 438 } else if number < ADJUST_BLOCK_NUMBER { 439 avgBaseTaget := new(big.Int).Set(parent.Difficulty) 440 var header *types.Header 441 for i := 1; i < 4; i++ { 442 header = chain.GetHeaderByNumber(number - uint64(i)) 443 avgBaseTaget = new(big.Int).Add(avgBaseTaget, header.Difficulty) 444 } 445 avgBaseTaget = new(big.Int).Div(avgBaseTaget, big.NewInt(4)) 446 durTime := parent.Time - header.Time 447 newTarget := new(big.Int).Div(new(big.Int).Mul(avgBaseTaget, new(big.Int).SetUint64(durTime)), new(big.Int).SetUint64(BLOCK_INTERVAL*4)).Uint64() 448 hisTaget := avgBaseTaget.Uint64() 449 if newTarget > MAX_BASE_TARGET { 450 newTarget = MAX_BASE_TARGET 451 } 452 if newTarget < hisTaget*9/10 { 453 newTarget = hisTaget * 9 / 10 454 } 455 if newTarget == 0 { 456 newTarget = 1 457 } 458 459 if newTarget > hisTaget*11/10 { 460 newTarget = hisTaget * 11 / 10 461 } 462 if newTarget > MAX_BASE_TARGET { 463 newTarget = MAX_BASE_TARGET 464 } 465 fmt.Printf("New target diffculty %d\n", newTarget) 466 return new(big.Int).SetUint64(newTarget) 467 468 } else { 469 avgBaseTaget := new(big.Int).Set(parent.Difficulty) 470 var header *types.Header 471 for i := 1; i < 24; i++ { 472 header = chain.GetHeaderByNumber(number - uint64(i)) 473 avgBaseTaget = new(big.Int).Add(avgBaseTaget, header.Difficulty) 474 } 475 avgBaseTaget = new(big.Int).Div(avgBaseTaget, big.NewInt(24)) 476 durTime := parent.Time - header.Time 477 newTarget := new(big.Int).Div(new(big.Int).Mul(avgBaseTaget, new(big.Int).SetUint64(durTime)), new(big.Int).SetUint64(BLOCK_INTERVAL*24)).Uint64() 478 479 hisTaget := avgBaseTaget.Uint64() 480 if newTarget > MAX_BASE_TARGET { 481 newTarget = MAX_BASE_TARGET 482 } 483 484 if newTarget < hisTaget*8/10 { 485 newTarget = hisTaget * 8 / 10 486 } 487 if newTarget == 0 { 488 newTarget = 1 489 } 490 491 if newTarget > hisTaget*12/10 { 492 newTarget = hisTaget * 12 / 10 493 } 494 if newTarget > MAX_BASE_TARGET { 495 newTarget = MAX_BASE_TARGET 496 } 497 fmt.Printf("New target diffculty %d\n", newTarget) 498 return new(big.Int).SetUint64(newTarget) 499 } 500 501 } 502 503 // VerifySeal implements consensus.Engine, checking whether the given block satisfies 504 // the PoW difficulty requirements. 505 func (ethPoc *EthPoc) VerifySeal(chain consensus.ChainReader, header *types.Header) error { 506 number := header.Number.Uint64() 507 parent := chain.GetHeader(header.ParentHash, number-1) 508 if parent == nil { 509 return consensus.ErrUnknownAncestor 510 } 511 512 genSign := header.MixDigest.Bytes() 513 scoop := int(calculateScoop(genSign, number)) 514 deadLine := calculateDeadline(header.PlotterID, header.Nonce, scoop, genSign, header.Difficulty) 515 return ethPoc.verifySeal(chain, parent.Time, deadLine, header, false) 516 } 517 518 // verifySeal checks whether a block satisfies the PoW difficulty requirements, 519 // either using the usual EthPoc cache for it, or alternatively using a full DAG 520 // to make remote mining fast. 521 func (ethPoc *EthPoc) verifySeal(chain consensus.ChainReader, pTime uint64, deadLine *big.Int, header *types.Header, fulldag bool) error { 522 523 if header.Time > deadLine.Uint64()+pTime { 524 return nil 525 } 526 //return nil 527 528 //TODO:checkout nonce 529 return errors.New("DeadLine error") 530 } 531 532 func calculateDeadline(plotter uint64, nonce types.BlockNonce, scoop int, newGenSig []byte, baseTarget *big.Int) *big.Int { 533 hit := calculateHit(plotter, nonce, scoop, newGenSig) 534 return new(big.Int).Div(hit, baseTarget) 535 } 536 537 func calculateGenSign(lastGenSig []byte, lastGenId uint64) []byte { 538 baseBuf := make([]byte, HASH_SIZE+8) 539 copy(baseBuf[0:HASH_SIZE], lastGenSig) 540 binary.BigEndian.PutUint64(baseBuf[HASH_SIZE:HASH_SIZE+8], lastGenId) 541 542 sl := shabal.NewShabal256() 543 sl.Write(baseBuf) 544 return sl.Sum(nil) 545 } 546 547 func calculateScoop(genSig []byte, number uint64) int64 { 548 baseBuf := make([]byte, HASH_SIZE+8) 549 copy(baseBuf[0:HASH_SIZE], genSig) 550 binary.BigEndian.PutUint64(baseBuf[HASH_SIZE:], number) 551 552 sl := shabal.NewShabal256() 553 sl.Write(baseBuf) 554 hash := sl.Sum(nil) 555 556 return new(big.Int).Mod(new(big.Int).SetBytes(hash), big.NewInt(int64(SCOOPS_PER_PLOT))).Int64() 557 } 558 559 func calculateHit(plotter uint64, nonce types.BlockNonce, scoop int, newGenSig []byte) *big.Int { 560 data := miningPlot(plotter, nonce) 561 sl := shabal.NewShabal256() 562 sl.Write(newGenSig) 563 sl.Write(data[scoop*SCOOP_SIZE : scoop*SCOOP_SIZE+SCOOP_SIZE]) 564 hash := sl.Sum(nil) 565 566 b := make([]byte, 8) 567 for i := 0; i < 8; i++ { 568 copy(b[i:], hash[7-i:7-i+1]) 569 } 570 571 return new(big.Int).SetBytes(b) 572 } 573 574 func miningPlot(plotter uint64, nonce types.BlockNonce) []byte { 575 baseBuf := make([]byte, 16) 576 binary.BigEndian.PutUint64(baseBuf[0:8], plotter) 577 binary.BigEndian.PutUint64(baseBuf[8:16], nonce.Uint64()) 578 579 sl := shabal.NewShabal256() 580 581 plotBuf := make([]byte, PLOT_SIZE+len(baseBuf)) 582 copy(plotBuf[PLOT_SIZE:], baseBuf[0:]) 583 for i := PLOT_SIZE; i > 0; i -= HASH_SIZE { 584 index := PLOT_SIZE + len(baseBuf) - i 585 if index > HASH_CAP { 586 index = HASH_CAP 587 } 588 sl.Write(plotBuf[i : i+index]) 589 copy(plotBuf[i-HASH_SIZE:i], sl.Sum(nil)) 590 } 591 592 sl.Write(plotBuf) 593 finalHash := sl.Sum(nil) 594 595 data := make([]byte, PLOT_SIZE) 596 for i := 0; i < PLOT_SIZE; i++ { 597 data[i] = (byte)(plotBuf[i] ^ finalHash[i%HASH_SIZE]) 598 } 599 600 hashBuffer := make([]byte, HASH_SIZE) 601 revPos := PLOT_SIZE - HASH_SIZE 602 for pos := 32; pos < (PLOT_SIZE / 2); pos += 64 { 603 copy(hashBuffer, data[pos:pos+HASH_SIZE]) 604 copy(data[pos:pos+HASH_SIZE], data[revPos:revPos+HASH_SIZE]) 605 copy(data[revPos:revPos+HASH_SIZE], hashBuffer[0:HASH_SIZE]) 606 revPos -= 64 //move backwards 607 } 608 return data 609 } 610 611 // Prepare implements consensus.Engine, initializing the difficulty field of a 612 // header to conform to the EthPoc protocol. The changes are done inline. 613 func (ethPoc *EthPoc) Prepare(chain consensus.ChainReader, header *types.Header) error { 614 parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) 615 if parent == nil { 616 return consensus.ErrUnknownAncestor 617 } 618 619 hash := calculateGenSign(parent.MixDigest.Bytes(), header.PlotterID) 620 header.MixDigest = common.BytesToHash(hash) 621 header.Difficulty = ethPoc.CalcDifficulty(chain, header.Time, parent) 622 return nil 623 } 624 625 // Finalize implements consensus.Engine, accumulating the block and uncle rewards, 626 // setting the final state and assembling the block. 627 func (ethPoc *EthPoc) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { 628 // Accumulate any block and uncle rewards and commit the final state root 629 accumulateRewards(chain.Config(), state, header, uncles) 630 header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) 631 } 632 633 634 // Finalize implements consensus.Engine, accumulating the block and uncle rewards, 635 // setting the final state and assembling the block. 636 func (ethPoc *EthPoc) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { 637 // Accumulate any block and uncle rewards and commit the final state root 638 accumulateRewards(chain.Config(), state, header, uncles) 639 header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) 640 641 // Header seems complete, assemble into a block and return 642 return types.NewBlock(header, txs, uncles, receipts), nil 643 } 644 645 646 // SealHash returns the hash of a block prior to it being sealed. 647 func (ethPoc *EthPoc) SealHash(header *types.Header) (hash common.Hash) { 648 hasher := sha3.NewLegacyKeccak256() 649 650 rlp.Encode(hasher, []interface{}{ 651 header.ParentHash, 652 header.UncleHash, 653 header.Coinbase, 654 header.Root, 655 header.TxHash, 656 header.ReceiptHash, 657 header.Bloom, 658 header.Difficulty, 659 header.Number, 660 header.GasLimit, 661 header.GasUsed, 662 header.Extra, 663 }) 664 hasher.Sum(hash[:0]) 665 return hash 666 } 667 668 // Some weird constants to avoid constant memory allocs for them. 669 var ( 670 big8 = big.NewInt(8) 671 big32 = big.NewInt(32) 672 ) 673 674 // AccumulateRewards credits the coinbase of the given block with the mining 675 // reward. The total reward consists of the static block reward and rewards for 676 // included uncles. The coinbase of each uncle block is also rewarded. 677 func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) { 678 //TODO:change reward 679 if len(uncles) > 0 { 680 return 681 } 682 // Select the correct block reward based on chain progression 683 initReward := FrontierBlockReward 684 rewardYears := new(big.Int).Div(header.Number, new(big.Int).SetUint64(EACH_NUMBER_OF_4YEAR)) 685 686 if rewardYears.Uint64() > 33 { 687 return 688 } 689 blockReward := new(big.Int).Div(initReward, new(big.Int).Exp(big.NewInt(2), rewardYears, big.NewInt(0))) 690 state.AddBalance(header.Coinbase, blockReward) 691 }