2018-06-20 15:30:44 -07:00
|
|
|
package merkle
|
|
|
|
|
|
|
|
import (
|
2018-08-16 08:52:59 -07:00
|
|
|
"math/bits"
|
|
|
|
|
2018-06-20 21:05:38 -07:00
|
|
|
"github.com/tendermint/tendermint/crypto/tmhash"
|
2018-06-20 15:30:44 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
// SimpleHashFromTwoHashes is the basic operation of the Merkle tree: Hash(left | right).
|
|
|
|
func SimpleHashFromTwoHashes(left, right []byte) []byte {
|
|
|
|
var hasher = tmhash.New()
|
2018-08-30 21:38:25 -07:00
|
|
|
_, err := hasher.Write(InnerHashPrefix)
|
2018-08-16 08:52:59 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
_, err = hasher.Write(left)
|
2018-06-20 15:30:44 -07:00
|
|
|
if err != nil {
|
2018-06-29 12:17:26 +04:00
|
|
|
panic(err)
|
|
|
|
}
|
2018-08-16 08:52:59 -07:00
|
|
|
_, err = hasher.Write(right)
|
2018-06-20 15:30:44 -07:00
|
|
|
if err != nil {
|
2018-06-29 12:17:26 +04:00
|
|
|
panic(err)
|
|
|
|
}
|
2018-06-20 15:30:44 -07:00
|
|
|
return hasher.Sum(nil)
|
|
|
|
}
|
|
|
|
|
2018-08-16 08:52:59 -07:00
|
|
|
// SimpleHashFromByteSlices computes a Merkle tree from items that are byte slices.
|
|
|
|
func SimpleHashFromByteSlices(items [][]byte) []byte {
|
2018-06-20 15:30:44 -07:00
|
|
|
hashes := make([][]byte, len(items))
|
|
|
|
for i, item := range items {
|
2018-08-16 08:52:59 -07:00
|
|
|
hash := tmhash.Sum(append([]byte{0}, item...))
|
2018-06-20 15:30:44 -07:00
|
|
|
hashes[i] = hash
|
|
|
|
}
|
|
|
|
return simpleHashFromHashes(hashes)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SimpleHashFromMap computes a Merkle tree from sorted map.
|
|
|
|
// Like calling SimpleHashFromHashers with
|
|
|
|
// `item = []byte(Hash(key) | Hash(value))`,
|
|
|
|
// sorted by `item`.
|
|
|
|
func SimpleHashFromMap(m map[string]Hasher) []byte {
|
|
|
|
sm := newSimpleMap()
|
|
|
|
for k, v := range m {
|
|
|
|
sm.Set(k, v)
|
|
|
|
}
|
|
|
|
return sm.Hash()
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
|
|
|
|
// Expects hashes!
|
|
|
|
func simpleHashFromHashes(hashes [][]byte) []byte {
|
|
|
|
// Recursive impl.
|
|
|
|
switch len(hashes) {
|
|
|
|
case 0:
|
|
|
|
return nil
|
|
|
|
case 1:
|
|
|
|
return hashes[0]
|
|
|
|
default:
|
2018-08-16 08:52:59 -07:00
|
|
|
k := getSplitPoint(len(hashes))
|
|
|
|
left := simpleHashFromHashes(hashes[:k])
|
|
|
|
right := simpleHashFromHashes(hashes[k:])
|
2018-06-20 15:30:44 -07:00
|
|
|
return SimpleHashFromTwoHashes(left, right)
|
|
|
|
}
|
|
|
|
}
|
2018-08-16 08:52:59 -07:00
|
|
|
|
|
|
|
func getSplitPoint(length int) int {
|
|
|
|
if length < 1 {
|
|
|
|
panic("Trying to split a tree with size < 1")
|
|
|
|
}
|
|
|
|
uLength := uint(length)
|
|
|
|
bitlen := bits.Len(uLength)
|
|
|
|
k := 1 << uint(bitlen-1)
|
|
|
|
if k == length {
|
|
|
|
k >>= 1
|
|
|
|
}
|
|
|
|
return k
|
|
|
|
}
|