lbry-sdk/lbrynet/lbrylive/StreamDescriptor.py
Jimmy Kiselak 192ac6959a more specific exceptions, and change when blobs are deleted
More specific exceptions are raised when problems are encountered
looking up metadata and validating stream descriptor files, and
on the GUI those more specific exceptions are used to prevent
errors from being presented to the user.

If the user has selected the option to re-upload data for some
stream, blobs downloaded for that purpose will not be deleted
when they are finished being output. Instead, by default, for
the GUI they will be deleted when the stream is removed from
the GUI. That can be changed so they are not deleted at all,
using the lbry.conf file.
2015-09-01 17:49:26 -04:00

131 lines
No EOL
4.6 KiB
Python

import binascii
import logging
from lbrynet.core.cryptoutils import get_lbry_hash_obj, verify_signature
from twisted.internet import defer, threads
from lbrynet.core.Error import DuplicateStreamHashError, InvalidStreamDescriptorError
from lbrynet.lbrylive.LiveBlob import LiveBlobInfo
from lbrynet.interfaces import IStreamDescriptorValidator
from zope.interface import implements
LiveStreamType = "lbrylive"
def save_sd_info(stream_info_manager, sd_info, ignore_duplicate=False):
logging.debug("Saving info for %s", str(sd_info['stream_name']))
hex_stream_name = sd_info['stream_name']
public_key = sd_info['public_key']
key = sd_info['key']
stream_hash = sd_info['stream_hash']
raw_blobs = sd_info['blobs']
crypt_blobs = []
for blob in raw_blobs:
length = blob['length']
if length != 0:
blob_hash = blob['blob_hash']
else:
blob_hash = None
blob_num = blob['blob_num']
revision = blob['revision']
iv = blob['iv']
signature = blob['signature']
crypt_blobs.append(LiveBlobInfo(blob_hash, blob_num, length, iv, revision, signature))
logging.debug("Trying to save stream info for %s", str(hex_stream_name))
d = stream_info_manager.save_stream(stream_hash, public_key, hex_stream_name,
key, crypt_blobs)
def check_if_duplicate(err):
if ignore_duplicate is True:
err.trap(DuplicateStreamHashError)
d.addErrback(check_if_duplicate)
d.addCallback(lambda _: stream_hash)
return d
def get_sd_info(stream_info_manager, stream_hash, include_blobs):
d = stream_info_manager.get_stream_info(stream_hash)
def format_info(stream_info):
fields = {}
fields['stream_type'] = LiveStreamType
fields['stream_name'] = stream_info[2]
fields['public_key'] = stream_info[0]
fields['key'] = stream_info[1]
fields['stream_hash'] = stream_hash
def format_blobs(blobs):
formatted_blobs = []
for blob_hash, blob_num, revision, iv, length, signature in blobs:
blob = {}
if length != 0:
blob['blob_hash'] = blob_hash
blob['blob_num'] = blob_num
blob['revision'] = revision
blob['iv'] = iv
blob['length'] = length
blob['signature'] = signature
formatted_blobs.append(blob)
fields['blobs'] = formatted_blobs
return fields
if include_blobs is True:
d = stream_info_manager.get_blobs_for_stream(stream_hash)
else:
d = defer.succeed([])
d.addCallback(format_blobs)
return d
d.addCallback(format_info)
return d
class LBRYLiveStreamDescriptorValidator(object):
implements(IStreamDescriptorValidator)
def __init__(self, raw_info):
self.raw_info = raw_info
def validate(self):
logging.debug("Trying to validate stream descriptor for %s", str(self.raw_info['stream_name']))
hex_stream_name = self.raw_info['stream_name']
public_key = self.raw_info['public_key']
key = self.raw_info['key']
stream_hash = self.raw_info['stream_hash']
h = get_lbry_hash_obj()
h.update(hex_stream_name)
h.update(public_key)
h.update(key)
if h.hexdigest() != stream_hash:
raise InvalidStreamDescriptorError("Stream hash does not match stream metadata")
blobs = self.raw_info['blobs']
def check_blob_signatures():
for blob in blobs:
length = blob['length']
if length != 0:
blob_hash = blob['blob_hash']
else:
blob_hash = None
blob_num = blob['blob_num']
revision = blob['revision']
iv = blob['iv']
signature = blob['signature']
hashsum = get_lbry_hash_obj()
hashsum.update(stream_hash)
if length != 0:
hashsum.update(blob_hash)
hashsum.update(str(blob_num))
hashsum.update(str(revision))
hashsum.update(iv)
hashsum.update(str(length))
if not verify_signature(hashsum.digest(), signature, public_key):
raise InvalidStreamDescriptorError("Invalid signature in stream descriptor")
return threads.deferToThread(check_blob_signatures)
def info_to_show(self):
info = []
info.append(("stream_name", binascii.unhexlify(self.raw_info.get("stream_name"))))
return info