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.

158 lines
3.5 KiB

  1. package blocks
  2. import (
  3. "bytes"
  4. "errors"
  5. "sync"
  6. "github.com/tendermint/tendermint/merkle"
  7. )
  8. // A collection of block parts.
  9. // Doesn't do any validation.
  10. type BlockPartSet struct {
  11. mtx sync.Mutex
  12. height uint32
  13. total uint16 // total number of parts
  14. numParts uint16 // number of parts in this set
  15. parts []*BlockPart
  16. _block *Block // cache
  17. }
  18. var (
  19. ErrInvalidBlockPartConflict = errors.New("Invalid block part conflict") // Signer signed conflicting parts
  20. )
  21. // parts may be nil if the parts aren't in hand.
  22. func NewBlockPartSet(height uint32, parts []*BlockPart) *BlockPartSet {
  23. bps := &BlockPartSet{
  24. height: height,
  25. parts: parts,
  26. numParts: uint16(len(parts)),
  27. }
  28. if len(parts) > 0 {
  29. bps.total = parts[0].Total
  30. }
  31. return bps
  32. }
  33. func (bps *BlockPartSet) Height() uint32 {
  34. return bps.height
  35. }
  36. func (bps *BlockPartSet) BlockParts() []*BlockPart {
  37. bps.mtx.Lock()
  38. defer bps.mtx.Unlock()
  39. return bps.parts
  40. }
  41. func (bps *BlockPartSet) BitArray() []byte {
  42. bps.mtx.Lock()
  43. defer bps.mtx.Unlock()
  44. if bps.parts == nil {
  45. return nil
  46. }
  47. bitArray := make([]byte, (len(bps.parts)+7)/8)
  48. for i, part := range bps.parts {
  49. if part != nil {
  50. bitArray[i/8] |= 1 << uint(i%8)
  51. }
  52. }
  53. return bitArray
  54. }
  55. // If the part isn't valid, returns an error.
  56. // err can be ErrInvalidBlockPartConflict
  57. // NOTE: Caller must check the signature before adding.
  58. func (bps *BlockPartSet) AddBlockPart(part *BlockPart) (added bool, err error) {
  59. bps.mtx.Lock()
  60. defer bps.mtx.Unlock()
  61. if bps.parts == nil {
  62. // First received part for this round.
  63. bps.parts = make([]*BlockPart, part.Total)
  64. bps.total = uint16(part.Total)
  65. bps.parts[int(part.Index)] = part
  66. bps.numParts++
  67. return true, nil
  68. } else {
  69. // Check part.Index and part.Total
  70. if uint16(part.Index) >= bps.total {
  71. return false, ErrInvalidBlockPartConflict
  72. }
  73. if uint16(part.Total) != bps.total {
  74. return false, ErrInvalidBlockPartConflict
  75. }
  76. // Check for existing parts.
  77. existing := bps.parts[part.Index]
  78. if existing != nil {
  79. if bytes.Equal(existing.Bytes, part.Bytes) {
  80. // Ignore duplicate
  81. return false, nil
  82. } else {
  83. return false, ErrInvalidBlockPartConflict
  84. }
  85. } else {
  86. bps.parts[int(part.Index)] = part
  87. bps.numParts++
  88. return true, nil
  89. }
  90. }
  91. }
  92. func (bps *BlockPartSet) IsComplete() bool {
  93. bps.mtx.Lock()
  94. defer bps.mtx.Unlock()
  95. return bps.total > 0 && bps.total == bps.numParts
  96. }
  97. func (bps *BlockPartSet) Block() *Block {
  98. if !bps.IsComplete() {
  99. return nil
  100. }
  101. bps.mtx.Lock()
  102. defer bps.mtx.Unlock()
  103. if bps._block == nil {
  104. block, err := BlockPartsToBlock(bps.parts)
  105. if err != nil {
  106. panic(err)
  107. }
  108. bps._block = block
  109. }
  110. return bps._block
  111. }
  112. func (bps *BlockPartSet) Hash() []byte {
  113. if !bps.IsComplete() {
  114. panic("Cannot get hash of an incomplete BlockPartSet")
  115. }
  116. hashes := [][]byte{}
  117. for _, part := range bps.parts {
  118. partHash := part.Hash()
  119. hashes = append(hashes, partHash)
  120. }
  121. return merkle.HashFromByteSlices(hashes)
  122. }
  123. // The proposal hash includes both the block hash
  124. // as well as the BlockPartSet merkle hash.
  125. func (bps *BlockPartSet) ProposalHash() []byte {
  126. bpsHash := bps.Hash()
  127. blockHash := bps.Block().Hash()
  128. return merkle.HashFromByteSlices([][]byte{bpsHash, blockHash})
  129. }
  130. //-----------------------------------------------------------------------------
  131. func BlockPartsToBlock(parts []*BlockPart) (*Block, error) {
  132. blockBytes := []byte{}
  133. for _, part := range parts {
  134. blockBytes = append(blockBytes, part.Bytes...)
  135. }
  136. var n int64
  137. var err error
  138. block := ReadBlock(bytes.NewReader(blockBytes), &n, &err)
  139. return block, err
  140. }