github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/consensus/scrypt/consensus.go (about) 1 // Copyright (c) 2019 Simplechain 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Lesser General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Lesser General Public License for more details. 12 // 13 // You should have received a copy of the GNU Lesser General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package scrypt 17 18 import ( 19 "bytes" 20 "errors" 21 "fmt" 22 "math/big" 23 "runtime" 24 "time" 25 26 "github.com/bigzoro/my_simplechain/common" 27 "github.com/bigzoro/my_simplechain/consensus" 28 "github.com/bigzoro/my_simplechain/core/state" 29 "github.com/bigzoro/my_simplechain/core/types" 30 "github.com/bigzoro/my_simplechain/params" 31 "github.com/bigzoro/my_simplechain/rlp" 32 33 mapset "github.com/deckarep/golang-set" 34 "golang.org/x/crypto/sha3" 35 ) 36 37 // Scrypt proof-of-work protocol constants. 38 var ( 39 maxUncles = 2 // Maximum number of uncles allowed in a single block 40 allowedFutureBlockTime = 15 * time.Second // Max time from current time allowed for blocks, before they're considered future blocks 41 BlockReward *big.Int = new(big.Int).Mul(big.NewInt(1e+18), big.NewInt(20)) 42 BlockAttenuation *big.Int = big.NewInt(2500000) 43 big5 *big.Int = big.NewInt(5) 44 big100 *big.Int = big.NewInt(100) 45 ) 46 47 // Various error messages to mark blocks invalid. These should be private to 48 // prevent engine specific errors from being referenced in the remainder of the 49 // codebase, inherently breaking if the engine is swapped out. Please put common 50 // error types into the consensus package. 51 var ( 52 errZeroBlockTime = errors.New("timestamp equals parent's") 53 errTooManyUncles = errors.New("too many uncles") 54 errDuplicateUncle = errors.New("duplicate uncle") 55 errUncleIsAncestor = errors.New("uncle is ancestor") 56 errDanglingUncle = errors.New("uncle's parent is not ancestor") 57 errInvalidDifficulty = errors.New("non-positive difficulty") 58 errInvalidMixDigest = errors.New("invalid mix digest") 59 errInvalidPoW = errors.New("invalid proof-of-work") 60 ) 61 62 // Author implements consensus.Engine, returning the header's coinbase as the 63 // proof-of-work verified author of the block. 64 func (powScrypt *PowScrypt) Author(header *types.Header) (common.Address, error) { 65 return header.Coinbase, nil 66 } 67 68 // VerifyHeader checks whether a header conforms to the consensus rules of the 69 // stock Simplechain scrypt engine. 70 func (powScrypt *PowScrypt) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { 71 // If we're running a full engine faking, accept any input as valid 72 if powScrypt.config.PowMode == ModeFullFake { 73 return nil 74 } 75 // Short circuit if the header is known, or its parent not 76 number := header.Number.Uint64() 77 if chain.GetHeader(header.Hash(), number) != nil { 78 return nil 79 } 80 parent := chain.GetHeader(header.ParentHash, number-1) 81 if parent == nil { 82 return consensus.ErrUnknownAncestor 83 } 84 // Sanity checks passed, do a proper verification 85 return powScrypt.verifyHeader(chain, header, parent, false, seal) 86 } 87 88 // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers 89 // concurrently. The method returns a quit channel to abort the operations and 90 // a results channel to retrieve the async verifications. 91 func (powScrypt *PowScrypt) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { 92 // If we're running a full engine faking, accept any input as valid 93 if powScrypt.config.PowMode == ModeFullFake || len(headers) == 0 { 94 abort, results := make(chan struct{}), make(chan error, len(headers)) 95 for i := 0; i < len(headers); i++ { 96 results <- nil 97 } 98 return abort, results 99 } 100 // Spawn as many workers as allowed threads 101 workers := runtime.GOMAXPROCS(0) 102 if len(headers) < workers { 103 workers = len(headers) 104 } 105 106 // Create a task channel and spawn the verifiers 107 var ( 108 inputs = make(chan int) 109 done = make(chan int, workers) 110 errors = make([]error, len(headers)) 111 abort = make(chan struct{}) 112 ) 113 for i := 0; i < workers; i++ { 114 go func() { 115 for index := range inputs { 116 errors[index] = powScrypt.verifyHeaderWorker(chain, headers, seals, index) 117 done <- index 118 } 119 }() 120 } 121 122 errorsOut := make(chan error, len(headers)) 123 go func() { 124 defer close(inputs) 125 var ( 126 in, out = 0, 0 127 checked = make([]bool, len(headers)) 128 inputs = inputs 129 ) 130 for { 131 select { 132 case inputs <- in: 133 if in++; in == len(headers) { 134 // Reached end of headers. Stop sending to workers. 135 inputs = nil 136 } 137 case index := <-done: 138 for checked[index] = true; checked[out]; out++ { 139 errorsOut <- errors[out] 140 if out == len(headers)-1 { 141 return 142 } 143 } 144 case <-abort: 145 return 146 } 147 } 148 }() 149 return abort, errorsOut 150 } 151 152 func (powScrypt *PowScrypt) verifyHeaderWorker(chain consensus.ChainReader, headers []*types.Header, seals []bool, index int) error { 153 var parent *types.Header 154 if index == 0 { 155 parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1) 156 } else if headers[index-1].Hash() == headers[index].ParentHash { 157 parent = headers[index-1] 158 } 159 if parent == nil { 160 return consensus.ErrUnknownAncestor 161 } 162 if chain.GetHeader(headers[index].Hash(), headers[index].Number.Uint64()) != nil { 163 return nil // known block 164 } 165 return powScrypt.verifyHeader(chain, headers[index], parent, false, seals[index]) 166 } 167 168 // VerifyUncles verifies that the given block's uncles conform to the consensus 169 // rules of the stock SimpleChain scrypt engine. 170 func (powScrypt *PowScrypt) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { 171 // If we're running a full engine faking, accept any input as valid 172 if powScrypt.config.PowMode == ModeFullFake { 173 return nil 174 } 175 // Verify that there are at most 2 uncles included in this block 176 if len(block.Uncles()) > maxUncles { 177 return errTooManyUncles 178 } 179 if len(block.Uncles()) == 0 { 180 return nil 181 } 182 // Gather the set of past uncles and ancestors 183 uncles, ancestors := mapset.NewSet(), make(map[common.Hash]*types.Header) 184 185 number, parent := block.NumberU64()-1, block.ParentHash() 186 for i := 0; i < 7; i++ { 187 ancestor := chain.GetBlock(parent, number) 188 if ancestor == nil { 189 break 190 } 191 ancestors[ancestor.Hash()] = ancestor.Header() 192 for _, uncle := range ancestor.Uncles() { 193 uncles.Add(uncle.Hash()) 194 } 195 parent, number = ancestor.ParentHash(), number-1 196 } 197 ancestors[block.Hash()] = block.Header() 198 uncles.Add(block.Hash()) 199 200 // Verify each of the uncles that it's recent, but not an ancestor 201 for _, uncle := range block.Uncles() { 202 // Make sure every uncle is rewarded only once 203 hash := uncle.Hash() 204 if uncles.Contains(hash) { 205 return errDuplicateUncle 206 } 207 uncles.Add(hash) 208 209 // Make sure the uncle has a valid ancestry 210 if ancestors[hash] != nil { 211 return errUncleIsAncestor 212 } 213 if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() { 214 return errDanglingUncle 215 } 216 if err := powScrypt.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, true); err != nil { 217 return err 218 } 219 } 220 return nil 221 } 222 223 // verifyHeader checks whether a header conforms to the consensus rules of the 224 // stock Simplechain scrypt engine. 225 // See YP section 4.3.4. "Block Header Validity" 226 func (powScrypt *PowScrypt) verifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error { 227 // Ensure that the header's extra-data section is of a reasonable size 228 if uint64(len(header.Extra)) > params.MaximumExtraDataSize { 229 return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize) 230 } 231 // Verify the header's timestamp 232 if !uncle { 233 if header.Time > uint64(time.Now().Add(allowedFutureBlockTime).Unix()) { 234 return consensus.ErrFutureBlock 235 } 236 } 237 if header.Time <= parent.Time { 238 return errZeroBlockTime 239 } 240 // Verify the block's difficulty based in its timestamp and parent's difficulty 241 expected := powScrypt.CalcDifficulty(chain, header.Time, parent) 242 243 if expected.Cmp(header.Difficulty) != 0 { 244 return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected) 245 } 246 // Verify that the gas limit is <= 2^63-1 247 cap := uint64(0x7fffffffffffffff) 248 if header.GasLimit > cap { 249 return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap) 250 } 251 // Verify that the gasUsed is <= gasLimit 252 if header.GasUsed > header.GasLimit { 253 return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) 254 } 255 256 // Verify that the gas limit remains within allowed bounds 257 diff := int64(parent.GasLimit) - int64(header.GasLimit) 258 if diff < 0 { 259 diff *= -1 260 } 261 limit := parent.GasLimit / params.GasLimitBoundDivisor 262 263 if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit { 264 return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit) 265 } 266 // Verify that the block number is parent's +1 267 if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 { 268 return consensus.ErrInvalidNumber 269 } 270 // Verify the engine specific seal securing the block 271 if seal { 272 if err := powScrypt.VerifySeal(chain, header); err != nil { 273 return err 274 } 275 } 276 return nil 277 } 278 279 // CalcDifficulty is the difficulty adjustment algorithm. It returns 280 // the difficulty that a new block should have when created at time 281 // given the parent block's time and difficulty. 282 func (powScrypt *PowScrypt) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { 283 return CalcDifficulty(chain.Config(), time, parent) 284 } 285 286 // CalcDifficulty is the difficulty adjustment algorithm. It returns 287 // the difficulty that a new block should have when created at time 288 // given the parent block's time and difficulty. 289 func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int { 290 //TODO: handle forks 291 return calcDifficultySimpleChain(time, parent) 292 } 293 294 // Some weird constants to avoid constant memory allocs for them. 295 var ( 296 big1 = big.NewInt(1) 297 big2 = big.NewInt(2) 298 big3 = big.NewInt(3) 299 big5000 = big.NewInt(5000) 300 big900 = big.NewInt(900) 301 big1000 = big.NewInt(1000) 302 big100000 = big.NewInt(100000) 303 big100000000 = big.NewInt(100000000) 304 ) 305 306 func calcDifficultySimpleChain(time uint64, parent *types.Header) *big.Int { 307 // diff = 200000 308 // parent.UncleHash = 2 if len(parent.uncles) else 1 309 // diff = parent_diff 310 // + parent_diff * ( MIN ( timestamp - parent.timestamp , 900 ) ) ^ 2 * 3 / 100000000 311 // - parent_diff * ( MIN ( timestamp - parent.timestamp , 900 ) ) * 8 / 100000 312 // + parent_diff * parent.UncleHash / 1000 313 // diff = max ( diff , 5000 ) 314 315 x := big.NewInt(0) 316 yn := big.NewInt(0) 317 y1 := big.NewInt(0) 318 y2 := big.NewInt(0) 319 y3 := big.NewInt(0) 320 y_uncle := big.NewInt(0) 321 322 bigTime := new(big.Int).SetUint64(time) 323 324 if parent.UncleHash == types.EmptyUncleHash { 325 y_uncle.Set(big1) 326 } else { 327 y_uncle.Set(big2) 328 } 329 330 x.Sub(bigTime, new(big.Int).SetUint64(parent.Time)) 331 timeDiff := x 332 if timeDiff.Cmp(big900) > 0 { 333 timeDiff.Set(big900) 334 } 335 336 y1.Mul(timeDiff, timeDiff) 337 y1.Mul(y1, parent.Difficulty) 338 y1.Mul(y1, big3) 339 y1.Div(y1, big100000000) 340 341 y2.Mul(parent.Difficulty, timeDiff) 342 y2.Mul(y2, big8) 343 y2.Div(y2, big100000) 344 345 y3.Mul(parent.Difficulty, y_uncle) 346 y3.Div(y3, big1000) 347 348 yn.Add(yn, parent.Difficulty) 349 yn.Add(yn, y1) 350 yn.Sub(yn, y2) 351 yn.Add(yn, y3) 352 if yn.Cmp(big5000) < 0 { 353 yn.Set(big5000) 354 } 355 356 return yn 357 } 358 359 // VerifySeal implements consensus.Engine, checking whether the given block satisfies 360 // the PoW difficulty requirements. 361 func (powScrypt *PowScrypt) VerifySeal(chain consensus.ChainReader, header *types.Header) error { 362 return powScrypt.verifySeal(chain, header) 363 } 364 365 // verifySeal checks whether a block satisfies the PoW difficulty requirements, 366 func (powScrypt *PowScrypt) verifySeal(chain consensus.ChainReader, header *types.Header) error { 367 // If we're running a fake PoW, accept any seal as valid 368 if powScrypt.config.PowMode == ModeFake || powScrypt.config.PowMode == ModeFullFake { 369 time.Sleep(powScrypt.fakeDelay) 370 if powScrypt.fakeFail == header.Number.Uint64() { 371 return errInvalidPoW 372 } 373 return nil 374 } 375 // Ensure that we have a valid difficulty for the block 376 if header.Difficulty.Sign() <= 0 { 377 return errInvalidDifficulty 378 } 379 380 digest, result := ScryptHash(powScrypt.SealHash(header).Bytes(), header.Nonce.Uint64()) 381 382 if !bytes.Equal(header.MixDigest[:], digest) { 383 return errInvalidMixDigest 384 } 385 target := new(big.Int).Div(two256, header.Difficulty) 386 if new(big.Int).SetBytes(result).Cmp(target) > 0 { 387 return errInvalidPoW 388 } 389 return nil 390 } 391 392 // Prepare implements consensus.Engine, initializing the difficulty field of a 393 // header to conform to the ethash protocol. The changes are done inline. 394 func (powScrypt *PowScrypt) Prepare(chain consensus.ChainReader, header *types.Header) error { 395 parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) 396 if parent == nil { 397 return consensus.ErrUnknownAncestor 398 } 399 header.Difficulty = powScrypt.CalcDifficulty(chain, header.Time, parent) 400 return nil 401 } 402 403 // Finalize implements consensus.Engine, accumulating the block and uncle rewards, 404 // setting the final state on the header 405 func (powScrypt *PowScrypt) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, _ []*types.Receipt) error { 406 // Accumulate any block and uncle rewards and commit the final state root 407 accumulateRewards(chain.Config(), state, header, uncles) 408 header.Root = state.IntermediateRoot(true) 409 return nil 410 } 411 412 // FinalizeAndAssemble implements consensus.Engine, accumulating the block and 413 // uncle rewards, setting the final state and assembling the block. 414 func (powScrypt *PowScrypt) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { 415 // Accumulate any block and uncle rewards and commit the final state root 416 accumulateRewards(chain.Config(), state, header, uncles) 417 header.Root = state.IntermediateRoot(true) 418 419 // Header seems complete, assemble into a block and return 420 return types.NewBlock(header, txs, uncles, receipts), nil 421 } 422 423 // SealHash returns the hash of a block prior to it being sealed. 424 func (powScrypt *PowScrypt) SealHash(header *types.Header) (hash common.Hash) { 425 hasher := sha3.NewLegacyKeccak256() 426 427 _ = rlp.Encode(hasher, []interface{}{ 428 header.ParentHash, 429 header.UncleHash, 430 header.Coinbase, 431 header.Root, 432 header.TxHash, 433 header.ReceiptHash, 434 header.Bloom, 435 header.Difficulty, 436 header.Number, 437 header.GasLimit, 438 header.GasUsed, 439 header.Time, 440 header.Extra, 441 }) 442 hasher.Sum(hash[:0]) 443 return hash 444 } 445 446 // Some weird constants to avoid constant memory allocs for them. 447 var ( 448 big8 = big.NewInt(8) 449 big32 = big.NewInt(32) 450 ) 451 452 // AccumulateRewards credits the coinbase of the given block with the mining 453 // reward. The total reward consists of the static block reward and rewards for 454 // included uncles. The coinbase of each uncle block is also rewarded. 455 func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) { 456 blockReward := CalculateFixedRewards(header.Number) 457 uncleReward := big.NewInt(0) 458 r := new(big.Int) 459 for _, uncle := range uncles { 460 r.Add(uncle.Number, big8) 461 r.Sub(r, header.Number) 462 r.Mul(r, blockReward) 463 r.Div(r, big8) 464 state.AddBalance(uncle.Coinbase, r) 465 466 r.Div(blockReward, big32) 467 uncleReward.Add(uncleReward, r) 468 } 469 470 foundation := CalculateFoundationRewards(header.Number, blockReward) 471 blockReward.Sub(blockReward, foundation) 472 blockReward.Add(blockReward, uncleReward) 473 state.AddBalance(header.Coinbase, blockReward) 474 state.AddBalance(params.FoundationAddress, foundation) 475 476 } 477 478 func CalculateFixedRewards(blockNumber *big.Int) *big.Int { 479 reward := new(big.Int).Set(BlockReward) 480 number := new(big.Int).Set(blockNumber) 481 if number.Sign() == 1 { 482 number.Div(number, BlockAttenuation) 483 base := big.NewInt(0) 484 base.Exp(big.NewInt(2), number, big.NewInt(0)) 485 reward.Div(reward, base) 486 } 487 return reward 488 } 489 490 func CalculateFoundationRewards(blockNumber *big.Int, blockReward *big.Int) *big.Int { 491 foundation := new(big.Int).Set(blockReward) 492 foundation.Mul(foundation, big5) 493 number := new(big.Int).Set(blockNumber) 494 if number.Sign() == 1 { 495 number.Div(number, BlockAttenuation) 496 base := big.NewInt(0) 497 base.Exp(big.NewInt(2), number, big.NewInt(0)) 498 foundation.Div(foundation, base) 499 } 500 foundation.Div(foundation, big100) 501 return foundation 502 }