github.com/soomindae/tendermint@v0.0.5-0.20210528140126-84a0c70c8162/light/provider/mock/mock.go (about)

     1  package mock
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"strings"
     8  	"sync"
     9  
    10  	"github.com/soomindae/tendermint/light/provider"
    11  	"github.com/soomindae/tendermint/types"
    12  )
    13  
    14  type Mock struct {
    15  	chainID string
    16  
    17  	mtx              sync.Mutex
    18  	headers          map[int64]*types.SignedHeader
    19  	vals             map[int64]*types.ValidatorSet
    20  	evidenceToReport map[string]types.Evidence // hash => evidence
    21  	latestHeight     int64
    22  }
    23  
    24  var _ provider.Provider = (*Mock)(nil)
    25  
    26  // New creates a mock provider with the given set of headers and validator
    27  // sets.
    28  func New(chainID string, headers map[int64]*types.SignedHeader, vals map[int64]*types.ValidatorSet) *Mock {
    29  	height := int64(0)
    30  	for h := range headers {
    31  		if h > height {
    32  			height = h
    33  		}
    34  	}
    35  	return &Mock{
    36  		chainID:          chainID,
    37  		headers:          headers,
    38  		vals:             vals,
    39  		evidenceToReport: make(map[string]types.Evidence),
    40  		latestHeight:     height,
    41  	}
    42  }
    43  
    44  // ChainID returns the blockchain ID.
    45  func (p *Mock) ChainID() string {
    46  	return p.chainID
    47  }
    48  
    49  func (p *Mock) String() string {
    50  	var headers strings.Builder
    51  	for _, h := range p.headers {
    52  		fmt.Fprintf(&headers, " %d:%X", h.Height, h.Hash())
    53  	}
    54  
    55  	var vals strings.Builder
    56  	for _, v := range p.vals {
    57  		fmt.Fprintf(&vals, " %X", v.Hash())
    58  	}
    59  
    60  	return fmt.Sprintf("Mock{headers: %s, vals: %v}", headers.String(), vals.String())
    61  }
    62  
    63  func (p *Mock) LightBlock(_ context.Context, height int64) (*types.LightBlock, error) {
    64  	p.mtx.Lock()
    65  	defer p.mtx.Unlock()
    66  	var lb *types.LightBlock
    67  
    68  	if height > p.latestHeight {
    69  		return nil, provider.ErrHeightTooHigh
    70  	}
    71  
    72  	if height == 0 && len(p.headers) > 0 {
    73  		height = p.latestHeight
    74  	}
    75  
    76  	if _, ok := p.headers[height]; ok {
    77  		sh := p.headers[height]
    78  		vals := p.vals[height]
    79  		lb = &types.LightBlock{
    80  			SignedHeader: sh,
    81  			ValidatorSet: vals,
    82  		}
    83  	}
    84  	if lb == nil {
    85  		return nil, provider.ErrLightBlockNotFound
    86  	}
    87  	if lb.SignedHeader == nil || lb.ValidatorSet == nil {
    88  		return nil, provider.ErrBadLightBlock{Reason: errors.New("nil header or vals")}
    89  	}
    90  	if err := lb.ValidateBasic(lb.ChainID); err != nil {
    91  		return nil, provider.ErrBadLightBlock{Reason: err}
    92  	}
    93  	return lb, nil
    94  }
    95  
    96  func (p *Mock) ReportEvidence(_ context.Context, ev types.Evidence) error {
    97  	p.evidenceToReport[string(ev.Hash())] = ev
    98  	return nil
    99  }
   100  
   101  func (p *Mock) HasEvidence(ev types.Evidence) bool {
   102  	_, ok := p.evidenceToReport[string(ev.Hash())]
   103  	return ok
   104  }
   105  
   106  func (p *Mock) AddLightBlock(lb *types.LightBlock) {
   107  	p.mtx.Lock()
   108  	defer p.mtx.Unlock()
   109  
   110  	if err := lb.ValidateBasic(lb.ChainID); err != nil {
   111  		panic(fmt.Sprintf("unable to add light block, err: %v", err))
   112  	}
   113  	p.headers[lb.Height] = lb.SignedHeader
   114  	p.vals[lb.Height] = lb.ValidatorSet
   115  	if lb.Height > p.latestHeight {
   116  		p.latestHeight = lb.Height
   117  	}
   118  }
   119  
   120  func (p *Mock) Copy(id string) *Mock {
   121  	return New(id, p.headers, p.vals)
   122  }