github.com/0chain/gosdk@v1.17.11/zboxcore/encoder/erasurecode.go (about) 1 // Stream Encoder for erasure coding. 2 package encoder 3 4 import ( 5 "bufio" 6 "bytes" 7 8 "errors" 9 10 l "github.com/0chain/gosdk/zboxcore/logger" 11 12 "github.com/klauspost/reedsolomon" 13 ) 14 15 type StreamEncoder struct { 16 iDataShards int 17 iParityShards int 18 erasureCode reedsolomon.Encoder 19 data [][]byte 20 } 21 22 // Creates New encoder instance and return index for further access 23 func NewEncoder(iDataShards, iParityShards int) (*StreamEncoder, error) { 24 e := &StreamEncoder{} 25 var err error 26 27 e.erasureCode, err = reedsolomon.New(iDataShards, iParityShards, reedsolomon.WithAutoGoroutines(64*1024)) 28 if err != nil { 29 return nil, err 30 } 31 e.iDataShards = iDataShards 32 e.iParityShards = iParityShards 33 return e, nil 34 } 35 36 // Encodes and returns the shards on success and error on fails 37 func (e *StreamEncoder) Encode(in []byte) ([][]byte, error) { 38 var err error 39 e.data, err = e.erasureCode.Split(in) 40 if err != nil { 41 l.Logger.Error("Split failed", err.Error()) 42 return [][]byte{}, err 43 } 44 45 err = e.erasureCode.Encode(e.data) 46 if err != nil { 47 l.Logger.Error("Encode failed", err.Error()) 48 return [][]byte{}, err 49 } 50 return e.data, nil 51 } 52 53 func (e *StreamEncoder) Decode(in [][]byte, shardSize int) ([]byte, error) { 54 // Verify the input 55 if (len(in) < e.iDataShards+e.iParityShards) || (shardSize <= 0) { 56 return []byte{}, errors.New("Invalid input length") 57 } 58 59 err := e.erasureCode.Reconstruct(in) 60 if err != nil { 61 l.Logger.Error("Reconstruct failed -", err) 62 return []byte{}, err 63 } 64 _, err = e.erasureCode.Verify(in) 65 if err != nil { 66 l.Logger.Error("Verification failed after reconstruction, data likely corrupted.", err.Error()) 67 return []byte{}, err 68 } 69 70 var bytesBuf bytes.Buffer 71 bufWriter := bufio.NewWriter(&bytesBuf) 72 bufWriter = bufio.NewWriterSize(bufWriter, (shardSize * e.iDataShards)) 73 err = e.erasureCode.Join(bufWriter, in, (shardSize * e.iDataShards)) 74 if err != nil { 75 l.Logger.Error("join failed", err.Error()) 76 return []byte{}, err 77 } 78 bufWriter.Flush() 79 outBuf := bytesBuf.Bytes() 80 return outBuf, nil 81 }