diff --git a/account/account.go b/account/account.go index 081dc1063..4105588f5 100644 --- a/account/account.go +++ b/account/account.go @@ -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)) } //----------------------------------------------------------------------------- diff --git a/consensus/reactor.go b/consensus/reactor.go index 2cddd51ae..8671123ca 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -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)) diff --git a/merkle/simple_tree.go b/merkle/simple_tree.go index 2f05f8bb5..73465008e 100644 --- a/merkle/simple_tree.go +++ b/merkle/simple_tree.go @@ -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 { diff --git a/state/state.go b/state/state.go index a36fbff21..fcb408502 100644 --- a/state/state.go +++ b/state/state.go @@ -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. diff --git a/state/validator_set.go b/state/validator_set.go index a7cede7cc..5bfc76f96 100644 --- a/state/validator_set.go +++ b/state/validator_set.go @@ -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) { diff --git a/types/block.go b/types/block.go index eef5fe89a..8411edad1 100644 --- a/types/block.go +++ b/types/block.go @@ -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 } diff --git a/types/part_set.go b/types/part_set.go index 0868724e9..8c5de3be4 100644 --- a/types/part_set.go +++ b/types/part_set.go @@ -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 } diff --git a/types/part_set_test.go b/types/part_set_test.go index d27a85c4d..88cf2d585 100644 --- a/types/part_set_test.go +++ b/types/part_set_test.go @@ -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.")