github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/consensus/mock/mock.go (about)

     1  // Copyright 2019 The go-vnt Authors
     2  // This file is part of the go-vnt library.
     3  //
     4  // The go-vnt 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-vnt 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-vnt library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package mock
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"math/big"
    23  
    24  	"github.com/vntchain/go-vnt/common"
    25  	"github.com/vntchain/go-vnt/consensus"
    26  	"github.com/vntchain/go-vnt/core/state"
    27  	"github.com/vntchain/go-vnt/core/types"
    28  	"github.com/vntchain/go-vnt/log"
    29  	"github.com/vntchain/go-vnt/rpc"
    30  )
    31  
    32  var (
    33  	// errUnknownBlock is returned when the list of signers is requested for a block
    34  	// that is not part of the local blockchain.
    35  	errUnknownBlock = errors.New("unknown block")
    36  
    37  	// errInvalidDifficulty is returned if the difficulty of a block is not 1
    38  	errInvalidDifficulty = errors.New("invalid difficulty")
    39  )
    40  
    41  type Mock struct {
    42  	fakeFail uint64
    43  }
    44  
    45  func NewMock() *Mock {
    46  	return &Mock{}
    47  }
    48  
    49  func NewMockFail(failNum uint64) *Mock {
    50  	return &Mock{
    51  		fakeFail: failNum,
    52  	}
    53  }
    54  func (m *Mock) Author(header *types.Header) (common.Address, error) {
    55  	return header.Coinbase, nil
    56  }
    57  
    58  func (m *Mock) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
    59  	err := m.verifyHeader(chain, header, nil)
    60  	if err != nil {
    61  		log.Debug("VerifyHeader error", "hash", header.Hash(), "err", err.Error())
    62  	} else {
    63  		log.Debug("VerifyHeader NO error", "hash", header.Hash(), "number", header.Number.Int64())
    64  	}
    65  	return err
    66  }
    67  
    68  func (m *Mock) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
    69  	abort := make(chan struct{})
    70  	results := make(chan error, len(headers))
    71  	go func() {
    72  		for i, header := range headers {
    73  			err := m.verifyHeader(chain, header, headers[:i])
    74  
    75  			select {
    76  			case <-abort:
    77  				return
    78  			case results <- err:
    79  			}
    80  		}
    81  	}()
    82  	return abort, results
    83  }
    84  
    85  func (m *Mock) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
    86  	if m.fakeFail == header.Number.Uint64() {
    87  		return fmt.Errorf("fake Fail")
    88  	}
    89  	if header.Number == nil {
    90  		return errUnknownBlock
    91  	}
    92  	number := header.Number.Uint64()
    93  
    94  	// Ensure that the block's difficulty is meaningful (may not be correct at this point)
    95  	if number > 0 {
    96  		if header.Difficulty == nil || header.Difficulty.Cmp(big.NewInt(1)) != 0 {
    97  			return errInvalidDifficulty
    98  		}
    99  	}
   100  	// All basic checks passed, verify cascading fields
   101  	return m.verifyCascadingFields(chain, header, parents)
   102  }
   103  func (m *Mock) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
   104  	// The genesis block is the always valid dead-end
   105  	number := header.Number.Uint64()
   106  	if number == 0 {
   107  		return nil
   108  	}
   109  	// Ensure that the block's timestamp isn't too close to it's parent
   110  	var parent *types.Header
   111  	if len(parents) > 0 {
   112  		parent = parents[len(parents)-1]
   113  	} else {
   114  		parent = chain.GetHeader(header.ParentHash, number-1)
   115  	}
   116  	if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash {
   117  		return consensus.ErrUnknownAncestor
   118  	}
   119  	return nil
   120  }
   121  
   122  func (m *Mock) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
   123  	return nil
   124  }
   125  
   126  func (m *Mock) VerifyWitnesses(header *types.Header, db *state.StateDB, parent *types.Header) error {
   127  	return nil
   128  }
   129  
   130  func (m *Mock) VerifyCommitMsg(block *types.Block) error {
   131  	return nil
   132  }
   133  
   134  func (m *Mock) Prepare(chain consensus.ChainReader, header *types.Header) error {
   135  	header.Difficulty = big.NewInt(1)
   136  	return nil
   137  }
   138  
   139  func (m *Mock) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
   140  	receipts []*types.Receipt) (*types.Block, error) {
   141  	state.AddBalance(header.Coinbase, big.NewInt(5e18))
   142  	header.Root = state.IntermediateRoot(true)
   143  
   144  	// Assemble and return the final block for sealing
   145  	return types.NewBlock(header, txs, receipts), nil
   146  }
   147  
   148  func (m *Mock) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) {
   149  	return block, nil
   150  }
   151  
   152  func (m *Mock) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
   153  	return common.Big1
   154  }
   155  
   156  func (m *Mock) HandleBftMsg(chain consensus.ChainReader, msg types.ConsensusMsg) {
   157  }
   158  
   159  // APIs returns the RPC APIs this consensus engine provides.
   160  func (m *Mock) APIs(chain consensus.ChainReader) []rpc.API {
   161  	return nil
   162  }