github.com/vipernet-xyz/tm@v0.34.24/light/provider/mock/mock.go (about)

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