github.com/0chain/gosdk@v1.17.11/zboxcore/sdk/chunked_upload_hasher.go (about) 1 package sdk 2 3 import ( 4 "crypto/md5" 5 "encoding/hex" 6 "hash" 7 "sync" 8 9 "github.com/0chain/errors" 10 "github.com/0chain/gosdk/constants" 11 "github.com/0chain/gosdk/core/util" 12 ) 13 14 // Hasher interface to gather all hasher related functions. 15 // A hasher is used to calculate the hash of a file, fixed merkle tree, and validation merkle tree. 16 type Hasher interface { 17 // GetFileHash get file hash 18 GetFileHash() (string, error) 19 // WriteToFile write bytes to file hasher 20 WriteToFile(buf []byte) error 21 22 GetFixedMerkleRoot() (string, error) 23 // WriteToFixedMT write bytes to FMT hasher 24 WriteToFixedMT(buf []byte) error 25 26 GetValidationRoot() (string, error) 27 // WriteToValidationMT write bytes Validation Tree hasher 28 WriteToValidationMT(buf []byte) error 29 // Finalize will let merkle tree know that tree is finalized with the content it has received 30 Finalize() error 31 } 32 33 // see more detail about hash on https://github.com/0chain/blobber/wiki/Protocols#file-hash 34 type hasher struct { 35 File hash.Hash `json:"-"` 36 FixedMT *util.FixedMerkleTree `json:"fixed_merkle_tree"` 37 ValidationMT *util.ValidationTree `json:"validation_merkle_tree"` 38 } 39 40 // CreateHasher creat Hasher instance 41 func CreateHasher(dataSize int64) Hasher { 42 return &hasher{ 43 File: md5.New(), 44 FixedMT: util.NewFixedMerkleTree(), 45 ValidationMT: util.NewValidationTree(dataSize), 46 } 47 } 48 49 func CreateFileHasher() Hasher { 50 return &hasher{ 51 File: md5.New(), 52 } 53 } 54 55 func (h *hasher) GetFileHash() (string, error) { 56 if h == nil { 57 return "", errors.Throw(constants.ErrInvalidParameter, "h") 58 } 59 60 if h.File == nil { 61 return "", errors.Throw(constants.ErrInvalidParameter, "h.File") 62 } 63 return hex.EncodeToString(h.File.Sum(nil)), nil 64 } 65 66 // WriteToFile write bytes to file hasher 67 func (h *hasher) WriteToFile(buf []byte) error { 68 if h == nil { 69 return errors.Throw(constants.ErrInvalidParameter, "h") 70 } 71 72 if h.File == nil { 73 return errors.Throw(constants.ErrInvalidParameter, "h.File") 74 } 75 76 _, err := h.File.Write(buf) 77 return err 78 } 79 80 func (h *hasher) GetFixedMerkleRoot() (string, error) { 81 if h == nil { 82 return "", errors.Throw(constants.ErrInvalidParameter, "h") 83 } 84 85 if h.FixedMT == nil { 86 return "", errors.Throw(constants.ErrInvalidParameter, "h.Challenge") 87 } 88 89 return h.FixedMT.GetMerkleRoot(), nil 90 } 91 92 func (h *hasher) WriteToFixedMT(buf []byte) error { 93 if h == nil { 94 return errors.Throw(constants.ErrInvalidParameter, "h") 95 } 96 97 if h.FixedMT == nil { 98 return errors.Throw(constants.ErrInvalidParameter, "h.Challenge") 99 } 100 _, err := h.FixedMT.Write(buf) 101 return err 102 } 103 104 func (h *hasher) GetValidationRoot() (string, error) { 105 if h == nil { 106 return "", errors.Throw(constants.ErrInvalidParameter, "h") 107 } 108 109 if h.ValidationMT == nil { 110 return "", errors.Throw(constants.ErrInvalidParameter, "h.Content") 111 } 112 113 return hex.EncodeToString(h.ValidationMT.GetValidationRoot()), nil 114 } 115 116 func (h *hasher) WriteToValidationMT(buf []byte) error { 117 if h == nil { 118 return errors.Throw(constants.ErrInvalidParameter, "h") 119 } 120 121 if h.ValidationMT == nil { 122 return errors.Throw(constants.ErrInvalidParameter, "h.Content") 123 } 124 _, err := h.ValidationMT.Write(buf) 125 return err 126 } 127 128 func (h *hasher) Finalize() error { 129 var ( 130 wg sync.WaitGroup 131 errChan = make(chan error, 2) 132 ) 133 wg.Add(2) 134 go func() { 135 if err := h.FixedMT.Finalize(); err != nil { 136 errChan <- err 137 } 138 wg.Done() 139 }() 140 go func() { 141 if err := h.ValidationMT.Finalize(); err != nil { 142 errChan <- err 143 } 144 wg.Done() 145 }() 146 wg.Wait() 147 close(errChan) 148 for err := range errChan { 149 return err 150 } 151 return nil 152 }