github.com/code-to-go/safepool.lib@v0.0.0-20221205180519-ee25e63c226e/algo/merkle.go (about) 1 package algo 2 3 import ( 4 "hash" 5 "io" 6 "os" 7 ) 8 9 type MerkleTree struct { 10 DataLength uint32 11 Blocks []HashBlock 12 } 13 14 var UseSimd bool 15 16 func MerkleTreeFromFile(name string, splitBits uint) (MerkleTree, error) { 17 f, err := os.Open(name) 18 if err != nil { 19 return MerkleTree{}, err 20 } 21 defer f.Close() 22 23 return MerkleTreeFromReader(f, splitBits) 24 } 25 26 func MerkleTreeFromReader(r io.Reader, splitBits uint) (MerkleTree, error) { 27 blocks, err := HashSplit(r, splitBits, nil) 28 if err != nil { 29 return MerkleTree{}, err 30 } 31 32 start := 0 33 for start < len(blocks)-1 { 34 // blocks, start = buildMerkleRow(blake, length, blocks, start) 35 } 36 37 return MerkleTree{ 38 Blocks: blocks, 39 }, nil 40 } 41 42 // buildMerkleRow calculates a new row of a Merkle tree starting from start position until the end of the 43 func buildMerkleRow(blake hash.Hash, fileLength uint32, blocks []HashBlock, start int) (blocks2 []HashBlock, start2 int) { 44 l := len(blocks) 45 if l%2 == 1 { 46 blocks = append(blocks, getHashBlock(blake, fileLength)) 47 l++ 48 } 49 50 for i := start; i < l; i += 2 { 51 block := getHashBlock(blake, blocks[i].Length, blocks[i].Hash[:], blocks[i+1].Hash[:]) 52 blocks = append(blocks, block) 53 } 54 return blocks, l 55 } 56 57 func MerkleTreeRoot(m MerkleTree) (HashBlock, int) { 58 l := len(m.Blocks) - 1 59 return m.Blocks[l], l 60 } 61 62 func MerkleTreeHash(m MerkleTree) *[]byte { 63 l := len(m.Blocks) - 1 64 return &m.Blocks[l].Hash 65 } 66 67 func MerkleTreeAt(m MerkleTree, idx int) (block HashBlock, length uint32) { 68 block = m.Blocks[idx] 69 if idx+1 == len(m.Blocks) || m.Blocks[idx+1].Length <= m.Blocks[idx].Length { 70 return block, m.DataLength - block.Length 71 } else { 72 return block, m.Blocks[idx+1].Length - block.Length 73 } 74 } 75 76 func MerkleTreeChildren(m MerkleTree, idx int) (left int, right int) { 77 return 0, 0 78 } 79 80 func min(a, b int) int { 81 if a < b { 82 return a 83 } else { 84 return b 85 } 86 }