Browse Source

Fix usage of SimpleProof for PartSet

pull/95/head
Jae Kwon 9 years ago
parent
commit
1a652a1cbb
8 changed files with 54 additions and 42 deletions
  1. +1
    -1
      account/account.go
  2. +2
    -2
      consensus/reactor.go
  3. +26
    -5
      merkle/simple_tree.go
  4. +1
    -1
      state/state.go
  5. +1
    -1
      state/validator_set.go
  6. +3
    -3
      types/block.go
  7. +18
    -27
      types/part_set.go
  8. +2
    -2
      types/part_set_test.go

+ 1
- 1
account/account.go View File

@ -27,7 +27,7 @@ func SignBytes(chainID string, o Signable) []byte {
// HashSignBytes is a convenience method for getting the hash of the bytes of a signable
func HashSignBytes(chainID string, o Signable) []byte {
return merkle.HashFromBinary(SignBytes(chainID, o))
return merkle.SimpleHashFromBinary(SignBytes(chainID, o))
}
//-----------------------------------------------------------------------------


+ 2
- 2
consensus/reactor.go View File

@ -167,10 +167,10 @@ func (conR *ConsensusReactor) Receive(chId byte, peer *p2p.Peer, msgBytes []byte
case *PartMessage:
if msg.Type == partTypeProposalBlock {
ps.SetHasProposalBlockPart(msg.Height, msg.Round, msg.Part.Index)
ps.SetHasProposalBlockPart(msg.Height, msg.Round, msg.Part.Proof.Index)
_, err = conR.conS.AddProposalBlockPart(msg.Height, msg.Round, msg.Part)
} else if msg.Type == partTypeProposalPOL {
ps.SetHasProposalPOLPart(msg.Height, msg.Round, msg.Part.Index)
ps.SetHasProposalPOLPart(msg.Height, msg.Round, msg.Part.Proof.Index)
_, err = conR.conS.AddProposalPOLPart(msg.Height, msg.Round, msg.Part)
} else {
log.Warn(Fmt("Unknown part type %v", msg.Type))


+ 26
- 5
merkle/simple_tree.go View File

@ -27,6 +27,7 @@ package merkle
import (
"bytes"
"crypto/sha256"
"fmt"
"github.com/tendermint/tendermint/binary"
)
@ -89,11 +90,11 @@ func SimpleHashFromHashables(items []Hashable) []byte {
//--------------------------------------------------------------------------------
type SimpleProof struct {
Index uint
Total uint
LeafHash []byte
InnerHashes [][]byte // Hashes from leaf's sibling to a root's child.
RootHash []byte
Index uint `json:"index"`
Total uint `json:"total"`
LeafHash []byte `json:"leaf_hash"`
InnerHashes [][]byte `json:"inner_hashes"` // Hashes from leaf's sibling to a root's child.
RootHash []byte `json:"root_hash"`
}
// proofs[0] is the proof for items[0].
@ -131,6 +132,26 @@ func (sp *SimpleProof) Verify(leafHash []byte, rootHash []byte) bool {
return true
}
func (sp *SimpleProof) String() string {
return sp.StringIndented("")
}
func (sp *SimpleProof) StringIndented(indent string) string {
return fmt.Sprintf(`SimpleProof{
%s Index: %v
%s Total: %v
%s LeafHash: %X
%s InnerHashes: %X
%s RootHash: %X
%s}`,
indent, sp.Index,
indent, sp.Total,
indent, sp.LeafHash,
indent, sp.InnerHashes,
indent, sp.RootHash,
indent)
}
// Use the leafHash and innerHashes to get the root merkle hash.
// If the length of the innerHashes slice isn't exactly correct, the result is nil.
func computeHashFromInnerHashes(index uint, total uint, leafHash []byte, innerHashes [][]byte) []byte {


+ 1
- 1
state/state.go View File

@ -126,7 +126,7 @@ func (s *State) Hash() []byte {
s.validatorInfos,
s.nameReg,
}
return merkle.HashFromHashables(hashables)
return merkle.SimpleHashFromHashables(hashables)
}
// Mutates the block in place and updates it with new state hash.


+ 1
- 1
state/validator_set.go View File

@ -129,7 +129,7 @@ func (valSet *ValidatorSet) Hash() []byte {
for i, val := range valSet.Validators {
hashables[i] = val
}
return merkle.HashFromHashables(hashables)
return merkle.SimpleHashFromHashables(hashables)
}
func (valSet *ValidatorSet) Add(val *Validator) (added bool) {


+ 3
- 3
types/block.go View File

@ -72,7 +72,7 @@ func (b *Block) Hash() []byte {
// Merkle hash from subhashes.
hashes := [][]byte{hashHeader, hashValidation, hashData}
return merkle.HashFromHashes(hashes)
return merkle.SimpleHashFromHashes(hashes)
}
func (b *Block) MakePartSet() *PartSet {
@ -233,7 +233,7 @@ func (v *Validation) Hash() []byte {
for i, commit := range v.Commits {
bs[i] = commit
}
v.hash = merkle.HashFromBinaries(bs)
v.hash = merkle.SimpleHashFromBinaries(bs)
}
return v.hash
}
@ -278,7 +278,7 @@ func (data *Data) Hash() []byte {
for i, tx := range data.Txs {
bs[i] = account.SignBytes(config.GetString("chain_id"), tx)
}
data.hash = merkle.HashFromBinaries(bs)
data.hash = merkle.SimpleHashFromBinaries(bs)
}
return data.hash
}


+ 18
- 27
types/part_set.go View File

@ -6,7 +6,6 @@ import (
"errors"
"fmt"
"io"
"strings"
"sync"
"github.com/tendermint/tendermint/binary"
@ -20,13 +19,12 @@ const (
var (
ErrPartSetUnexpectedIndex = errors.New("Error part set unexpected index")
ErrPartSetInvalidTrail = errors.New("Error part set invalid trail")
ErrPartSetInvalidProof = errors.New("Error part set invalid proof")
)
type Part struct {
Index uint `json:"index"`
Trail [][]byte `json:"trail"`
Bytes []byte `json:"bytes"`
Proof merkle.SimpleProof `json:"proof"`
Bytes []byte `json:"bytes"`
// Cache
hash []byte
@ -51,18 +49,12 @@ func (part *Part) String() string {
}
func (part *Part) StringIndented(indent string) string {
trailStrings := make([]string, len(part.Trail))
for i, hash := range part.Trail {
trailStrings[i] = fmt.Sprintf("%X", hash)
}
return fmt.Sprintf(`Part{
%s Index: %v
%s Trail:
%s %v
%s Proof: %v
%s Bytes: %X
%s}`,
indent, part.Index,
indent,
indent, strings.Join(trailStrings, "\n"+indent+" "),
indent, part.Proof.StringIndented(indent+" "),
indent, part.Bytes,
indent)
}
@ -111,21 +103,20 @@ func NewPartSetFromData(data []byte) *PartSet {
partsBitArray := NewBitArray(uint(total))
for i := 0; i < total; i++ {
part := &Part{
Index: uint(i),
Bytes: data[i*partSize : MinInt(len(data), (i+1)*partSize)],
}
parts[i] = part
parts_[i] = part
partsBitArray.SetIndex(uint(i), true)
}
// Compute merkle trails
trails, rootTrail := merkle.HashTrailsFromHashables(parts_)
// Compute merkle proofs
proofs := merkle.SimpleProofsFromHashables(parts_)
for i := 0; i < total; i++ {
parts[i].Trail = trails[i].Flatten()
parts[i].Proof = *proofs[i]
}
return &PartSet{
total: uint(total),
hash: rootTrail.Hash,
hash: proofs[0].RootHash,
parts: parts,
partsBitArray: partsBitArray,
count: uint(total),
@ -201,23 +192,23 @@ func (ps *PartSet) AddPart(part *Part) (bool, error) {
defer ps.mtx.Unlock()
// Invalid part index
if part.Index >= ps.total {
if part.Proof.Index >= ps.total {
return false, ErrPartSetUnexpectedIndex
}
// If part already exists, return false.
if ps.parts[part.Index] != nil {
if ps.parts[part.Proof.Index] != nil {
return false, nil
}
// Check hash trail
if !merkle.VerifyHashTrail(uint(part.Index), uint(ps.total), part.Hash(), part.Trail, ps.hash) {
return false, ErrPartSetInvalidTrail
// Check hash proof
if !part.Proof.Verify(part.Hash(), ps.Hash()) {
return false, ErrPartSetInvalidProof
}
// Add part
ps.parts[part.Index] = part
ps.partsBitArray.SetIndex(uint(part.Index), true)
ps.parts[part.Proof.Index] = part
ps.partsBitArray.SetIndex(uint(part.Proof.Index), true)
ps.count++
return true, nil
}


+ 2
- 2
types/part_set_test.go View File

@ -58,7 +58,7 @@ func TestBasicPartSet(t *testing.T) {
}
func TestWrongTrail(t *testing.T) {
func TestWrongProof(t *testing.T) {
// Construct random data of size partSize * 100
data := RandBytes(partSize * 100)
@ -69,7 +69,7 @@ func TestWrongTrail(t *testing.T) {
// Test adding a part with wrong trail.
part := partSet.GetPart(0)
part.Trail[0][0] += byte(0x01)
part.Proof.InnerHashes[0][0] += byte(0x01)
added, err := partSet2.AddPart(part)
if added || err == nil {
t.Errorf("Expected to fail adding a part with bad trail.")


Loading…
Cancel
Save