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 }