You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
2.2 KiB

  1. package light
  2. import (
  3. "encoding/hex"
  4. "sort"
  5. lightErr "github.com/tendermint/tendermint/light/errors"
  6. )
  7. type memStoreProvider struct {
  8. // byHeight is always sorted by Height... need to support range search (nil, h]
  9. // btree would be more efficient for larger sets
  10. byHeight fullCommits
  11. byHash map[string]FullCommit
  12. }
  13. // fullCommits just exists to allow easy sorting
  14. type fullCommits []FullCommit
  15. func (s fullCommits) Len() int { return len(s) }
  16. func (s fullCommits) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  17. func (s fullCommits) Less(i, j int) bool {
  18. return s[i].Height() < s[j].Height()
  19. }
  20. // NewMemStoreProvider returns a new in-memory provider.
  21. func NewMemStoreProvider() Provider {
  22. return &memStoreProvider{
  23. byHeight: fullCommits{},
  24. byHash: map[string]FullCommit{},
  25. }
  26. }
  27. func (m *memStoreProvider) encodeHash(hash []byte) string {
  28. return hex.EncodeToString(hash)
  29. }
  30. // StoreCommit stores a FullCommit after verifying it.
  31. func (m *memStoreProvider) StoreCommit(fc FullCommit) error {
  32. // make sure the fc is self-consistent before saving
  33. err := fc.ValidateBasic(fc.Commit.Header.ChainID)
  34. if err != nil {
  35. return err
  36. }
  37. // store the valid fc
  38. key := m.encodeHash(fc.ValidatorsHash())
  39. m.byHash[key] = fc
  40. m.byHeight = append(m.byHeight, fc)
  41. sort.Sort(m.byHeight)
  42. return nil
  43. }
  44. // GetByHeight returns the FullCommit for height h or an error if the commit is not found.
  45. func (m *memStoreProvider) GetByHeight(h int) (FullCommit, error) {
  46. // search from highest to lowest
  47. for i := len(m.byHeight) - 1; i >= 0; i-- {
  48. fc := m.byHeight[i]
  49. if fc.Height() <= h {
  50. return fc, nil
  51. }
  52. }
  53. return FullCommit{}, lightErr.ErrCommitNotFound()
  54. }
  55. // GetByHash returns the FullCommit for the hash or an error if the commit is not found.
  56. func (m *memStoreProvider) GetByHash(hash []byte) (FullCommit, error) {
  57. var err error
  58. fc, ok := m.byHash[m.encodeHash(hash)]
  59. if !ok {
  60. err = lightErr.ErrCommitNotFound()
  61. }
  62. return fc, err
  63. }
  64. // LatestCommit returns the latest FullCommit or an error if no commits exist.
  65. func (m *memStoreProvider) LatestCommit() (FullCommit, error) {
  66. l := len(m.byHeight)
  67. if l == 0 {
  68. return FullCommit{}, lightErr.ErrCommitNotFound()
  69. }
  70. return m.byHeight[l-1], nil
  71. }