github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/merkle/merkle_hasher.go (about) 1 /* 2 * Copyright (C) 2018 The ontology Authors 3 * This file is part of The ontology library. 4 * 5 * The ontology is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * The ontology is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with The ontology. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 package merkle 20 21 import ( 22 "crypto/sha256" 23 24 "github.com/sixexorg/magnetic-ring/common" 25 ) 26 27 type TreeHasher struct { 28 } 29 30 func (self TreeHasher) hash_empty() common.Hash { 31 return sha256.Sum256(nil) 32 } 33 34 func (self TreeHasher) hash_leaf(data []byte) common.Hash { 35 tmp := append([]byte{0}, data...) 36 return sha256.Sum256(tmp) 37 } 38 39 func (self TreeHasher) hash_children(left, right common.Hash) common.Hash { 40 data := append([]byte{1}, left[:]...) 41 data = append(data, right[:]...) 42 return sha256.Sum256(data) 43 } 44 45 func (self TreeHasher) HashFullTreeWithLeafHash(leaves []common.Hash) common.Hash { 46 length := uint64(len(leaves)) 47 root_hash, hashes := self._hash_full(leaves, 0, length) 48 49 if uint(len(hashes)) != countBit(length) { 50 panic("assert failed in hash full tree") 51 } 52 53 // assert len(hashes) == countBit(len(leaves)) 54 // assert self._hash_fold(hashes) == root_hash if hashes else root_hash == self.hash_empty() 55 56 return root_hash 57 } 58 59 func (self TreeHasher) HashFullTree(leaves [][]byte) common.Hash { 60 length := uint64(len(leaves)) 61 leafhashes := make([]common.Hash, length, length) 62 for i := range leaves { 63 leafhashes[i] = self.hash_leaf(leaves[i]) 64 } 65 root_hash, hashes := self._hash_full(leafhashes, 0, length) 66 67 if uint(len(hashes)) != countBit(length) { 68 panic("assert failed in hash full tree") 69 } 70 71 // assert len(hashes) == countBit(len(leaves)) 72 // assert self._hash_fold(hashes) == root_hash if hashes else root_hash == self.hash_empty() 73 74 return root_hash 75 } 76 77 func (self TreeHasher) _hash_full(leaves []common.Hash, l_idx, r_idx uint64) (root_hash common.Hash, hashes []common.Hash) { 78 width := r_idx - l_idx 79 if width == 0 { 80 return self.hash_empty(), nil 81 } else if width == 1 { 82 leaf_hash := leaves[l_idx] 83 return leaf_hash, []common.Hash{leaf_hash} 84 } else { 85 var split_width uint64 = 1 << (countBit(width-1) - 1) 86 l_root, l_hashes := self._hash_full(leaves, l_idx, l_idx+split_width) 87 if len(l_hashes) != 1 { 88 panic("left tree always full") 89 } 90 r_root, r_hashes := self._hash_full(leaves, l_idx+split_width, r_idx) 91 root_hash = self.hash_children(l_root, r_root) 92 var hashes []common.Hash 93 if split_width*2 == width { 94 hashes = []common.Hash{root_hash} 95 } else { 96 hashes = append(l_hashes, r_hashes[:]...) 97 } 98 return root_hash, hashes 99 } 100 } 101 102 func (self TreeHasher) _hash_fold(hashes []common.Hash) common.Hash { 103 l := len(hashes) 104 accum := hashes[l-1] 105 for i := l - 2; i >= 0; i-- { 106 accum = self.hash_children(hashes[i], accum) 107 } 108 109 return accum 110 }