2015-03-22 19:00:08 -07:00
|
|
|
package types
|
2014-09-14 15:37:32 -07:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"errors"
|
2014-10-17 01:01:59 -07:00
|
|
|
"fmt"
|
2015-01-14 20:34:53 -08:00
|
|
|
"io"
|
2014-09-14 15:37:32 -07:00
|
|
|
"sync"
|
|
|
|
|
2015-12-17 13:27:30 -08:00
|
|
|
"golang.org/x/crypto/ripemd160"
|
2015-07-10 12:15:46 -07:00
|
|
|
|
2015-10-22 17:39:06 -07:00
|
|
|
. "github.com/tendermint/go-common"
|
|
|
|
"github.com/tendermint/go-merkle"
|
2015-11-10 13:10:43 -08:00
|
|
|
"github.com/tendermint/go-wire"
|
2014-09-14 15:37:32 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2016-03-10 17:20:07 -08:00
|
|
|
partSize = 65536 // 64KB ... 4096 // 4KB
|
2014-09-14 15:37:32 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
ErrPartSetUnexpectedIndex = errors.New("Error part set unexpected index")
|
2015-06-18 20:19:39 -07:00
|
|
|
ErrPartSetInvalidProof = errors.New("Error part set invalid proof")
|
2014-09-14 15:37:32 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
type Part struct {
|
2015-12-10 11:09:25 -08:00
|
|
|
Index int `json:"index"`
|
2015-06-18 20:19:39 -07:00
|
|
|
Bytes []byte `json:"bytes"`
|
2015-12-10 11:09:25 -08:00
|
|
|
Proof merkle.SimpleProof `json:"proof"`
|
2014-09-14 15:37:32 -07:00
|
|
|
|
|
|
|
// Cache
|
|
|
|
hash []byte
|
|
|
|
}
|
|
|
|
|
2014-10-30 03:32:09 -07:00
|
|
|
func (part *Part) Hash() []byte {
|
|
|
|
if part.hash != nil {
|
|
|
|
return part.hash
|
2014-09-14 15:37:32 -07:00
|
|
|
} else {
|
2015-07-10 12:15:46 -07:00
|
|
|
hasher := ripemd160.New()
|
2015-07-19 16:42:52 -07:00
|
|
|
hasher.Write(part.Bytes) // doesn't err
|
2014-10-30 03:32:09 -07:00
|
|
|
part.hash = hasher.Sum(nil)
|
|
|
|
return part.hash
|
2014-09-14 15:37:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-30 03:32:09 -07:00
|
|
|
func (part *Part) String() string {
|
2014-12-23 01:35:54 -08:00
|
|
|
return part.StringIndented("")
|
2014-10-17 01:01:59 -07:00
|
|
|
}
|
|
|
|
|
2014-12-23 01:35:54 -08:00
|
|
|
func (part *Part) StringIndented(indent string) string {
|
2015-12-10 11:09:25 -08:00
|
|
|
return fmt.Sprintf(`Part{#%v
|
2015-12-09 17:09:06 -08:00
|
|
|
%s Bytes: %X...
|
2015-12-10 11:09:25 -08:00
|
|
|
%s Proof: %v
|
2014-10-17 01:01:59 -07:00
|
|
|
%s}`,
|
2015-12-10 11:09:25 -08:00
|
|
|
part.Index,
|
2015-12-09 17:09:06 -08:00
|
|
|
indent, Fingerprint(part.Bytes),
|
2015-12-10 11:09:25 -08:00
|
|
|
indent, part.Proof.StringIndented(indent+" "),
|
2014-10-17 01:01:59 -07:00
|
|
|
indent)
|
|
|
|
}
|
|
|
|
|
2014-09-14 15:37:32 -07:00
|
|
|
//-------------------------------------
|
|
|
|
|
2014-10-30 03:32:09 -07:00
|
|
|
type PartSetHeader struct {
|
2015-06-25 20:28:34 -07:00
|
|
|
Total int `json:"total"`
|
2015-05-01 17:26:49 -07:00
|
|
|
Hash []byte `json:"hash"`
|
2014-10-30 03:32:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (psh PartSetHeader) String() string {
|
2014-11-05 03:08:29 -08:00
|
|
|
return fmt.Sprintf("PartSet{T:%v %X}", psh.Total, Fingerprint(psh.Hash))
|
2014-10-30 03:32:09 -07:00
|
|
|
}
|
|
|
|
|
2014-11-03 15:50:23 -08:00
|
|
|
func (psh PartSetHeader) IsZero() bool {
|
|
|
|
return psh.Total == 0
|
|
|
|
}
|
|
|
|
|
2014-10-30 03:32:09 -07:00
|
|
|
func (psh PartSetHeader) Equals(other PartSetHeader) bool {
|
2014-10-31 18:35:38 -07:00
|
|
|
return psh.Total == other.Total && bytes.Equal(psh.Hash, other.Hash)
|
2014-10-30 03:32:09 -07:00
|
|
|
}
|
|
|
|
|
2015-11-10 13:10:43 -08:00
|
|
|
func (psh PartSetHeader) WriteSignBytes(w io.Writer, n *int, err *error) {
|
2015-07-25 15:45:45 -07:00
|
|
|
wire.WriteTo([]byte(Fmt(`{"hash":"%X","total":%v}`, psh.Hash, psh.Total)), w, n, err)
|
2015-04-27 20:55:28 -07:00
|
|
|
}
|
|
|
|
|
2014-10-30 03:32:09 -07:00
|
|
|
//-------------------------------------
|
|
|
|
|
2014-09-14 15:37:32 -07:00
|
|
|
type PartSet struct {
|
2015-06-25 20:28:34 -07:00
|
|
|
total int
|
2014-10-31 18:35:38 -07:00
|
|
|
hash []byte
|
2014-09-14 15:37:32 -07:00
|
|
|
|
|
|
|
mtx sync.Mutex
|
|
|
|
parts []*Part
|
2015-05-05 22:53:06 -07:00
|
|
|
partsBitArray *BitArray
|
2015-06-25 20:28:34 -07:00
|
|
|
count int
|
2014-09-14 15:37:32 -07:00
|
|
|
}
|
|
|
|
|
2014-12-23 01:35:54 -08:00
|
|
|
// Returns an immutable, full PartSet from the data bytes.
|
|
|
|
// The data bytes are split into "partSize" chunks, and merkle tree computed.
|
2014-09-14 15:37:32 -07:00
|
|
|
func NewPartSetFromData(data []byte) *PartSet {
|
|
|
|
// divide data into 4kb parts.
|
|
|
|
total := (len(data) + partSize - 1) / partSize
|
|
|
|
parts := make([]*Part, total)
|
|
|
|
parts_ := make([]merkle.Hashable, total)
|
2015-06-25 20:28:34 -07:00
|
|
|
partsBitArray := NewBitArray(total)
|
2014-09-14 15:37:32 -07:00
|
|
|
for i := 0; i < total; i++ {
|
|
|
|
part := &Part{
|
2015-12-10 11:09:25 -08:00
|
|
|
Index: i,
|
2014-09-14 15:37:32 -07:00
|
|
|
Bytes: data[i*partSize : MinInt(len(data), (i+1)*partSize)],
|
|
|
|
}
|
|
|
|
parts[i] = part
|
|
|
|
parts_[i] = part
|
2015-06-25 20:28:34 -07:00
|
|
|
partsBitArray.SetIndex(i, true)
|
2014-09-14 15:37:32 -07:00
|
|
|
}
|
2015-06-18 20:19:39 -07:00
|
|
|
// Compute merkle proofs
|
2015-12-10 11:09:25 -08:00
|
|
|
root, proofs := merkle.SimpleProofsFromHashables(parts_)
|
2014-09-14 15:37:32 -07:00
|
|
|
for i := 0; i < total; i++ {
|
2015-06-18 20:19:39 -07:00
|
|
|
parts[i].Proof = *proofs[i]
|
2014-09-14 15:37:32 -07:00
|
|
|
}
|
|
|
|
return &PartSet{
|
2015-06-25 20:28:34 -07:00
|
|
|
total: total,
|
2015-12-10 11:09:25 -08:00
|
|
|
hash: root,
|
2014-09-14 15:37:32 -07:00
|
|
|
parts: parts,
|
|
|
|
partsBitArray: partsBitArray,
|
2015-06-25 20:28:34 -07:00
|
|
|
count: total,
|
2014-09-14 15:37:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns an empty PartSet ready to be populated.
|
2014-10-30 03:32:09 -07:00
|
|
|
func NewPartSetFromHeader(header PartSetHeader) *PartSet {
|
2014-09-14 15:37:32 -07:00
|
|
|
return &PartSet{
|
2014-10-30 03:32:09 -07:00
|
|
|
total: header.Total,
|
2014-10-31 18:35:38 -07:00
|
|
|
hash: header.Hash,
|
2014-10-30 03:32:09 -07:00
|
|
|
parts: make([]*Part, header.Total),
|
2015-06-25 20:28:34 -07:00
|
|
|
partsBitArray: NewBitArray(header.Total),
|
2014-09-14 15:37:32 -07:00
|
|
|
count: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-30 03:32:09 -07:00
|
|
|
func (ps *PartSet) Header() PartSetHeader {
|
|
|
|
if ps == nil {
|
|
|
|
return PartSetHeader{}
|
|
|
|
} else {
|
|
|
|
return PartSetHeader{
|
|
|
|
Total: ps.total,
|
2014-10-31 18:35:38 -07:00
|
|
|
Hash: ps.hash,
|
2014-10-30 03:32:09 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-03 15:50:23 -08:00
|
|
|
func (ps *PartSet) HasHeader(header PartSetHeader) bool {
|
|
|
|
if ps == nil {
|
|
|
|
return false
|
|
|
|
} else {
|
|
|
|
return ps.Header().Equals(header)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-05 22:53:06 -07:00
|
|
|
func (ps *PartSet) BitArray() *BitArray {
|
2014-09-14 15:37:32 -07:00
|
|
|
ps.mtx.Lock()
|
|
|
|
defer ps.mtx.Unlock()
|
|
|
|
return ps.partsBitArray.Copy()
|
|
|
|
}
|
|
|
|
|
2014-10-30 03:32:09 -07:00
|
|
|
func (ps *PartSet) Hash() []byte {
|
2014-10-21 01:18:46 -07:00
|
|
|
if ps == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2014-10-30 03:32:09 -07:00
|
|
|
return ps.hash
|
2014-09-14 15:37:32 -07:00
|
|
|
}
|
|
|
|
|
2014-10-30 03:32:09 -07:00
|
|
|
func (ps *PartSet) HashesTo(hash []byte) bool {
|
2014-10-26 13:26:27 -07:00
|
|
|
if ps == nil {
|
|
|
|
return false
|
|
|
|
}
|
2014-10-30 03:32:09 -07:00
|
|
|
return bytes.Equal(ps.hash, hash)
|
2014-10-26 13:26:27 -07:00
|
|
|
}
|
|
|
|
|
2015-06-25 20:28:34 -07:00
|
|
|
func (ps *PartSet) Count() int {
|
2014-10-18 01:42:33 -07:00
|
|
|
if ps == nil {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return ps.count
|
|
|
|
}
|
|
|
|
|
2015-06-25 20:28:34 -07:00
|
|
|
func (ps *PartSet) Total() int {
|
2014-09-14 15:37:32 -07:00
|
|
|
if ps == nil {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return ps.total
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ps *PartSet) AddPart(part *Part) (bool, error) {
|
|
|
|
ps.mtx.Lock()
|
|
|
|
defer ps.mtx.Unlock()
|
|
|
|
|
|
|
|
// Invalid part index
|
2015-12-10 11:09:25 -08:00
|
|
|
if part.Index >= ps.total {
|
2014-09-14 15:37:32 -07:00
|
|
|
return false, ErrPartSetUnexpectedIndex
|
|
|
|
}
|
|
|
|
|
|
|
|
// If part already exists, return false.
|
2015-12-10 11:09:25 -08:00
|
|
|
if ps.parts[part.Index] != nil {
|
2014-09-14 15:37:32 -07:00
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
2015-06-18 20:19:39 -07:00
|
|
|
// Check hash proof
|
2016-03-10 17:20:07 -08:00
|
|
|
// TODO: minor gains for not checking part sets we made
|
2015-12-10 11:09:25 -08:00
|
|
|
if !part.Proof.Verify(part.Index, ps.total, part.Hash(), ps.Hash()) {
|
2015-06-18 20:19:39 -07:00
|
|
|
return false, ErrPartSetInvalidProof
|
2014-09-14 15:37:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add part
|
2015-12-10 11:09:25 -08:00
|
|
|
ps.parts[part.Index] = part
|
|
|
|
ps.partsBitArray.SetIndex(part.Index, true)
|
2014-09-14 15:37:32 -07:00
|
|
|
ps.count++
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2015-06-25 20:28:34 -07:00
|
|
|
func (ps *PartSet) GetPart(index int) *Part {
|
2014-09-14 15:37:32 -07:00
|
|
|
ps.mtx.Lock()
|
|
|
|
defer ps.mtx.Unlock()
|
|
|
|
return ps.parts[index]
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ps *PartSet) IsComplete() bool {
|
|
|
|
return ps.count == ps.total
|
|
|
|
}
|
|
|
|
|
2015-01-14 20:34:53 -08:00
|
|
|
func (ps *PartSet) GetReader() io.Reader {
|
2014-09-14 15:37:32 -07:00
|
|
|
if !ps.IsComplete() {
|
2015-07-19 16:42:52 -07:00
|
|
|
PanicSanity("Cannot GetReader() on incomplete PartSet")
|
2014-09-14 15:37:32 -07:00
|
|
|
}
|
|
|
|
buf := []byte{}
|
|
|
|
for _, part := range ps.parts {
|
|
|
|
buf = append(buf, part.Bytes...)
|
|
|
|
}
|
|
|
|
return bytes.NewReader(buf)
|
|
|
|
}
|
2014-10-18 01:42:33 -07:00
|
|
|
|
2014-12-23 01:35:54 -08:00
|
|
|
func (ps *PartSet) StringShort() string {
|
2014-10-18 01:42:33 -07:00
|
|
|
if ps == nil {
|
|
|
|
return "nil-PartSet"
|
|
|
|
} else {
|
|
|
|
return fmt.Sprintf("(%v of %v)", ps.Count(), ps.Total())
|
|
|
|
}
|
|
|
|
}
|