github.com/mre-fog/trillianxx@v1.1.2-0.20180615153820-ae375a99d36a/merkle/maphasher/maphasher.go (about) 1 // Copyright 2017 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package maphasher provides hashing for maps. 16 package maphasher 17 18 import ( 19 "crypto" 20 "fmt" 21 22 "github.com/golang/glog" 23 "github.com/google/trillian" 24 "github.com/google/trillian/merkle/hashers" 25 ) 26 27 func init() { 28 hashers.RegisterMapHasher(trillian.HashStrategy_TEST_MAP_HASHER, Default) 29 } 30 31 // Domain separation prefixes 32 const ( 33 leafHashPrefix = 0 34 nodeHashPrefix = 1 35 ) 36 37 // Default is a SHA256 based MapHasher for maps. 38 var Default = New(crypto.SHA256) 39 40 // MapHasher implements a sparse merkle tree hashing algorithm. For testing only. 41 // It matches the test vectors generated by other sparse map implementations, 42 // but it does not offer the full N bit security of the underlying hash function. 43 type MapHasher struct { 44 crypto.Hash 45 nullHashes [][]byte 46 } 47 48 // New creates a new merkle.MapHasher using the passed in hash function. 49 func New(h crypto.Hash) hashers.MapHasher { 50 m := &MapHasher{Hash: h} 51 m.initNullHashes() 52 return m 53 } 54 55 // String returns a string representation for debugging. 56 func (m *MapHasher) String() string { 57 return fmt.Sprintf("MapHasher{%v}", m.Hash) 58 } 59 60 // HashEmpty returns the hash of an empty branch at a given depth. 61 // A depth of 0 indicates the hash of an empty leaf. 62 // Empty branches within the tree are plain interior nodes e1 = H(e0, e0) etc. 63 func (m *MapHasher) HashEmpty(treeID int64, index []byte, height int) []byte { 64 if height < 0 || height >= len(m.nullHashes) { 65 panic(fmt.Sprintf("HashEmpty(%v) out of bounds", height)) 66 } 67 depth := m.BitLen() - height 68 glog.V(5).Infof("HashEmpty(%x, %d): %x", index, depth, m.nullHashes[height]) 69 return m.nullHashes[height] 70 } 71 72 // HashLeaf returns the Merkle tree leaf hash of the data passed in through leaf. 73 // The hashed structure is leafHashPrefix||leaf. 74 func (m *MapHasher) HashLeaf(treeID int64, index []byte, leaf []byte) ([]byte, error) { 75 h := m.New() 76 h.Write([]byte{leafHashPrefix}) 77 h.Write(leaf) 78 r := h.Sum(nil) 79 glog.V(5).Infof("HashLeaf(%x): %x", index, r) 80 return r, nil 81 } 82 83 // HashChildren returns the internal Merkle tree node hash of the the two child nodes l and r. 84 // The hashed structure is NodeHashPrefix||l||r. 85 func (m *MapHasher) HashChildren(l, r []byte) []byte { 86 h := m.New() 87 h.Write([]byte{nodeHashPrefix}) 88 h.Write(l) 89 h.Write(r) 90 p := h.Sum(nil) 91 glog.V(5).Infof("HashChildren(%x, %x): %x", l, r, p) 92 return p 93 } 94 95 // BitLen returns the number of bits in the hash function. 96 func (m *MapHasher) BitLen() int { 97 return m.Size() * 8 98 } 99 100 // initNullHashes sets the cache of empty hashes, one for each level in the sparse tree, 101 // starting with the hash of an empty leaf, all the way up to the root hash of an empty tree. 102 // These empty branches are not stored on disk in a sparse tree. They are computed since their 103 // values are well-known. 104 func (m *MapHasher) initNullHashes() { 105 // Leaves are stored at depth 0. Root is at Size()*8. 106 // There are Size()*8 edges, and Size()*8 + 1 nodes in the tree. 107 nodes := m.Size()*8 + 1 108 r := make([][]byte, nodes) 109 h, err := m.HashLeaf(0, nil, nil) 110 if err != nil { 111 // This panic should be impossible to trigger. 112 // MapHasher.HashLeaf never returns an error. 113 panic(fmt.Sprintf("HashLeaf(): %v", err)) 114 } 115 r[0] = h 116 for i := 1; i < nodes; i++ { 117 r[i] = m.HashChildren(r[i-1], r[i-1]) 118 } 119 m.nullHashes = r 120 }