package merkle import ( "bytes" "crypto/sha256" "fmt" . "github.com/tendermint/tendermint/binary" ) func HashFromTwoHashes(left []byte, right []byte) []byte { var n int64 var err error var hasher = sha256.New() WriteByteSlice(hasher, left, &n, &err) WriteByteSlice(hasher, right, &n, &err) if err != nil { panic(err) } return hasher.Sum(nil) } /* Computes a deterministic minimal height merkle tree hash. If the number of items is not a power of two, some leaves will be at different levels. * / \ / \ / \ / \ * * / \ / \ / \ / \ / \ / \ * h2 * * / \ / \ / \ h0 h1 h3 h4 h5 h6 */ func HashFromHashes(hashes [][]byte) []byte { switch len(hashes) { case 0: return nil case 1: return hashes[0] default: left := HashFromHashes(hashes[:len(hashes)/2]) right := HashFromHashes(hashes[len(hashes)/2:]) return HashFromTwoHashes(left, right) } } // Convenience for HashFromHashes. func HashFromBinaries(items []Binary) []byte { hashes := [][]byte{} for _, item := range items { hasher := sha256.New() _, err := item.WriteTo(hasher) if err != nil { panic(err) } hash := hasher.Sum(nil) hashes = append(hashes, hash) } return HashFromHashes(hashes) } // Convenience for HashFromHashes. func HashFromHashables(items []Hashable) []byte { hashes := [][]byte{} for _, item := range items { hash := item.Hash() hashes = append(hashes, hash) } return HashFromHashes(hashes) } /* Calculates an array of hashes, useful for deriving hash trails. 7 / \ / \ / \ / \ 3 11 / \ / \ / \ / \ / \ / \ 1 5 9 13 / \ / \ / \ / \ 0 2 4 6 8 10 12 14 h0 h1 h2 h3 h4 h5 h6 h7 (diagram and idea borrowed from libswift) The hashes provided get assigned to even indices. The derived merkle hashes get assigned to odd indices. If "hashes" is not of length power of 2, it is padded with blank (zeroed) hashes. */ func HashTreeFromHashes(hashes [][]byte) [][]byte { // Make length of "hashes" a power of 2 hashesLen := uint32(len(hashes)) fullLen := uint32(1) for { if fullLen >= hashesLen { break } else { fullLen <<= 1 } } blank := make([]byte, len(hashes[0])) for i := hashesLen; i < fullLen; i++ { hashes = append(hashes, blank) } // The result is twice the length minus one. res := make([][]byte, len(hashes)*2-1) for i, hash := range hashes { res[i*2] = hash } // Fill all the hashes recursively. fillTreeRoot(res, 0, len(res)-1) return res } // Fill in the blanks. func fillTreeRoot(res [][]byte, start, end int) []byte { if start == end { return res[start] } else { mid := (start + end) / 2 left := fillTreeRoot(res, start, mid-1) right := fillTreeRoot(res, mid+1, end) root := HashFromTwoHashes(left, right) res[mid] = root return root } } // Convenience for HashTreeFromHashes. func HashTreeFromHashables(items []Hashable) [][]byte { hashes := [][]byte{} for _, item := range items { hash := item.Hash() hashes = append(hashes, hash) } return HashTreeFromHashes(hashes) } /* Given the original index of an item, (e.g. for h5 in the diagram above, the index is 5, not 10) returns a trail of hashes, which along with the index can be used to calculate the merkle root. See VerifyHashTrailForIndex() */ func HashTrailForIndex(hashTree [][]byte, index int) [][]byte { trail := [][]byte{} index *= 2 // We start from the leaf layer and work our way up. // Notice the indices in the diagram: // 0 2 4 ... offset 0, stride 2 // 1 5 9 ... offset 1, stride 4 // 3 11 19 ... offset 3, stride 8 // 7 23 39 ... offset 7, stride 16 etc. offset := 0 stride := 2 for { // Calculate sibling of index. var next int if ((index-offset)/stride)%2 == 0 { next = index + stride } else { next = index - stride } if next >= len(hashTree) { break } // Insert sibling hash to trail. trail = append(trail, hashTree[next]) index = (index + next) / 2 offset += stride / 2 stride *= 2 } return trail } // Ensures that leafHash is part of rootHash. func VerifyHashTrailForIndex(index int, leafHash []byte, trail [][]byte, rootHash []byte) bool { index *= 2 offset := 0 stride := 2 tempHash := make([]byte, len(leafHash)) copy(tempHash, leafHash) for i := 0; i < len(trail); i++ { var next int if ((index-offset)/stride)%2 == 0 { next = index + stride tempHash = HashFromTwoHashes(tempHash, trail[i]) } else { next = index - stride tempHash = HashFromTwoHashes(trail[i], tempHash) } index = (index + next) / 2 offset += stride / 2 stride *= 2 } return bytes.Equal(rootHash, tempHash) } //----------------------------------------------------------------------------- func PrintIAVLNode(node *IAVLNode) { fmt.Println("==== NODE") if node != nil { printIAVLNode(node, 0) } fmt.Println("==== END") } func printIAVLNode(node *IAVLNode, indent int) { indentPrefix := "" for i := 0; i < indent; i++ { indentPrefix += " " } if node.rightNode != nil { printIAVLNode(node.rightNode, indent+1) } else if node.rightHash != nil { fmt.Printf("%s %X\n", indentPrefix, node.rightHash) } fmt.Printf("%s%v:%v\n", indentPrefix, node.key, node.height) if node.leftNode != nil { printIAVLNode(node.leftNode, indent+1) } else if node.leftHash != nil { fmt.Printf("%s %X\n", indentPrefix, node.leftHash) } } func maxUint8(a, b uint8) uint8 { if a > b { return a } return b }