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.

102 lines
2.2 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package blocks
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "encoding/json"
  6. . "github.com/tendermint/tendermint/binary"
  7. . "github.com/tendermint/tendermint/common"
  8. db_ "github.com/tendermint/tendermint/db"
  9. )
  10. var (
  11. blockStoreKey = []byte("blockStore")
  12. )
  13. //-----------------------------------------------------------------------------
  14. type BlockStoreJSON struct {
  15. Height uint32
  16. }
  17. func (bsj BlockStoreJSON) Save(db db_.DB) {
  18. bytes, err := json.Marshal(bsj)
  19. if err != nil {
  20. Panicf("Could not marshal state bytes: %v", err)
  21. }
  22. db.Set(blockStoreKey, bytes)
  23. }
  24. func LoadBlockStoreJSON(db db_.DB) BlockStoreJSON {
  25. bytes := db.Get(blockStoreKey)
  26. if bytes == nil {
  27. return BlockStoreJSON{
  28. Height: 0,
  29. }
  30. }
  31. bsj := BlockStoreJSON{}
  32. err := json.Unmarshal(bytes, &bsj)
  33. if err != nil {
  34. Panicf("Could not unmarshal bytes: %X", bytes)
  35. }
  36. return bsj
  37. }
  38. //-----------------------------------------------------------------------------
  39. /*
  40. Simple low level store for blocks, which is actually stored as separte parts (wire format).
  41. */
  42. type BlockStore struct {
  43. height uint32
  44. db db_.DB
  45. }
  46. func NewBlockStore(db db_.DB) *BlockStore {
  47. bsjson := LoadBlockStoreJSON(db)
  48. return &BlockStore{
  49. height: bsjson.Height,
  50. db: db,
  51. }
  52. }
  53. // Height() returns the last known contiguous block height.
  54. func (bs *BlockStore) Height() uint32 {
  55. return bs.height
  56. }
  57. func (bs *BlockStore) LoadBlock(height uint32) *Block {
  58. blockBytes := bs.db.Get(calcBlockKey(height))
  59. if blockBytes == nil {
  60. return nil
  61. }
  62. var n int64
  63. var err error
  64. block := ReadBlock(bytes.NewReader(blockBytes), &n, &err)
  65. if err != nil {
  66. Panicf("Error reading block: %v", err)
  67. }
  68. return block
  69. }
  70. // Writes are synchronous and atomic.
  71. func (bs *BlockStore) SaveBlock(block *Block) {
  72. height := block.Height
  73. if height != bs.height+1 {
  74. Panicf("BlockStore can only save contiguous blocks. Wanted %v, got %v", bs.height+1, height)
  75. }
  76. // Save block
  77. blockBytes := BinaryBytes(block)
  78. bs.db.Set(calcBlockKey(height), blockBytes)
  79. // Save new BlockStoreJSON descriptor
  80. BlockStoreJSON{Height: height}.Save(bs.db)
  81. }
  82. //-----------------------------------------------------------------------------
  83. func calcBlockKey(height uint32) []byte {
  84. buf := [9]byte{'B'}
  85. binary.BigEndian.PutUint32(buf[1:9], height)
  86. return buf[:]
  87. }