switch to lbry.go/stream

This commit is contained in:
Alex Grintsvayg 2019-01-10 08:02:43 -05:00
parent 14d6d32a41
commit 75ad143d84
6 changed files with 4 additions and 389 deletions

View file

@ -4,7 +4,8 @@ import (
"crypto/rand"
"github.com/lbryio/reflector.go/reflector"
"github.com/lbryio/reflector.go/stream"
"github.com/lbryio/lbry.go/stream"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"

View file

@ -4,9 +4,8 @@ import (
"encoding/json"
"net"
"github.com/lbryio/reflector.go/stream"
"github.com/lbryio/lbry.go/extras/errors"
"github.com/lbryio/lbry.go/stream"
log "github.com/sirupsen/logrus"
)

View file

@ -11,10 +11,10 @@ import (
"time"
"github.com/lbryio/reflector.go/store"
"github.com/lbryio/reflector.go/stream"
"github.com/lbryio/lbry.go/extras/errors"
"github.com/lbryio/lbry.go/extras/stop"
"github.com/lbryio/lbry.go/stream"
log "github.com/sirupsen/logrus"
)

View file

@ -1,192 +0,0 @@
package stream
import (
"bytes"
"crypto/aes"
"crypto/rand"
"crypto/sha512"
"encoding/hex"
"encoding/json"
"strconv"
"github.com/lbryio/lbry.go/extras/errors"
)
const MaxBlobSize = 2 * 1024 * 1024
type Blob []byte
var ErrBlobTooBig = errors.Base("blob must be at most " + strconv.Itoa(MaxBlobSize) + " bytes")
var ErrBlobEmpty = errors.Base("blob is empty")
func (b Blob) Size() int {
return len(b)
}
// Hash returns a hash of the blob data
func (b Blob) Hash() []byte {
if b.Size() == 0 {
return nil
}
hashBytes := sha512.Sum384(b)
return hashBytes[:]
}
// HexHash returns th blob hash as a hex string
func (b Blob) HashHex() string {
return hex.EncodeToString(b.Hash())
}
// ValidForSend returns true if the blob size is within the limits
func (b Blob) ValidForSend() error {
if b.Size() > MaxBlobSize {
return ErrBlobTooBig
}
if b.Size() == 0 {
return ErrBlobEmpty
}
return nil
}
// BlobInfo is the stream descriptor info for a single blob in a stream
// Encoding to and from JSON is customized to match existing behavior (see json.go in package)
type BlobInfo struct {
Length int `json:"length"`
BlobNum int `json:"blob_num"`
BlobHash []byte `json:"-"`
IV []byte `json:"-"`
}
// Hash returns the hash of the blob info for calculating the stream hash
func (bi BlobInfo) Hash() []byte {
sum := sha512.New384()
if bi.Length > 0 {
sum.Write([]byte(hex.EncodeToString(bi.BlobHash)))
}
sum.Write([]byte(strconv.Itoa(bi.BlobNum)))
sum.Write([]byte(hex.EncodeToString(bi.IV)))
sum.Write([]byte(strconv.Itoa(bi.Length)))
return sum.Sum(nil)
}
// SDBlob contains information about the rest of the blobs in the stream
// Encoding to and from JSON is customized to match existing behavior (see json.go in package)
type SDBlob struct {
StreamName string `json:"-"`
BlobInfos []BlobInfo `json:"blobs"`
StreamType string `json:"stream_type"`
Key []byte `json:"-"`
SuggestedFileName string `json:"-"`
StreamHash []byte `json:"-"`
ivFunc func() []byte
}
// ToBlob converts the SDBlob to a normal data Blob
func (s SDBlob) ToBlob() (Blob, error) {
b, err := json.Marshal(s)
return Blob(b), err
}
// FromBlob unmarshals a data Blob that should contain SDBlob data
func (s *SDBlob) FromBlob(b Blob) error {
return json.Unmarshal(b, s)
}
func NewSdBlob(blobs []Blob) *SDBlob {
return newSdBlob(blobs, nil, nil)
}
func newSdBlob(blobs []Blob, key []byte, ivs [][]byte) *SDBlob {
sd := &SDBlob{}
if key == nil {
key = randIV()
}
sd.Key = key
if ivs == nil {
ivs = make([][]byte, len(blobs))
for i := range ivs {
ivs[i] = randIV()
}
}
for i, b := range blobs {
sd.addBlob(b, ivs[i])
}
sd.updateStreamHash()
return sd
}
// addBlob adds the blob's info to stream
func (s *SDBlob) addBlob(b Blob, iv []byte) {
if iv == nil {
iv = s.nextIV()
}
s.BlobInfos = append(s.BlobInfos, BlobInfo{
BlobNum: len(s.BlobInfos),
Length: b.Size(),
BlobHash: b.Hash(),
IV: iv,
})
}
// nextIV returns the next IV using ivFunc, or a random IV if no ivFunc is set
func (s SDBlob) nextIV() []byte {
if s.ivFunc != nil {
return s.ivFunc()
}
return randIV()
}
// IsValid returns true if the set StreamHash matches the current hash of the stream data
func (s SDBlob) IsValid() bool {
return bytes.Equal(s.StreamHash, s.computeStreamHash())
}
// updateStreamHash sets the stream hash to the current hash of the stream data
func (s *SDBlob) updateStreamHash() {
s.StreamHash = s.computeStreamHash()
}
// computeStreamHash calculates the stream hash for the stream
func (s *SDBlob) computeStreamHash() []byte {
return streamHash(
hex.EncodeToString([]byte(s.StreamName)),
hex.EncodeToString(s.Key),
hex.EncodeToString([]byte(s.SuggestedFileName)),
s.BlobInfos,
)
}
// streamHash calculates the stream hash, given the stream's fields and blobs
func streamHash(hexStreamName, hexKey, hexSuggestedFileName string, blobInfos []BlobInfo) []byte {
blobSum := sha512.New384()
for _, b := range blobInfos {
blobSum.Write(b.Hash())
}
sum := sha512.New384()
sum.Write([]byte(hexStreamName))
sum.Write([]byte(hexKey))
sum.Write([]byte(hexSuggestedFileName))
sum.Write(blobSum.Sum(nil))
return sum.Sum(nil)
}
// randIV returns a random AES IV
func randIV() []byte {
blob := make([]byte, aes.BlockSize)
_, err := rand.Read(blob)
if err != nil {
panic("failed to make random blob")
}
return blob
}
// NullIV returns an IV of 0s
func NullIV() []byte {
return make([]byte, aes.BlockSize)
}

File diff suppressed because one or more lines are too long

View file

@ -1,110 +0,0 @@
package stream
import (
"encoding/hex"
"encoding/json"
"github.com/lbryio/lbry.go/extras/errors"
)
// inspired by https://blog.gopheracademy.com/advent-2016/advanced-encoding-decoding/
type SDBlobAlias SDBlob
type JSONSDBlob struct {
StreamName string `json:"stream_name"`
SDBlobAlias
Key string `json:"key"`
SuggestedFileName string `json:"suggested_file_name"`
StreamHash string `json:"stream_hash"`
}
func (s SDBlob) MarshalJSON() ([]byte, error) {
var tmp JSONSDBlob
tmp.StreamName = hex.EncodeToString([]byte(s.StreamName))
tmp.StreamHash = hex.EncodeToString(s.StreamHash)
tmp.SuggestedFileName = hex.EncodeToString([]byte(s.SuggestedFileName))
tmp.Key = hex.EncodeToString(s.Key)
tmp.SDBlobAlias = SDBlobAlias(s)
return json.Marshal(tmp)
}
func (s *SDBlob) UnmarshalJSON(b []byte) error {
var tmp JSONSDBlob
err := json.Unmarshal(b, &tmp)
if err != nil {
return errors.Err(err)
}
*s = SDBlob(tmp.SDBlobAlias)
str, err := hex.DecodeString(tmp.StreamName)
if err != nil {
return errors.Err(err)
}
s.StreamName = string(str)
str, err = hex.DecodeString(tmp.SuggestedFileName)
if err != nil {
return errors.Err(err)
}
s.SuggestedFileName = string(str)
s.StreamHash, err = hex.DecodeString(tmp.StreamHash)
if err != nil {
return errors.Err(err)
}
s.Key, err = hex.DecodeString(tmp.Key)
if err != nil {
return errors.Err(err)
}
return nil
}
type BlobInfoAlias BlobInfo
type JSONBlobInfo struct {
BlobInfoAlias
BlobHash string `json:"blob_hash,omitempty"`
IV string `json:"iv"`
}
func (bi BlobInfo) MarshalJSON() ([]byte, error) {
var tmp JSONBlobInfo
tmp.IV = hex.EncodeToString(bi.IV)
if len(bi.BlobHash) > 0 {
tmp.BlobHash = hex.EncodeToString(bi.BlobHash)
}
tmp.BlobInfoAlias = BlobInfoAlias(bi)
return json.Marshal(tmp)
}
func (bi *BlobInfo) UnmarshalJSON(b []byte) error {
var tmp JSONBlobInfo
err := json.Unmarshal(b, &tmp)
if err != nil {
return errors.Err(err)
}
*bi = BlobInfo(tmp.BlobInfoAlias)
bi.BlobHash, err = hex.DecodeString(tmp.BlobHash)
if err != nil {
return errors.Err(err)
}
bi.IV, err = hex.DecodeString(tmp.IV)
if err != nil {
return errors.Err(err)
}
return nil
}