github.com/tendermint/tmlibs@v0.9.0/merkle/simple_tree.go (about) 1 /* 2 Computes a deterministic minimal height merkle tree hash. 3 If the number of items is not a power of two, some leaves 4 will be at different levels. Tries to keep both sides of 5 the tree the same size, but the left may be one greater. 6 7 Use this for short deterministic trees, such as the validator list. 8 For larger datasets, use IAVLTree. 9 10 * 11 / \ 12 / \ 13 / \ 14 / \ 15 * * 16 / \ / \ 17 / \ / \ 18 / \ / \ 19 * * * h6 20 / \ / \ / \ 21 h0 h1 h2 h3 h4 h5 22 23 */ 24 25 package merkle 26 27 import ( 28 "github.com/tendermint/tmlibs/merkle/tmhash" 29 ) 30 31 func SimpleHashFromTwoHashes(left []byte, right []byte) []byte { 32 var hasher = tmhash.New() 33 err := encodeByteSlice(hasher, left) 34 if err != nil { 35 panic(err) 36 } 37 err = encodeByteSlice(hasher, right) 38 if err != nil { 39 panic(err) 40 } 41 return hasher.Sum(nil) 42 } 43 44 func SimpleHashFromHashes(hashes [][]byte) []byte { 45 // Recursive impl. 46 switch len(hashes) { 47 case 0: 48 return nil 49 case 1: 50 return hashes[0] 51 default: 52 left := SimpleHashFromHashes(hashes[:(len(hashes)+1)/2]) 53 right := SimpleHashFromHashes(hashes[(len(hashes)+1)/2:]) 54 return SimpleHashFromTwoHashes(left, right) 55 } 56 } 57 58 // NOTE: Do not implement this, use SimpleHashFromByteslices instead. 59 // type Byteser interface { Bytes() []byte } 60 // func SimpleHashFromBytesers(items []Byteser) []byte { ... } 61 62 func SimpleHashFromByteslices(bzs [][]byte) []byte { 63 hashes := make([][]byte, len(bzs)) 64 for i, bz := range bzs { 65 hashes[i] = SimpleHashFromBytes(bz) 66 } 67 return SimpleHashFromHashes(hashes) 68 } 69 70 func SimpleHashFromBytes(bz []byte) []byte { 71 hasher := tmhash.New() 72 hasher.Write(bz) 73 return hasher.Sum(nil) 74 } 75 76 func SimpleHashFromHashers(items []Hasher) []byte { 77 hashes := make([][]byte, len(items)) 78 for i, item := range items { 79 hash := item.Hash() 80 hashes[i] = hash 81 } 82 return SimpleHashFromHashes(hashes) 83 } 84 85 func SimpleHashFromMap(m map[string]Hasher) []byte { 86 sm := NewSimpleMap() 87 for k, v := range m { 88 sm.Set(k, v) 89 } 90 return sm.Hash() 91 }