github.com/bartle-stripe/trillian@v1.2.1/storage/cache/map_subtree_cache.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 cache 16 17 import ( 18 "encoding/base64" 19 "fmt" 20 "math/big" 21 22 "github.com/golang/glog" 23 "github.com/google/trillian/merkle" 24 "github.com/google/trillian/merkle/hashers" 25 "github.com/google/trillian/storage" 26 "github.com/google/trillian/storage/storagepb" 27 ) 28 29 // NewMapSubtreeCache creates and returns a SubtreeCache appropriate for use with a map 30 // tree. The caller must supply the strata depths to be used, the treeID and a suitable MapHasher. 31 func NewMapSubtreeCache(mapStrata []int, treeID int64, hasher hashers.MapHasher) SubtreeCache { 32 return NewSubtreeCache(mapStrata, populateMapSubtreeNodes(treeID, hasher), prepareMapSubtreeWrite()) 33 } 34 35 // populateMapSubtreeNodes re-creates Map subtree's InternalNodes from the 36 // subtree Leaves map. 37 // 38 // This uses HStar2 to repopulate internal nodes. 39 func populateMapSubtreeNodes(treeID int64, hasher hashers.MapHasher) storage.PopulateSubtreeFunc { 40 return func(st *storagepb.SubtreeProto) error { 41 st.InternalNodes = make(map[string][]byte) 42 leaves := make([]merkle.HStar2LeafHash, 0, len(st.Leaves)) 43 for k64, v := range st.Leaves { 44 sfx, err := storage.ParseSuffix(k64) 45 if err != nil { 46 return err 47 } 48 // TODO(gdbelvin): test against subtree depth. 49 if sfx.Bits%depthQuantum != 0 { 50 return fmt.Errorf("unexpected non-leaf suffix found: %x", sfx.Bits) 51 } 52 53 leaves = append(leaves, merkle.HStar2LeafHash{ 54 Index: storage.NewNodeIDFromPrefixSuffix(st.Prefix, sfx, hasher.BitLen()).BigInt(), 55 LeafHash: v, 56 }) 57 } 58 hs2 := merkle.NewHStar2(treeID, hasher) 59 root, err := hs2.HStar2Nodes(st.Prefix, int(st.Depth), leaves, nil, 60 func(depth int, index *big.Int, h []byte) error { 61 if depth == len(st.Prefix)*8 && len(st.Prefix) > 0 { 62 // no space for the root in the node cache 63 return nil 64 } 65 nodeID := storage.NewNodeIDFromBigInt(depth, index, hasher.BitLen()) 66 _, sfx := nodeID.Split(len(st.Prefix), int(st.Depth)) 67 sfxKey := sfx.String() 68 if glog.V(4) { 69 b, err := base64.StdEncoding.DecodeString(sfxKey) 70 if err != nil { 71 glog.Errorf("base64.DecodeString(%v): %v", sfxKey, err) 72 } 73 glog.Infof("PopulateMapSubtreeNodes.Set(%x, %d) suffix: %x: %x", index.Bytes(), depth, b, h) 74 } 75 st.InternalNodes[sfxKey] = h 76 return nil 77 }) 78 if err != nil { 79 return err 80 } 81 st.RootHash = root 82 return err 83 } 84 } 85 86 // prepareMapSubtreeWrite prepares a map subtree for writing. For maps the internal 87 // nodes are never written to storage and are thus always cleared. 88 func prepareMapSubtreeWrite() storage.PrepareSubtreeWriteFunc { 89 return func(st *storagepb.SubtreeProto) error { 90 st.InternalNodes = nil 91 // We don't check the node count for map subtrees but ensure it's zero for consistency 92 st.InternalNodeCount = 0 93 return nil 94 } 95 }