github.com/aquanetwork/aquachain@v1.7.8/consensus/aquahash/consensus.go (about)

     1  // Copyright 2017 The aquachain Authors
     2  // This file is part of the aquachain library.
     3  //
     4  // The aquachain 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 aquachain 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 aquachain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package aquahash
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/binary"
    22  	"errors"
    23  	"fmt"
    24  	"math/big"
    25  	"runtime"
    26  	"time"
    27  
    28  	"gitlab.com/aquachain/aquachain/common"
    29  	"gitlab.com/aquachain/aquachain/common/log"
    30  	"gitlab.com/aquachain/aquachain/common/math"
    31  	"gitlab.com/aquachain/aquachain/consensus"
    32  	"gitlab.com/aquachain/aquachain/core/state"
    33  	"gitlab.com/aquachain/aquachain/core/types"
    34  	"gitlab.com/aquachain/aquachain/crypto"
    35  	"gitlab.com/aquachain/aquachain/params"
    36  
    37  	set "gopkg.in/fatih/set.v0"
    38  )
    39  
    40  // Aquahash proof-of-work protocol constants.
    41  var (
    42  	BlockReward            = params.BlockReward
    43  	maxUncles              = 2                // Maximum number of uncles allowed in a single block
    44  	maxUnclesHF5           = 1                // Maximum number of uncles allowed in a single block after HF5 is activated
    45  	allowedFutureBlockTime = 15 * time.Second // Max time from current time allowed for blocks, before they're considered future blocks
    46  )
    47  
    48  // Various error messages to mark blocks invalid. These should be private to
    49  // prevent engine specific errors from being referenced in the remainder of the
    50  // codebase, inherently breaking if the engine is swapped out. Please put common
    51  // error types into the consensus package.
    52  var (
    53  	errLargeBlockTime    = errors.New("timestamp too big")
    54  	errZeroBlockTime     = errors.New("timestamp equals parent's")
    55  	errTooManyUncles     = errors.New("too many uncles")
    56  	errDuplicateUncle    = errors.New("duplicate uncle")
    57  	errUncleIsAncestor   = errors.New("uncle is ancestor")
    58  	errDanglingUncle     = errors.New("uncle's parent is not ancestor")
    59  	errNonceOutOfRange   = errors.New("nonce out of range")
    60  	errInvalidDifficulty = errors.New("non-positive difficulty")
    61  	errInvalidMixDigest  = errors.New("invalid mix digest")
    62  	errInvalidPoW        = errors.New("invalid proof-of-work")
    63  
    64  	errUnknownGrandparent = errors.New("nil grandparent")
    65  )
    66  
    67  // Author implements consensus.Engine, returning the header's coinbase as the
    68  // proof-of-work verified author of the block.
    69  func (aquahash *Aquahash) Author(header *types.Header) (common.Address, error) {
    70  	return header.Coinbase, nil
    71  }
    72  
    73  // VerifyHeader checks whether a header conforms to the consensus rules of the
    74  // stock AquaChain aquahash engine.
    75  func (aquahash *Aquahash) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
    76  	// If we're running a full engine faking, accept any input as valid
    77  	if aquahash.config.PowMode == ModeFullFake {
    78  		return nil
    79  	}
    80  	// Short circuit if the header is known, or it's parent not
    81  	number := header.Number.Uint64()
    82  	if chain.GetHeader(header.Hash(), number) != nil {
    83  		return nil
    84  	}
    85  
    86  	var parent, grandparent *types.Header
    87  	parent = chain.GetHeader(header.ParentHash, number-1)
    88  	if parent == nil {
    89  		return consensus.ErrUnknownAncestor
    90  	}
    91  	if number > 2 {
    92  		grandparent = chain.GetHeader(parent.ParentHash, number-2)
    93  		if grandparent == nil {
    94  			return fmt.Errorf("nil grandparent: %v", number-2)
    95  		}
    96  	}
    97  	// Sanity checks passed, do a proper verification
    98  	return aquahash.verifyHeader(chain, header, parent, grandparent, 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 (aquahash *Aquahash) 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 aquahash.config.PowMode == 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  	// set version
   121  	for i := range headers {
   122  		if headers[i].Version == 0 {
   123  			panic("hf5: verifyheaders did not receive header version")
   124  		}
   125  	}
   126  
   127  	// Create a task channel and spawn the verifiers
   128  	var (
   129  		inputs = make(chan int)
   130  		done   = make(chan int, workers)
   131  		errors = make([]error, len(headers))
   132  		abort  = make(chan struct{})
   133  	)
   134  	for i := 0; i < workers; i++ {
   135  		go func() {
   136  			for index := range inputs {
   137  				errors[index] = aquahash.verifyHeaderWorker(chain, headers, seals, index)
   138  				done <- index
   139  			}
   140  		}()
   141  	}
   142  
   143  	errorsOut := make(chan error, len(headers))
   144  	go func() {
   145  		defer close(inputs)
   146  		var (
   147  			in, out = 0, 0
   148  			checked = make([]bool, len(headers))
   149  			inputs  = inputs
   150  		)
   151  		for {
   152  			select {
   153  			case inputs <- in:
   154  				if in++; in == len(headers) {
   155  					// Reached end of headers. Stop sending to workers.
   156  					inputs = nil
   157  				}
   158  			case index := <-done:
   159  				for checked[index] = true; checked[out]; out++ {
   160  					errorsOut <- errors[out]
   161  					if out == len(headers)-1 {
   162  						return
   163  					}
   164  				}
   165  			case <-abort:
   166  				return
   167  			}
   168  		}
   169  	}()
   170  	return abort, errorsOut
   171  }
   172  
   173  func (aquahash *Aquahash) verifyHeaderWorker(chain consensus.ChainReader, headers []*types.Header, seals []bool, index int) error {
   174  	var parent, grandparent *types.Header
   175  	if index == 0 {
   176  		parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1)
   177  		if headers[0].Number.Uint64() > 2 && parent != nil {
   178  			grandparent = chain.GetHeader(parent.ParentHash, headers[0].Number.Uint64()-2)
   179  		}
   180  	} else if index == 1 {
   181  		parent = headers[0]
   182  		if parent.Number.Uint64() > 1 {
   183  			grandparent = chain.GetHeader(parent.ParentHash, parent.Number.Uint64()-1)
   184  		}
   185  	} else if headers[index-1].Hash() == headers[index].ParentHash {
   186  		parent = headers[index-1]
   187  		grandparent = headers[index-2]
   188  	}
   189  	if parent == nil && headers[0].Number.Uint64() != 0 {
   190  		return consensus.ErrUnknownAncestor
   191  	}
   192  	if grandparent == nil && parent != nil && parent.Number.Uint64() > 1 {
   193  		return errUnknownGrandparent
   194  	}
   195  	if chain.GetHeader(headers[index].Hash(), headers[index].Number.Uint64()) != nil {
   196  		return nil // known block
   197  	}
   198  	return aquahash.verifyHeader(chain, headers[index], parent, grandparent, false, seals[index])
   199  }
   200  
   201  // VerifyUncles verifies that the given block's uncles conform to the consensus
   202  // rules of the stock AquaChain aquahash engine.
   203  func (aquahash *Aquahash) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
   204  	// If we're running a full engine faking, accept any input as valid
   205  	if aquahash.config.PowMode == ModeFullFake {
   206  		return nil
   207  	}
   208  	// Verify that there are at most 2 uncles included in this block
   209  	if len(block.Uncles()) > maxUncles {
   210  		return errTooManyUncles
   211  	}
   212  	// Verify that there are at most 0 uncles included in this block
   213  	if len(block.Uncles()) > maxUnclesHF5 && chain.Config().IsHF(5, block.Number()) {
   214  		return errTooManyUncles
   215  	}
   216  	// Gather the set of past uncles and ancestors
   217  	uncles, ancestors := set.New(), make(map[common.Hash]*types.Header)
   218  
   219  	number, parent := block.NumberU64()-1, block.ParentHash()
   220  	for i := 0; i < 7; i++ {
   221  		ancestor := chain.GetBlock(parent, number)
   222  		if ancestor == nil {
   223  			break
   224  		}
   225  		ancestors[ancestor.Hash()] = ancestor.Header()
   226  		for _, uncle := range ancestor.Uncles() {
   227  			uncles.Add(uncle.SetVersion(byte(chain.Config().GetBlockVersion(uncle.Number))))
   228  		}
   229  		parent, number = ancestor.ParentHash(), number-1
   230  	}
   231  	if block.Version() == 0 {
   232  		return fmt.Errorf("verify uncles: block version not set")
   233  	}
   234  	ancestorhash := block.Hash()
   235  	ancestors[ancestorhash] = block.Header()
   236  	uncles.Add(ancestorhash)
   237  
   238  	// Verify each of the uncles that it's recent, but not an ancestor
   239  	for _, uncle := range block.Uncles() {
   240  
   241  		unum := uncle.Number
   242  		hash := uncle.SetVersion(byte(chain.Config().GetBlockVersion(unum)))
   243  
   244  		// Make sure every uncle is rewarded only once
   245  		if uncles.Has(hash) {
   246  			if number > 15000 {
   247  				return errDuplicateUncle
   248  			} else if ancestorhash.Hex() == "0xbac2283407b519ffbb8c47772d1b7cf740646dddf69744ff44219cb868b00548" && unum.Uint64() == 13313 {
   249  			} else if ancestorhash.Hex() == "0xa955c8499ce9c4fb00700a8d97db8600dc50c8a81275627a18e30cfb82c19ac2" && unum.Uint64() == 13315 {
   250  			} else if ancestorhash.Hex() == "0x7da0315b99e059f17b18bfd7f07c57b8e3be3aac261dbf470fb2d6cb0acb9899" && unum.Uint64() == 13998 {
   251  			} else {
   252  				return errDuplicateUncle
   253  			}
   254  		}
   255  
   256  		uncles.Add(hash)
   257  
   258  		// Make sure the uncle has a valid ancestry
   259  		if ancestors[hash] != nil {
   260  			return errUncleIsAncestor
   261  		}
   262  
   263  		if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() {
   264  			if number > 15000 {
   265  				return errDanglingUncle
   266  			}
   267  			parentHash := uncle.ParentHash.Hex()
   268  			if parentHash == "0x6b818656fb5059ab4dd070e2c2822a7774065090e74ff31515764212c88e2923" && uncle.Number.Uint64() == 14003 {
   269  				log.Debug("Weird block", "uncle", unum, "number", number)
   270  				return nil
   271  			} else if parentHash == "0x0afd1b00b8e1a49652beeb860e3b58dacc865dd3e3d9d303374ed3ffdfef8eea" && uncle.Number.Uint64() == 14001 {
   272  				log.Debug("Weird block", "uncle", unum, "number", number)
   273  				return nil
   274  			} else if hash.Hex() == "0xed6dae6d2d4f599d78429e127e8a654fe96c30f4b6c9bacb01cfa45d8a57b45e" && uncle.Number.Uint64() == 14004 {
   275  				log.Debug("Weird block", "uncle", unum, "number", number)
   276  				return nil
   277  			} else if hash.Hex() == "0x13cb01d5d3566d076b5e128e5733f17968f95329fb1777ff38db53abdcca3e4c" && uncle.Number.Uint64() == 14008 {
   278  				log.Debug("Weird block", "uncle", unum, "number", number)
   279  				return nil
   280  			} else if hash.Hex() == "0x822735d89d8493434d3ec1f504c9f103d7bb4761cd358370b00dd234621cf1b9" && uncle.Number.Uint64() == 14009 {
   281  				log.Debug("Weird block", "uncle", unum, "number", number)
   282  				return nil
   283  			} else {
   284  				return errDanglingUncle
   285  			}
   286  		}
   287  		parent := ancestors[uncle.ParentHash]
   288  		grandparent := ancestors[parent.ParentHash]
   289  		if err := aquahash.verifyHeader(chain, uncle, parent, grandparent, true, true); err != nil {
   290  			return err
   291  		}
   292  	}
   293  	return nil
   294  }
   295  
   296  // verifyHeader checks whether a header conforms to the consensus rules of the
   297  // stock AquaChain aquahash engine.
   298  // See YP section 4.3.4. "Block Header Validity"
   299  func (aquahash *Aquahash) verifyHeader(chain consensus.ChainReader, header, parent, grandparent *types.Header, uncle bool, seal bool) error {
   300  	// Ensure that the header's extra-data section is of a reasonable size
   301  	if uint64(len(header.Extra)) > params.MaximumExtraDataSize {
   302  		return fmt.Errorf("block %d extra-data too long: %d > %d", header.Number, len(header.Extra), params.MaximumExtraDataSize)
   303  	}
   304  	// Verify the header's timestamp
   305  	if uncle {
   306  		if header.Time.Cmp(math.MaxBig256) > 0 {
   307  			return errLargeBlockTime
   308  		}
   309  	} else {
   310  		if header.Time.Cmp(big.NewInt(time.Now().Add(allowedFutureBlockTime).Unix())) > 0 {
   311  			return consensus.ErrFutureBlock
   312  		}
   313  	}
   314  	if header.Time.Cmp(parent.Time) <= 0 {
   315  		return errZeroBlockTime
   316  	}
   317  	// Verify the block's difficulty based in it's timestamp and parent's difficulty
   318  	expected := aquahash.CalcDifficulty(chain, header.Time.Uint64(), parent, grandparent)
   319  
   320  	if expected.Cmp(header.Difficulty) != 0 {
   321  		return fmt.Errorf("block %d invalid difficulty: have %v, want %v", header.Number, header.Difficulty, expected)
   322  	}
   323  	// Verify that the gas limit is <= 2^63-1
   324  	cap := uint64(0x7fffffffffffffff)
   325  	if header.GasLimit > cap {
   326  		return fmt.Errorf("block %d invalid gasLimit: have %v, max %v", header.Number, header.GasLimit, cap)
   327  	}
   328  	// Verify that the gasUsed is <= gasLimit
   329  	if header.GasUsed > header.GasLimit {
   330  		return fmt.Errorf("block %d invalid gasUsed: have %d, gasLimit %d", header.Number, header.GasUsed, header.GasLimit)
   331  	}
   332  
   333  	// Verify that the gas limit remains within allowed bounds
   334  	diff := int64(parent.GasLimit) - int64(header.GasLimit)
   335  	if diff < 0 {
   336  		diff *= -1
   337  	}
   338  	limit := parent.GasLimit / params.GasLimitBoundDivisor
   339  
   340  	if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit {
   341  		return fmt.Errorf("block %d invalid gas limit: have %d, want %d += %d", header.Number, header.GasLimit, parent.GasLimit, limit)
   342  	}
   343  	// Verify that the block number is parent's +1
   344  	if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 {
   345  		return consensus.ErrInvalidNumber
   346  	}
   347  	// Verify the engine specific seal securing the block
   348  	if seal {
   349  		if err := aquahash.VerifySeal(chain, header); err != nil {
   350  			return err
   351  		}
   352  	}
   353  	return nil
   354  }
   355  
   356  // CalcDifficulty is the difficulty adjustment algorithm. It returns
   357  // the difficulty that a new block should have when created at time
   358  // given the parent block's time and difficulty.
   359  func (aquahash *Aquahash) CalcDifficulty(chain consensus.ChainReader, time uint64, parent, grandparent *types.Header) *big.Int {
   360  	if grandparent == nil && parent != nil && parent.Number.Uint64() != 0 {
   361  		grandparent = chain.GetHeader(parent.ParentHash, parent.Number.Uint64()-1)
   362  	}
   363  	return CalcDifficulty(chain.Config(), time, parent, grandparent)
   364  }
   365  
   366  // CalcDifficulty is the difficulty adjustment algorithm. It returns
   367  // the difficulty that a new block should have when created at time
   368  // given the parent block's time and difficulty.
   369  func CalcDifficulty(config *params.ChainConfig, time uint64, parent, grandparent *types.Header) *big.Int {
   370  	if config == nil {
   371  		panic("calcdiff got nil config")
   372  	}
   373  	return calcDifficultyHFX(config, time, parent, grandparent)
   374  }
   375  
   376  // VerifySeal implements consensus.Engine, checking whether the given block satisfies
   377  // the PoW difficulty requirements.
   378  func (aquahash *Aquahash) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
   379  	// If we're running a fake PoW, accept any seal as valid
   380  	if aquahash.config.PowMode == ModeFake || aquahash.config.PowMode == ModeFullFake {
   381  		time.Sleep(aquahash.fakeDelay)
   382  		if aquahash.fakeFail == header.Number.Uint64() {
   383  			return errInvalidPoW
   384  		}
   385  		return nil
   386  	}
   387  	// If we're running a shared PoW, delegate verification to it
   388  	if aquahash.shared != nil {
   389  		return aquahash.shared.VerifySeal(chain, header)
   390  	}
   391  	// Sanity check that the block number is below the lookup table size (60M blocks)
   392  	number := header.Number.Uint64()
   393  	if number/epochLength >= maxEpoch {
   394  		// Go < 1.7 cannot calculate new cache/dataset sizes (no fast prime check)
   395  		return errNonceOutOfRange
   396  	}
   397  	// Ensure that we have a valid difficulty for the block
   398  	if header.Difficulty.Sign() <= 0 {
   399  		return errInvalidDifficulty
   400  	}
   401  
   402  	// Recompute the digest and PoW value and verify against the header
   403  	cache := aquahash.cache(number)
   404  	size := datasetSize(number)
   405  	if aquahash.config.PowMode == ModeTest {
   406  		size = 32 * 1024
   407  	}
   408  	var (
   409  		digest []byte
   410  		result []byte
   411  	)
   412  	switch header.Version {
   413  	case types.H_UNSET: // 0
   414  		panic("header version not set")
   415  	case types.H_KECCAK256: // 1
   416  		digest, result = hashimotoLight(size, cache.cache, header.HashNoNonce().Bytes(), header.Nonce.Uint64())
   417  	default:
   418  		seed := make([]byte, 40)
   419  		copy(seed, header.HashNoNonce().Bytes())
   420  		binary.LittleEndian.PutUint64(seed[32:], header.Nonce.Uint64())
   421  		result = crypto.VersionHash(byte(header.Version), seed)
   422  		digest = make([]byte, common.HashLength)
   423  	}
   424  	// Caches are unmapped in a finalizer. Ensure that the cache stays live
   425  	// until after the call to hashimotoLight so it's not unmapped while being used.
   426  	runtime.KeepAlive(cache)
   427  
   428  	if !bytes.Equal(header.MixDigest[:], digest) {
   429  		//fmt.Printf("Invalid Digest (%v):\n%x (!=) %x\n", header.Number.Uint64(), header.MixDigest[:], digest)
   430  		return errInvalidMixDigest
   431  	}
   432  	target := new(big.Int).Div(maxUint256, header.Difficulty)
   433  	if new(big.Int).SetBytes(result).Cmp(target) > 0 {
   434  		return errInvalidPoW
   435  	}
   436  	return nil
   437  }
   438  
   439  // Prepare implements consensus.Engine, initializing the difficulty field of a
   440  // header to conform to the aquahash protocol. The changes are done inline.
   441  func (aquahash *Aquahash) Prepare(chain consensus.ChainReader, header *types.Header) error {
   442  	var parent, grandparent *types.Header
   443  	parent = chain.GetHeader(header.ParentHash, header.Number.Uint64()-1)
   444  	if parent == nil {
   445  		return consensus.ErrUnknownAncestor
   446  	}
   447  	if header.Number.Uint64() > 2 {
   448  		grandparent = chain.GetHeader(parent.ParentHash, header.Number.Uint64()-2)
   449  		if grandparent == nil {
   450  			return errUnknownGrandparent
   451  		}
   452  	}
   453  	header.Difficulty = aquahash.CalcDifficulty(chain, header.Time.Uint64(), parent, grandparent)
   454  	return nil
   455  }
   456  
   457  // Finalize implements consensus.Engine, accumulating the block and uncle rewards,
   458  // setting the final state and assembling the block.
   459  func (aquahash *Aquahash) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
   460  	// Accumulate any block and uncle rewards and commit the final state root
   461  	header.SetVersion(byte(chain.Config().GetBlockVersion(header.Number)))
   462  	for i := range uncles {
   463  		uncles[i].Version = header.Version // uncles must have same version
   464  	}
   465  	accumulateRewards(chain.Config(), state, header, uncles)
   466  	header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
   467  	// Header seems complete, assemble into a block and return
   468  	return types.NewBlock(header, txs, uncles, receipts), nil
   469  }
   470  
   471  // Some weird constants to avoid constant memory allocs for them.
   472  var (
   473  	big8  = big.NewInt(8)
   474  	big32 = big.NewInt(32)
   475  )
   476  
   477  // AccumulateRewards credits the coinbase of the given block with the mining
   478  // reward. The total reward consists of the static block reward and rewards for
   479  // included uncles. The coinbase of each uncle block is also rewarded.
   480  func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) {
   481  	// Select the correct block reward based on chain progression
   482  	blockReward := BlockReward
   483  
   484  	// fees-only after 42,000,000
   485  	// since uncles have a reward too, we will have to adjust this number
   486  	// luckily we have time before we hit anywhere near there
   487  	rewarding := header.Number.Cmp(params.MaxMoney) == -1
   488  	if !rewarding {
   489  		return
   490  	}
   491  	// Accumulate the rewards for the miner and any included uncles
   492  	reward := new(big.Int).Set(blockReward)
   493  	r := new(big.Int)
   494  	for _, uncle := range uncles {
   495  		r.Add(uncle.Number, big8)
   496  		r.Sub(r, header.Number)
   497  		r.Mul(r, blockReward)
   498  		r.Div(r, big8)
   499  		state.AddBalance(uncle.Coinbase, r)
   500  
   501  		r.Div(blockReward, big32)
   502  		reward.Add(reward, r)
   503  	}
   504  	state.AddBalance(header.Coinbase, reward)
   505  }