github.com/letsencrypt/trillian@v1.1.2-0.20180615153820-ae375a99d36a/merkle/hash_chainer.go (about) 1 // Copyright 2018 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 merkle 16 17 import ( 18 "github.com/google/trillian/merkle/hashers" 19 ) 20 21 // hashChainer provides convenience methods for hashing subranges of Merkle 22 // Tree proofs to obtain (sub-)tree hashes. Depending on how the path to a tree 23 // node relates to the query and/or tree borders, different methods are there. 24 // 25 // TODO(pavelkalinnikov): Add a Merkle Trees doc with visual explanations. 26 type hashChainer struct { 27 hasher hashers.LogHasher 28 } 29 30 // chainInner computes a subtree hash for a node on or below the tree's right 31 // border. Assumes |proof| hashes are ordered from lower levels to upper, and 32 // |seed| is the initial subtree/leaf hash on the path located at the specified 33 // |index| on its level. 34 func (c hashChainer) chainInner(seed []byte, proof [][]byte, index int64) []byte { 35 for i, h := range proof { 36 if (index>>uint(i))&1 == 0 { 37 seed = c.hasher.HashChildren(seed, h) 38 } else { 39 seed = c.hasher.HashChildren(h, seed) 40 } 41 } 42 return seed 43 } 44 45 // chainInnerRight computes a subtree hash like chainInner, but only takes 46 // hashes to the left from the path into consideration, which effectively means 47 // the result is a hash of the corresponding earlier version of this subtree. 48 func (c hashChainer) chainInnerRight(seed []byte, proof [][]byte, index int64) []byte { 49 for i, h := range proof { 50 if (index>>uint(i))&1 == 1 { 51 seed = c.hasher.HashChildren(h, seed) 52 } 53 } 54 return seed 55 } 56 57 // chainBorderRight chains proof hashes along tree borders. This differs from 58 // inner chaining because |proof| contains only left-side subtree hashes. 59 func (c hashChainer) chainBorderRight(seed []byte, proof [][]byte) []byte { 60 for _, h := range proof { 61 seed = c.hasher.HashChildren(h, seed) 62 } 63 return seed 64 }