github.com/number571/tendermint@v0.34.11-gost/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/number571/tendermint/light/provider"
    12  	"github.com/number571/tendermint/types"
    13  )
    14  
    15  type Mock struct {
    16  	id 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(id 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  		id:               id,
    38  		headers:          headers,
    39  		vals:             vals,
    40  		evidenceToReport: make(map[string]types.Evidence),
    41  		latestHeight:     height,
    42  	}
    43  }
    44  
    45  func (p *Mock) String() string {
    46  	var headers strings.Builder
    47  	for _, h := range p.headers {
    48  		fmt.Fprintf(&headers, " %d:%X", h.Height, h.Hash())
    49  	}
    50  
    51  	var vals strings.Builder
    52  	for _, v := range p.vals {
    53  		fmt.Fprintf(&vals, " %X", v.Hash())
    54  	}
    55  
    56  	return fmt.Sprintf("Mock{id: %s, headers: %s, vals: %v}", p.id, headers.String(), vals.String())
    57  }
    58  
    59  func (p *Mock) LightBlock(ctx context.Context, height int64) (*types.LightBlock, error) {
    60  	p.mtx.Lock()
    61  	defer p.mtx.Unlock()
    62  
    63  	select {
    64  	case <-ctx.Done():
    65  		return nil, ctx.Err()
    66  	case <-time.After(10 * time.Millisecond):
    67  	}
    68  
    69  	var lb *types.LightBlock
    70  
    71  	if height > p.latestHeight {
    72  		return nil, provider.ErrHeightTooHigh
    73  	}
    74  
    75  	if height == 0 && len(p.headers) > 0 {
    76  		height = p.latestHeight
    77  	}
    78  
    79  	if _, ok := p.headers[height]; ok {
    80  		sh := p.headers[height]
    81  		vals := p.vals[height]
    82  		lb = &types.LightBlock{
    83  			SignedHeader: sh,
    84  			ValidatorSet: vals,
    85  		}
    86  	}
    87  	if lb == nil {
    88  		return nil, provider.ErrLightBlockNotFound
    89  	}
    90  	if lb.SignedHeader == nil || lb.ValidatorSet == nil {
    91  		return nil, provider.ErrBadLightBlock{Reason: errors.New("nil header or vals")}
    92  	}
    93  	if err := lb.ValidateBasic(lb.ChainID); err != nil {
    94  		return nil, provider.ErrBadLightBlock{Reason: err}
    95  	}
    96  	return lb, nil
    97  }
    98  
    99  func (p *Mock) ReportEvidence(_ context.Context, ev types.Evidence) error {
   100  	p.evidenceToReport[string(ev.Hash())] = ev
   101  	return nil
   102  }
   103  
   104  func (p *Mock) HasEvidence(ev types.Evidence) bool {
   105  	_, ok := p.evidenceToReport[string(ev.Hash())]
   106  	return ok
   107  }
   108  
   109  func (p *Mock) AddLightBlock(lb *types.LightBlock) {
   110  	p.mtx.Lock()
   111  	defer p.mtx.Unlock()
   112  
   113  	if err := lb.ValidateBasic(lb.ChainID); err != nil {
   114  		panic(fmt.Sprintf("unable to add light block, err: %v", err))
   115  	}
   116  	p.headers[lb.Height] = lb.SignedHeader
   117  	p.vals[lb.Height] = lb.ValidatorSet
   118  	if lb.Height > p.latestHeight {
   119  		p.latestHeight = lb.Height
   120  	}
   121  }
   122  
   123  func (p *Mock) Copy(id string) *Mock {
   124  	return New(id, p.headers, p.vals)
   125  }