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 }