github.com/beyonderyue/gochain@v2.2.26+incompatible/consensus/clique/fake.go (about)

     1  package clique
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"time"
     7  
     8  	"github.com/gochain-io/gochain/common"
     9  	"github.com/gochain-io/gochain/common/hexutil"
    10  	"github.com/gochain-io/gochain/consensus"
    11  	"github.com/gochain-io/gochain/core/state"
    12  	"github.com/gochain-io/gochain/core/types"
    13  	"github.com/gochain-io/gochain/params"
    14  	"github.com/gochain-io/gochain/rpc"
    15  )
    16  
    17  // fakeEngine is a fake clique consensus.Engine for testing only.
    18  type fakeEngine struct {
    19  	real  *Clique
    20  	Full  bool
    21  	Delay time.Duration
    22  	Fail  uint64
    23  }
    24  
    25  // NewFaker returns a new fake consensus.Engine.
    26  func NewFaker() consensus.Engine {
    27  	return &fakeEngine{
    28  		real: &Clique{
    29  			config: params.DefaultCliqueConfig(),
    30  		},
    31  	}
    32  }
    33  
    34  // NewFaker returns a new fake consensus.Engine which sleeps for delay during header verification.
    35  func NewFakeDelayer(delay time.Duration) consensus.Engine {
    36  	return &fakeEngine{
    37  		real: &Clique{
    38  			config: params.DefaultCliqueConfig(),
    39  		},
    40  		Delay: delay,
    41  	}
    42  }
    43  
    44  // NewFakeFailer returns a new fake consensus.Engine which fails header verification at the given block.
    45  func NewFakeFailer(fail uint64) consensus.Engine {
    46  	return &fakeEngine{
    47  		real: &Clique{
    48  			config: params.DefaultCliqueConfig(),
    49  		},
    50  		Fail: fail,
    51  	}
    52  }
    53  
    54  // NewFullFaker returns a new fake consensus.Engine which skips header verification entirely.
    55  func NewFullFaker() consensus.Engine {
    56  	return &fakeEngine{
    57  		real: &Clique{
    58  			config: params.DefaultCliqueConfig(),
    59  		},
    60  		Full: true,
    61  	}
    62  }
    63  
    64  func (e *fakeEngine) APIs(chain consensus.ChainReader) []rpc.API {
    65  	return e.real.APIs(chain)
    66  }
    67  
    68  func (e *fakeEngine) Authorize(signer common.Address, fn consensus.SignerFn) {
    69  	e.real.Authorize(signer, fn)
    70  }
    71  
    72  func (e *fakeEngine) Author(header *types.Header) (common.Address, error) {
    73  	return header.Coinbase, nil
    74  }
    75  
    76  func (e *fakeEngine) VerifyHeader(ctx context.Context, chain consensus.ChainReader, header *types.Header) error {
    77  	if e.Full {
    78  		return nil
    79  	}
    80  	// Sanity check.
    81  	number := header.Number.Uint64()
    82  	if chain.GetHeader(header.Hash(), number) != nil {
    83  		return nil
    84  	}
    85  	if number > 0 {
    86  		parent := chain.GetHeader(header.ParentHash, number-1)
    87  		if parent == nil {
    88  			return consensus.ErrUnknownAncestor
    89  		}
    90  	}
    91  	// Subset of real method - skip cascading field and seal verification.
    92  	if err := e.real.verifyHeader(ctx, chain, header, nil); err != nil {
    93  		return err
    94  	}
    95  	return e.delayOrFail(ctx, chain, header, nil)
    96  }
    97  
    98  func (e *fakeEngine) VerifyHeaders(ctx context.Context, chain consensus.ChainReader, headers []*types.Header) (chan<- struct{}, <-chan error) {
    99  	if e.Full || len(headers) == 0 {
   100  		return e.real.verifyHeaders(ctx, chain, headers, nil)
   101  	}
   102  	// Subset of real method - skip cascading field and seal verification.
   103  	return e.real.verifyHeaders(ctx, chain, headers, []verifyFn{e.real.verifyHeader, e.delayOrFail})
   104  }
   105  
   106  func (e *fakeEngine) delayOrFail(_ context.Context, _ consensus.ChainReader, header *types.Header, _ []*types.Header) error {
   107  	time.Sleep(e.Delay)
   108  	if e.Fail > 0 && e.Fail == header.Number.Uint64() {
   109  		return errors.New("fake failure")
   110  	}
   111  	return nil
   112  }
   113  
   114  func (e *fakeEngine) Prepare(ctx context.Context, chain consensus.ChainReader, header *types.Header) error {
   115  	header.Extra = ExtraEnsureVanity(header.Extra)
   116  	if header.Difficulty == nil {
   117  		header.Difficulty = header.Coinbase.Big()
   118  		if header.Difficulty.Uint64() == 0 {
   119  			header.Difficulty.SetUint64(1)
   120  		}
   121  	}
   122  	return nil
   123  }
   124  
   125  func (e *fakeEngine) Finalize(ctx context.Context, chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
   126  	receipts []*types.Receipt, block bool) *types.Block {
   127  	return e.real.Finalize(ctx, chain, header, state, txs, receipts, block)
   128  }
   129  
   130  func (e *fakeEngine) Seal(ctx context.Context, chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, *time.Time, error) {
   131  	header := block.Header()
   132  	header.Nonce, header.MixDigest = types.BlockNonce{}, common.Hash{}
   133  	header.Signer = hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
   134  	return block.WithSeal(header), nil, nil
   135  }
   136  
   137  func (e *fakeEngine) SealHash(header *types.Header) common.Hash {
   138  	return e.real.SealHash(header)
   139  }