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.

204 lines
5.1 KiB

10 years ago
  1. package blocks
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "encoding/json"
  6. "io"
  7. . "github.com/tendermint/tendermint/binary"
  8. . "github.com/tendermint/tendermint/common"
  9. db_ "github.com/tendermint/tendermint/db"
  10. )
  11. //-----------------------------------------------------------------------------
  12. /*
  13. Simple low level store for blocks, which is actually stored as separte parts (wire format).
  14. */
  15. type BlockStore struct {
  16. height uint32
  17. db db_.DB
  18. }
  19. func NewBlockStore(db db_.DB) *BlockStore {
  20. bsjson := LoadBlockStoreJSON(db)
  21. return &BlockStore{
  22. height: bsjson.Height,
  23. db: db,
  24. }
  25. }
  26. // Height() returns the last known contiguous block height.
  27. func (bs *BlockStore) Height() uint32 {
  28. return bs.height
  29. }
  30. func (bs *BlockStore) GetReader(key []byte) io.Reader {
  31. bytez := bs.db.Get(key)
  32. if bytez == nil {
  33. return nil
  34. }
  35. return bytes.NewReader(bytez)
  36. }
  37. func (bs *BlockStore) LoadBlock(height uint32) *Block {
  38. var n int64
  39. var err error
  40. meta := ReadBlockMeta(bs.GetReader(calcBlockMetaKey(height)), &n, &err)
  41. if err != nil {
  42. Panicf("Error reading block meta: %v", err)
  43. }
  44. bytez := []byte{}
  45. for i := uint16(0); i < meta.Parts.Total; i++ {
  46. part := bs.LoadBlockPart(height, i)
  47. bytez = append(bytez, part.Bytes...)
  48. }
  49. block := ReadBlock(bytes.NewReader(bytez), &n, &err)
  50. if err != nil {
  51. Panicf("Error reading block: %v", err)
  52. }
  53. return block
  54. }
  55. func (bs *BlockStore) LoadBlockPart(height uint32, index uint16) *Part {
  56. var n int64
  57. var err error
  58. part := ReadPart(bs.GetReader(calcBlockPartKey(height, index)), &n, &err)
  59. if err != nil {
  60. Panicf("Error reading block part: %v", err)
  61. }
  62. return part
  63. }
  64. func (bs *BlockStore) LoadBlockMeta(height uint32) *BlockMeta {
  65. var n int64
  66. var err error
  67. meta := ReadBlockMeta(bs.GetReader(calcBlockMetaKey(height)), &n, &err)
  68. if err != nil {
  69. Panicf("Error reading block meta: %v", err)
  70. }
  71. return meta
  72. }
  73. func (bs *BlockStore) LoadBlockValidation(height uint32) *Validation {
  74. var n int64
  75. var err error
  76. validation := ReadValidation(bs.GetReader(calcBlockValidationKey(height)), &n, &err)
  77. if err != nil {
  78. Panicf("Error reading validation: %v", err)
  79. }
  80. return validation
  81. }
  82. func (bs *BlockStore) SaveBlock(block *Block, blockParts *PartSet) {
  83. height := block.Height
  84. if height != bs.height+1 {
  85. Panicf("BlockStore can only save contiguous blocks. Wanted %v, got %v", bs.height+1, height)
  86. }
  87. if !blockParts.IsComplete() {
  88. Panicf("BlockStore can only save complete block part sets")
  89. }
  90. meta := &BlockMeta{
  91. Hash: block.Hash(),
  92. Parts: blockParts.Header(),
  93. Header: block.Header,
  94. }
  95. // Save block meta
  96. metaBytes := BinaryBytes(meta)
  97. bs.db.Set(calcBlockMetaKey(height), metaBytes)
  98. // Save block parts
  99. for i := uint16(0); i < blockParts.Total(); i++ {
  100. bs.saveBlockPart(height, i, blockParts.GetPart(i))
  101. }
  102. // Save block validation (duplicate and separate)
  103. validationBytes := BinaryBytes(block.Validation)
  104. bs.db.Set(calcBlockValidationKey(height), validationBytes)
  105. // Save new BlockStoreJSON descriptor
  106. BlockStoreJSON{Height: height}.Save(bs.db)
  107. // Done!
  108. bs.height = height
  109. }
  110. func (bs *BlockStore) saveBlockPart(height uint32, index uint16, part *Part) {
  111. if height != bs.height+1 {
  112. Panicf("BlockStore can only save contiguous blocks. Wanted %v, got %v", bs.height+1, height)
  113. }
  114. partBytes := BinaryBytes(part)
  115. bs.db.Set(calcBlockPartKey(height, index), partBytes)
  116. }
  117. //-----------------------------------------------------------------------------
  118. type BlockMeta struct {
  119. Hash []byte // The BlockHash
  120. Parts PartSetHeader // The PartSetHeader, for transfer
  121. Header *Header // The block's Header
  122. }
  123. func ReadBlockMeta(r io.Reader, n *int64, err *error) *BlockMeta {
  124. return &BlockMeta{
  125. Hash: ReadByteSlice(r, n, err),
  126. Parts: ReadPartSetHeader(r, n, err),
  127. Header: ReadHeader(r, n, err),
  128. }
  129. }
  130. func (bm *BlockMeta) WriteTo(w io.Writer) (n int64, err error) {
  131. WriteByteSlice(w, bm.Hash, &n, &err)
  132. WriteBinary(w, bm.Parts, &n, &err)
  133. WriteBinary(w, bm.Header, &n, &err)
  134. return
  135. }
  136. //-----------------------------------------------------------------------------
  137. func calcBlockMetaKey(height uint32) []byte {
  138. buf := [5]byte{'H'}
  139. binary.BigEndian.PutUint32(buf[1:5], height)
  140. return buf[:]
  141. }
  142. func calcBlockPartKey(height uint32, partIndex uint16) []byte {
  143. buf := [7]byte{'P'}
  144. binary.BigEndian.PutUint32(buf[1:5], height)
  145. binary.BigEndian.PutUint16(buf[5:7], partIndex)
  146. return buf[:]
  147. }
  148. func calcBlockValidationKey(height uint32) []byte {
  149. buf := [5]byte{'V'}
  150. binary.BigEndian.PutUint32(buf[1:5], height)
  151. return buf[:]
  152. }
  153. //-----------------------------------------------------------------------------
  154. var blockStoreKey = []byte("blockStore")
  155. type BlockStoreJSON struct {
  156. Height uint32
  157. }
  158. func (bsj BlockStoreJSON) Save(db db_.DB) {
  159. bytes, err := json.Marshal(bsj)
  160. if err != nil {
  161. Panicf("Could not marshal state bytes: %v", err)
  162. }
  163. db.Set(blockStoreKey, bytes)
  164. }
  165. func LoadBlockStoreJSON(db db_.DB) BlockStoreJSON {
  166. bytes := db.Get(blockStoreKey)
  167. if bytes == nil {
  168. return BlockStoreJSON{
  169. Height: 0,
  170. }
  171. }
  172. bsj := BlockStoreJSON{}
  173. err := json.Unmarshal(bytes, &bsj)
  174. if err != nil {
  175. Panicf("Could not unmarshal bytes: %X", bytes)
  176. }
  177. return bsj
  178. }