From 2dcebe48b7ee4aa9902cfc5ccba66af6b2180fa7 Mon Sep 17 00:00:00 2001 From: Victor Shyba Date: Mon, 17 Sep 2018 17:13:30 -0300 Subject: [PATCH] move lbryschema/lbryschema into lbrynet/schema --- lbrynet/schema/__init__.py | 13 + lbrynet/schema/address.py | 68 ++ lbrynet/schema/base.py | 105 +++ lbrynet/schema/claim.py | 193 +++++ lbrynet/schema/decode.py | 63 ++ lbrynet/schema/encoding.py | 78 ++ lbrynet/schema/error.py | 22 + lbrynet/schema/fee.py | 79 ++ lbrynet/schema/hashing.py | 24 + lbrynet/schema/legacy/StructuredDict.py | 59 ++ lbrynet/schema/legacy/__init__.py | 0 lbrynet/schema/legacy/metadata_schemas.py | 276 +++++++ lbrynet/schema/legacy/migrate.py | 79 ++ lbrynet/schema/proto/__init__.py | 0 lbrynet/schema/proto/certificate.proto | 18 + lbrynet/schema/proto/certificate_pb2.py | 144 ++++ lbrynet/schema/proto/claim.proto | 22 + lbrynet/schema/proto/claim_pb2.py | 156 ++++ lbrynet/schema/proto/fee.proto | 18 + lbrynet/schema/proto/fee_pb2.py | 146 ++++ lbrynet/schema/proto/metadata.proto | 212 +++++ lbrynet/schema/proto/metadata_pb2.py | 934 ++++++++++++++++++++++ lbrynet/schema/proto/signature.proto | 14 + lbrynet/schema/proto/signature_pb2.py | 116 +++ lbrynet/schema/proto/source.proto | 16 + lbrynet/schema/proto/source_pb2.py | 138 ++++ lbrynet/schema/proto/stream.proto | 15 + lbrynet/schema/proto/stream_pb2.py | 111 +++ lbrynet/schema/schema/__init__.py | 102 +++ lbrynet/schema/schema/certificate.py | 54 ++ lbrynet/schema/schema/claim.py | 51 ++ lbrynet/schema/schema/fee.py | 17 + lbrynet/schema/schema/metadata.py | 17 + lbrynet/schema/schema/schema.py | 15 + lbrynet/schema/schema/signature.py | 17 + lbrynet/schema/schema/source.py | 19 + lbrynet/schema/schema/stream.py | 20 + lbrynet/schema/signature/flags.py | 41 + lbrynet/schema/signature/serializer.py | 11 + lbrynet/schema/signer.py | 102 +++ lbrynet/schema/uri.py | 171 ++++ lbrynet/schema/validator.py | 136 ++++ 42 files changed, 3892 insertions(+) create mode 100644 lbrynet/schema/__init__.py create mode 100644 lbrynet/schema/address.py create mode 100644 lbrynet/schema/base.py create mode 100644 lbrynet/schema/claim.py create mode 100644 lbrynet/schema/decode.py create mode 100644 lbrynet/schema/encoding.py create mode 100644 lbrynet/schema/error.py create mode 100644 lbrynet/schema/fee.py create mode 100644 lbrynet/schema/hashing.py create mode 100644 lbrynet/schema/legacy/StructuredDict.py create mode 100644 lbrynet/schema/legacy/__init__.py create mode 100644 lbrynet/schema/legacy/metadata_schemas.py create mode 100644 lbrynet/schema/legacy/migrate.py create mode 100644 lbrynet/schema/proto/__init__.py create mode 100644 lbrynet/schema/proto/certificate.proto create mode 100644 lbrynet/schema/proto/certificate_pb2.py create mode 100644 lbrynet/schema/proto/claim.proto create mode 100644 lbrynet/schema/proto/claim_pb2.py create mode 100644 lbrynet/schema/proto/fee.proto create mode 100644 lbrynet/schema/proto/fee_pb2.py create mode 100644 lbrynet/schema/proto/metadata.proto create mode 100644 lbrynet/schema/proto/metadata_pb2.py create mode 100644 lbrynet/schema/proto/signature.proto create mode 100644 lbrynet/schema/proto/signature_pb2.py create mode 100644 lbrynet/schema/proto/source.proto create mode 100644 lbrynet/schema/proto/source_pb2.py create mode 100644 lbrynet/schema/proto/stream.proto create mode 100644 lbrynet/schema/proto/stream_pb2.py create mode 100644 lbrynet/schema/schema/__init__.py create mode 100644 lbrynet/schema/schema/certificate.py create mode 100644 lbrynet/schema/schema/claim.py create mode 100644 lbrynet/schema/schema/fee.py create mode 100644 lbrynet/schema/schema/metadata.py create mode 100644 lbrynet/schema/schema/schema.py create mode 100644 lbrynet/schema/schema/signature.py create mode 100644 lbrynet/schema/schema/source.py create mode 100644 lbrynet/schema/schema/stream.py create mode 100644 lbrynet/schema/signature/flags.py create mode 100644 lbrynet/schema/signature/serializer.py create mode 100644 lbrynet/schema/signer.py create mode 100644 lbrynet/schema/uri.py create mode 100644 lbrynet/schema/validator.py diff --git a/lbrynet/schema/__init__.py b/lbrynet/schema/__init__.py new file mode 100644 index 000000000..6c86a5fbb --- /dev/null +++ b/lbrynet/schema/__init__.py @@ -0,0 +1,13 @@ +import os + +__version__ = "0.0.16" + +BLOCKCHAIN_NAME_ENVVAR = "LBRYSCHEMA_BLOCKCHAIN_NAME" +if BLOCKCHAIN_NAME_ENVVAR in os.environ: + if os.environ[BLOCKCHAIN_NAME_ENVVAR] in ['lbrycrd_main', 'lbrycrd_regtest', + 'lbrycrd_testnet']: + BLOCKCHAIN_NAME = os.environ[BLOCKCHAIN_NAME_ENVVAR] + else: + raise OSError("invalid blockchain name: %s" % os.environ[BLOCKCHAIN_NAME_ENVVAR]) +else: + BLOCKCHAIN_NAME = "lbrycrd_main" diff --git a/lbrynet/schema/address.py b/lbrynet/schema/address.py new file mode 100644 index 000000000..4b92ab2ca --- /dev/null +++ b/lbrynet/schema/address.py @@ -0,0 +1,68 @@ +import six +import lbryschema +from lbryschema.base import b58encode, b58decode, validate_b58_checksum +from lbryschema.hashing import double_sha256, hash160 +from lbryschema.error import InvalidAddress +from lbryschema.schema import ADDRESS_LENGTH, ADDRESS_PREFIXES, PUBKEY_ADDRESS, SCRIPT_ADDRESS + + +def validate_address_length(addr_bytes): + if len(addr_bytes) != ADDRESS_LENGTH: + raise InvalidAddress("Invalid address length: %i" % len(addr_bytes)) + + +def validate_address_prefix(addr_bytes): + if six.PY3: + prefix = addr_bytes[0] + else: + prefix = ord(addr_bytes[0]) + if prefix not in ADDRESS_PREFIXES[lbryschema.BLOCKCHAIN_NAME].values(): + raise InvalidAddress("Invalid address prefix: %.2X" % prefix) + + +def validate_lbrycrd_address_bytes(addr_bytes): + validate_address_length(addr_bytes) + validate_address_prefix(addr_bytes) + validate_b58_checksum(addr_bytes) + return addr_bytes + + +def decode_address(v): + """decode and validate a b58 address""" + return validate_lbrycrd_address_bytes(b58decode(v)) + + +def encode_address(addr_bytes): + """validate and encode an address as b58""" + v = validate_lbrycrd_address_bytes(addr_bytes) + return b58encode(v) + + +def hash_160_bytes_to_address(h160, addrtype=PUBKEY_ADDRESS): + if addrtype == PUBKEY_ADDRESS: + prefix = chr(ADDRESS_PREFIXES[lbryschema.BLOCKCHAIN_NAME][PUBKEY_ADDRESS]) + elif addrtype == SCRIPT_ADDRESS: + prefix = chr(ADDRESS_PREFIXES[lbryschema.BLOCKCHAIN_NAME][SCRIPT_ADDRESS]) + else: + raise Exception("Invalid address prefix") + return b58encode(prefix + h160 + double_sha256(prefix + h160)[0:4]) + + +def public_key_to_address(public_key): + return hash_160_bytes_to_address(hash160(public_key)) + + +def address_to_hash_160(addr): + bytes = decode_address(addr) + prefix, pubkey_bytes, addr_checksum = bytes[0], bytes[1:21], bytes[21:] + if prefix == chr(ADDRESS_PREFIXES[lbryschema.BLOCKCHAIN_NAME][PUBKEY_ADDRESS]): + return PUBKEY_ADDRESS, pubkey_bytes + return SCRIPT_ADDRESS, pubkey_bytes + + +def is_address(addr): + try: + addr_bytes = decode_address(addr) + return True + except InvalidAddress: + return False diff --git a/lbrynet/schema/base.py b/lbrynet/schema/base.py new file mode 100644 index 000000000..aa4745d77 --- /dev/null +++ b/lbrynet/schema/base.py @@ -0,0 +1,105 @@ +import six +from lbryschema.schema import ADDRESS_CHECKSUM_LENGTH +from lbryschema.hashing import double_sha256 +from lbryschema.error import InvalidAddress + + +alphabet = b'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' + + +if six.PY2: + iseq, bseq, buffer = ( + lambda s: map(ord, s), + lambda s: ''.join(map(chr, s)), + lambda s: s, + ) +elif six.PY3: + iseq, bseq, buffer = ( + lambda s: s, + bytes, + lambda s: s.buffer, + ) + + +def scrub_input(v): + if isinstance(v, str) and not isinstance(v, bytes): + v = v.encode('ascii') + return v + + +def b58encode_int(i, default_one=True): + '''Encode an integer using Base58''' + if not i and default_one: + return alphabet[0:1] + string = b"" + while i: + i, idx = divmod(i, 58) + string = alphabet[idx:idx+1] + string + return string + + +def b58encode(v): + '''Encode a string using Base58''' + + v = scrub_input(v) + + nPad = len(v) + v = v.lstrip(b'\0') + nPad -= len(v) + + p, acc = 1, 0 + for c in iseq(reversed(v)): + acc += p * c + p = p << 8 + + result = b58encode_int(acc, default_one=False) + + return alphabet[0:1] * nPad + result + + +def b58decode_int(v): + '''Decode a Base58 encoded string as an integer''' + + v = scrub_input(v) + + decimal = 0 + for char in v: + decimal = decimal * 58 + alphabet.index(char) + return decimal + + +def b58decode(v): + '''Decode a Base58 encoded string''' + + v = scrub_input(v) + + origlen = len(v) + v = v.lstrip(alphabet[0:1]) + newlen = len(v) + + acc = b58decode_int(v) + + result = [] + while acc > 0: + acc, mod = divmod(acc, 256) + result.append(mod) + + return (b'\0' * (origlen - newlen) + bseq(reversed(result))) + + +def validate_b58_checksum(addr_bytes): + addr_without_checksum = addr_bytes[:-ADDRESS_CHECKSUM_LENGTH] + addr_checksum = addr_bytes[-ADDRESS_CHECKSUM_LENGTH:] + if double_sha256(addr_without_checksum)[:ADDRESS_CHECKSUM_LENGTH] != addr_checksum: + raise InvalidAddress("Invalid address checksum") + + +def b58decode_strip_checksum(v): + addr_bytes = b58decode(v) + validate_b58_checksum(addr_bytes) + return addr_bytes[:-ADDRESS_CHECKSUM_LENGTH] + + +def b58encode_with_checksum(addr_bytes): + addr_checksum = double_sha256(addr_bytes)[:ADDRESS_CHECKSUM_LENGTH] + return b58encode(addr_bytes + addr_checksum) diff --git a/lbrynet/schema/claim.py b/lbrynet/schema/claim.py new file mode 100644 index 000000000..22027a7b7 --- /dev/null +++ b/lbrynet/schema/claim.py @@ -0,0 +1,193 @@ +import json +import binascii +from google.protobuf import json_format # pylint: disable=no-name-in-module +from google.protobuf.message import DecodeError as DecodeError_pb # pylint: disable=no-name-in-module,import-error + +from collections import OrderedDict + +from lbryschema.schema.claim import Claim +from lbryschema.proto import claim_pb2 +from lbryschema.validator import get_validator +from lbryschema.signer import get_signer +from lbryschema.schema import NIST256p, CURVE_NAMES, CLAIM_TYPE_NAMES +from lbryschema.encoding import decode_fields, decode_b64_fields, encode_fields +from lbryschema.error import DecodeError +from lbryschema.fee import Fee + + +class ClaimDict(OrderedDict): + def __init__(self, claim_dict=None): + if isinstance(claim_dict, claim_pb2.Claim): + raise Exception("To initialize %s with a Claim protobuf use %s.load_protobuf" % + (self.__class__.__name__, self.__class__.__name__)) + OrderedDict.__init__(self, claim_dict or []) + + @property + def protobuf_dict(self): + """Claim dictionary using base64 to represent bytes""" + + return json.loads(json_format.MessageToJson(self.protobuf, True)) + + @property + def protobuf(self): + """Claim message object""" + + return Claim.load(self) + + @property + def serialized(self): + """Serialized Claim protobuf""" + + return self.protobuf.SerializeToString() + + @property + def serialized_no_signature(self): + """Serialized Claim protobuf without publisherSignature field""" + claim = self.protobuf + claim.ClearField("publisherSignature") + return ClaimDict.load_protobuf(claim).serialized + + @property + def has_signature(self): + claim = self.protobuf + if claim.HasField("publisherSignature"): + return True + return False + + @property + def is_certificate(self): + claim = self.protobuf + return CLAIM_TYPE_NAMES[claim.claimType] == "certificate" + + @property + def is_stream(self): + claim = self.protobuf + return CLAIM_TYPE_NAMES[claim.claimType] == "stream" + + @property + def source_hash(self): + claim = self.protobuf + if not CLAIM_TYPE_NAMES[claim.claimType] == "stream": + return None + return binascii.hexlify(claim.stream.source.source) + + @property + def has_fee(self): + claim = self.protobuf + if not CLAIM_TYPE_NAMES[claim.claimType] == "stream": + return None + if claim.stream.metadata.HasField("fee"): + return True + return False + + @property + def source_fee(self): + claim = self.protobuf + if not CLAIM_TYPE_NAMES[claim.claimType] == "stream": + return None + if claim.stream.metadata.HasField("fee"): + return Fee.load_protobuf(claim.stream.metadata.fee) + return None + + @property + def certificate_id(self): + if not self.has_signature: + return None + return binascii.hexlify(self.protobuf.publisherSignature.certificateId) + + @property + def signature(self): + if not self.has_signature: + return None + return binascii.hexlify(self.protobuf.publisherSignature.signature) + + @property + def protobuf_len(self): + """Length of serialized string""" + + return self.protobuf.ByteSize() + + @property + def json_len(self): + """Length of json encoded string""" + + return len(json.dumps(self.claim_dict)) + + @property + def claim_dict(self): + """Claim dictionary with bytes represented as hex and base58""" + + return dict(encode_fields(self)) + + @classmethod + def load_protobuf_dict(cls, protobuf_dict): + """ + Load a ClaimDict from a dictionary with base64 encoded bytes + (as returned by the protobuf json formatter) + """ + + return cls(decode_b64_fields(protobuf_dict)) + + @classmethod + def load_protobuf(cls, protobuf_claim): + """Load ClaimDict from a protobuf Claim message""" + return cls.load_protobuf_dict(json.loads(json_format.MessageToJson(protobuf_claim, True))) + + @classmethod + def load_dict(cls, claim_dict): + """Load ClaimDict from a dictionary with hex and base58 encoded bytes""" + try: + return cls.load_protobuf(cls(decode_fields(claim_dict)).protobuf) + except json_format.ParseError as err: + raise DecodeError(str(err)) + + @classmethod + def deserialize(cls, serialized): + """Load a ClaimDict from a serialized protobuf string""" + + temp_claim = claim_pb2.Claim() + try: + temp_claim.ParseFromString(serialized) + except DecodeError_pb: + raise DecodeError(DecodeError_pb) + return cls.load_protobuf(temp_claim) + + @classmethod + def generate_certificate(cls, private_key, curve=NIST256p): + signer = get_signer(curve).load_pem(private_key) + return cls.load_protobuf(signer.certificate) + + def sign(self, private_key, claim_address, cert_claim_id, curve=NIST256p): + signer = get_signer(curve).load_pem(private_key) + signed = signer.sign_stream_claim(self, claim_address, cert_claim_id) + return ClaimDict.load_protobuf(signed) + + def validate_signature(self, claim_address, certificate): + if isinstance(certificate, ClaimDict): + certificate = certificate.protobuf + curve = CURVE_NAMES[certificate.certificate.keyType] + validator = get_validator(curve).load_from_certificate(certificate, self.certificate_id) + return validator.validate_claim_signature(self, claim_address) + + def validate_private_key(self, private_key, certificate_id): + certificate = self.protobuf + if CLAIM_TYPE_NAMES[certificate.claimType] != "certificate": + return + curve = CURVE_NAMES[certificate.certificate.keyType] + validator = get_validator(curve).load_from_certificate(certificate, certificate_id) + signing_key = validator.signing_key_from_pem(private_key) + return validator.validate_private_key(signing_key) + + def get_validator(self, certificate_id): + """ + Get a lbryschema.validator.Validator object for a certificate claim + + :param certificate_id: claim id of this certificate claim + :return: None or lbryschema.validator.Validator object + """ + + claim = self.protobuf + if CLAIM_TYPE_NAMES[claim.claimType] != "certificate": + return + curve = CURVE_NAMES[claim.certificate.keyType] + return get_validator(curve).load_from_certificate(claim, certificate_id) diff --git a/lbrynet/schema/decode.py b/lbrynet/schema/decode.py new file mode 100644 index 000000000..62db08ecc --- /dev/null +++ b/lbrynet/schema/decode.py @@ -0,0 +1,63 @@ +import json +import binascii + +import six + +from lbryschema.error import DecodeError, InvalidAddress +from lbryschema.legacy.migrate import migrate as schema_migrator +from lbryschema.claim import ClaimDict + +from google.protobuf import json_format # pylint: disable=no-name-in-module + + +def migrate_json_claim_value(decoded_json): + try: + if 'fee' in decoded_json: + old_fee = decoded_json['fee'] + if not old_fee[list(old_fee.keys())[0]]['amount']: + del decoded_json['fee'] + return migrate_json_claim_value(decoded_json) + except (TypeError, AttributeError, InvalidAddress): + raise DecodeError("Failed to decode claim") + try: + pb_migrated = schema_migrator(decoded_json) + return pb_migrated + except json_format.ParseError as parse_error: + raise DecodeError("Failed to parse protobuf: %s" % parse_error) + except Exception as err: + raise DecodeError("Failed to migrate claim: %s" % err) + + +def smart_decode(claim_value): + """ + Decode a claim value + + Try decoding claim protobuf, if this fails try decoding json and migrating it. + If unable to decode or migrate, raise DecodeError + """ + + # if already decoded, return + if isinstance(claim_value, ClaimDict): + return claim_value + elif isinstance(claim_value, dict): + return ClaimDict.load_dict(claim_value) + + try: + claim_value = binascii.unhexlify(claim_value) + except (TypeError, ValueError): + pass + + if claim_value[0] in ['{', ord('{')]: + try: + if six.PY3 and isinstance(claim_value, six.binary_type): + claim_value = claim_value.decode() + decoded_json = json.loads(claim_value) + return migrate_json_claim_value(decoded_json) + except (ValueError, TypeError): + pass + try: + if six.PY3 and isinstance(claim_value, six.text_type): + claim_value = claim_value.encode() + return ClaimDict.deserialize(claim_value) + except (DecodeError, InvalidAddress, KeyError, TypeError): + raise DecodeError(claim_value) diff --git a/lbrynet/schema/encoding.py b/lbrynet/schema/encoding.py new file mode 100644 index 000000000..8090f5780 --- /dev/null +++ b/lbrynet/schema/encoding.py @@ -0,0 +1,78 @@ +import base64, binascii +from copy import deepcopy +from lbryschema.address import decode_address, encode_address +from lbryschema.schema import CLAIM_TYPES, CLAIM_TYPE, STREAM_TYPE, CERTIFICATE_TYPE +from lbryschema.schema import SIGNATURE +from lbryschema.error import DecodeError, InvalidAddress + + +def encode_fields(claim_dictionary): + """Encode bytes to hex and b58 for return by ClaimDict""" + claim_dictionary = deepcopy(claim_dictionary) + claim_type = CLAIM_TYPES[claim_dictionary[CLAIM_TYPE]] + claim_value = claim_dictionary[claim_type] + if claim_type == CLAIM_TYPES[STREAM_TYPE]: + claim_value['source']['source'] = binascii.hexlify(claim_value['source']['source']).decode() + if 'fee' in claim_value['metadata']: + try: + address = encode_address(claim_value['metadata']['fee']['address']) + except InvalidAddress as err: + raise DecodeError("Invalid fee address: %s" % err) + claim_value['metadata']['fee']['address'] = address + elif claim_type == CLAIM_TYPES[CERTIFICATE_TYPE]: + public_key = claim_value["publicKey"] + claim_value["publicKey"] = binascii.hexlify(public_key).decode() + if SIGNATURE in claim_dictionary: + encoded_sig = binascii.hexlify(claim_dictionary[SIGNATURE]['signature']).decode() + encoded_cert_id = binascii.hexlify(claim_dictionary[SIGNATURE]['certificateId']).decode() + claim_dictionary[SIGNATURE]['signature'] = encoded_sig + claim_dictionary[SIGNATURE]['certificateId'] = encoded_cert_id + claim_dictionary[claim_type] = claim_value + return claim_dictionary + + +def decode_fields(claim_dictionary): + """Decode hex and b58 encoded bytes in dictionaries given to ClaimDict""" + claim_dictionary = deepcopy(claim_dictionary) + claim_type = CLAIM_TYPES[claim_dictionary[CLAIM_TYPE]] + claim_value = claim_dictionary[claim_type] + if claim_type == CLAIM_TYPES[STREAM_TYPE]: + claim_value['source']['source'] = binascii.unhexlify(claim_value['source']['source']) + if 'fee' in claim_value['metadata']: + try: + address = decode_address(claim_value['metadata']['fee']['address']) + except InvalidAddress as err: + raise DecodeError("Invalid fee address: %s" % err) + claim_value['metadata']['fee']['address'] = address + elif claim_type == CLAIM_TYPES[CERTIFICATE_TYPE]: + public_key = binascii.unhexlify(claim_value["publicKey"]) + claim_value["publicKey"] = public_key + if SIGNATURE in claim_dictionary: + decoded_sig = binascii.unhexlify(claim_dictionary[SIGNATURE]['signature']) + decoded_cert_id = binascii.unhexlify(claim_dictionary[SIGNATURE]['certificateId']) + claim_dictionary[SIGNATURE]['signature'] = decoded_sig + claim_dictionary[SIGNATURE]['certificateId'] = decoded_cert_id + claim_dictionary[claim_type] = claim_value + return claim_dictionary + + +def decode_b64_fields(claim_dictionary): + """Decode b64 encoded bytes in protobuf generated dictionary to be given to ClaimDict""" + claim_dictionary = deepcopy(claim_dictionary) + claim_type = CLAIM_TYPES[claim_dictionary[CLAIM_TYPE]] + claim_value = claim_dictionary[claim_type] + if claim_type == CLAIM_TYPES[STREAM_TYPE]: + claim_value['source']['source'] = base64.b64decode(claim_value['source']['source']) + if 'fee' in claim_value['metadata']: + address = base64.b64decode(claim_value['metadata']['fee']['address']) + claim_value['metadata']['fee']['address'] = address + elif claim_type == CLAIM_TYPES[CERTIFICATE_TYPE]: + public_key = base64.b64decode(claim_value["publicKey"]) + claim_value["publicKey"] = public_key + if SIGNATURE in claim_dictionary: + encoded_sig = base64.b64decode(claim_dictionary[SIGNATURE]['signature']) + encoded_cert_id = base64.b64decode(claim_dictionary[SIGNATURE]['certificateId']) + claim_dictionary[SIGNATURE]['signature'] = encoded_sig + claim_dictionary[SIGNATURE]['certificateId'] = encoded_cert_id + claim_dictionary[claim_type] = claim_value + return claim_dictionary diff --git a/lbrynet/schema/error.py b/lbrynet/schema/error.py new file mode 100644 index 000000000..57d50293a --- /dev/null +++ b/lbrynet/schema/error.py @@ -0,0 +1,22 @@ +class UnknownSourceType(Exception): + pass + + +class InvalidSourceHashLength(Exception): + pass + + +class DecodeError(Exception): + pass + + +class URIParseError(Exception): + pass + + +class CertificateError(Exception): + pass + + +class InvalidAddress(Exception): + pass diff --git a/lbrynet/schema/fee.py b/lbrynet/schema/fee.py new file mode 100644 index 000000000..d327d5441 --- /dev/null +++ b/lbrynet/schema/fee.py @@ -0,0 +1,79 @@ +from collections import OrderedDict + +from lbryschema.address import encode_address, decode_address +from lbryschema.schema import CURRENCY_NAMES, CURRENCY_MAP +from lbryschema.schema.fee import Fee as FeeHelper +from lbryschema.proto import fee_pb2 + + +def migrate(fee): + if len(list(fee.keys())) == 3 and 'currency' in fee and 'amount' in fee and 'address' in fee: + return FeeHelper.load({ + "version": "_0_0_1", + "currency": fee['currency'], + "amount": fee['amount'], + "address": decode_address(fee['address']) + }) + if len(list(fee.keys())) > 1: + raise Exception("Invalid fee") + + currency = list(fee.keys())[0] + amount = fee[currency]['amount'] + address = fee[currency]['address'] + + return FeeHelper.load({ + "version": "_0_0_1", + "currency": currency, + "amount": amount, + "address": decode_address(address) + }) + + +class Fee(OrderedDict): + def __init__(self, fee): + if (len(fee) == 4 and "version" in fee and "currency" in fee + and "amount" in fee and "address" in fee): + OrderedDict.__init__(self, fee) + else: + OrderedDict.__init__(self, Fee.load_protobuf(migrate(fee))) + + @property + def currency(self): + return self['currency'] + + @property + def address(self): + return self['address'] + + @property + def amount(self): + return self['amount'] + + @property + def version(self): + return self['version'] + + @property + def protobuf(self): + pb = { + "version": self.version, + "currency": CURRENCY_MAP[self.currency], + "address": decode_address(self.address), + "amount": self.amount + } + return FeeHelper.load(pb) + + @classmethod + def load_protobuf(cls, pb): + return cls({ + "version": pb.version, + "currency": CURRENCY_NAMES[pb.currency], + "address": encode_address(pb.address), + "amount": pb.amount + }) + + @classmethod + def deserialize(cls, serialized): + pb = fee_pb2.Fee() + pb.ParseFromString(serialized) + return cls.load_protobuf(pb) diff --git a/lbrynet/schema/hashing.py b/lbrynet/schema/hashing.py new file mode 100644 index 000000000..1b2adc5ee --- /dev/null +++ b/lbrynet/schema/hashing.py @@ -0,0 +1,24 @@ +import six +import hashlib + + +def sha256(x): + if isinstance(x, six.text_type): + x = x.encode('utf-8') + return hashlib.sha256(x).digest() + + +def double_sha256(x): + return sha256(sha256(x)) + + +def ripemd160(x): + if isinstance(x, six.text_type): + x = x.encode('utf-8') + md = hashlib.new('ripemd160') + md.update(x) + return md.digest() + + +def hash160(x): + return ripemd160(sha256(x)) diff --git a/lbrynet/schema/legacy/StructuredDict.py b/lbrynet/schema/legacy/StructuredDict.py new file mode 100644 index 000000000..31442d0d8 --- /dev/null +++ b/lbrynet/schema/legacy/StructuredDict.py @@ -0,0 +1,59 @@ +import jsonschema + + +class StructuredDict(dict): + """ + A dictionary that enforces a structure specified by a schema, and supports + migration between different versions of the schema. + """ + + # To be specified in sub-classes, an array in the format + # [(version, schema, migration), ...] + _versions = [] + + # Used internally to allow schema lookups by version number + _schemas = {} + + version = None + + def __init__(self, value, starting_version, migrate=True, target_version=None): + dict.__init__(self, value) + + self.version = starting_version + self._schemas = dict([(version, schema) for (version, schema, _) in self._versions]) + + self.validate(starting_version) + + if migrate: + self.migrate(target_version) + + def _upgrade_version_range(self, start_version, end_version): + after_starting_version = False + for version, schema, migration in self._versions: + if not after_starting_version: + if version == self.version: + after_starting_version = True + continue + + yield version, schema, migration + + if end_version and version == end_version: + break + + def validate(self, version): + jsonschema.validate(self, self._schemas[version]) + + def migrate(self, target_version=None): + if target_version: + assert self._versions.index(target_version) > self._versions.index(self.version), \ + "Current version is above target version" + + for version, schema, migration in self._upgrade_version_range(self.version, target_version): + migration(self) + try: + self.validate(version) + except jsonschema.ValidationError as e: + raise jsonschema.ValidationError( + "Could not migrate to version %s due to validation error: %s" % + (version, e.message)) + self.version = version diff --git a/lbrynet/schema/legacy/__init__.py b/lbrynet/schema/legacy/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/lbrynet/schema/legacy/metadata_schemas.py b/lbrynet/schema/legacy/metadata_schemas.py new file mode 100644 index 000000000..6165ccaa6 --- /dev/null +++ b/lbrynet/schema/legacy/metadata_schemas.py @@ -0,0 +1,276 @@ +VER_001 = { + '$schema': 'http://json-schema.org/draft-04/schema#', + 'title': 'LBRY metadata schema 0.0.1', + 'definitions': { + 'fee_info': { + 'type': 'object', + 'properties': { + 'amount': { + 'type': 'number', + 'minimum': 0, + 'exclusiveMinimum': True, + }, + 'address': { + 'type': 'string' + } + }, + } + }, + 'type': 'object', + + 'properties': { + 'ver': { + 'type': 'string', + 'default': '0.0.1' + }, + 'title': { + 'type': 'string' + }, + 'description': { + 'type': 'string' + }, + 'author': { + 'type': 'string' + }, + 'language': { + 'type': 'string' + }, + 'license': { + 'type': 'string' + }, + 'content-type': { + 'type': 'string' + }, + 'sources': { + 'type': 'object', + 'properties': { + 'lbry_sd_hash': { + 'type': 'string' + }, + 'btih': { + 'type': 'string' + }, + 'url': { + 'type': 'string' + } + }, + 'additionalProperties': False + }, + 'thumbnail': { + 'type': 'string' + }, + 'preview': { + 'type': 'string' + }, + 'fee': { + 'properties': { + 'LBC': {'$ref': '#/definitions/fee_info'}, + 'BTC': {'$ref': '#/definitions/fee_info'}, + 'USD': {'$ref': '#/definitions/fee_info'} + } + }, + 'contact': { + 'type': 'number' + }, + 'pubkey': { + 'type': 'string' + }, + }, + 'required': [ + 'title', 'description', 'author', 'language', 'license', 'content-type', 'sources'], + 'additionalProperties': False +} + + +VER_002 = { + '$schema': 'http://json-schema.org/draft-04/schema#', + 'title': 'LBRY metadata schema 0.0.2', + 'definitions': { + 'fee_info': { + 'type': 'object', + 'properties': { + 'amount': { + 'type': 'number', + 'minimum': 0, + 'exclusiveMinimum': True, + }, + 'address': { + 'type': 'string' + } + }, + } + }, + 'type': 'object', + + 'properties': { + 'ver': { + 'type': 'string', + 'enum': ['0.0.2'], + }, + 'title': { + 'type': 'string' + }, + 'description': { + 'type': 'string' + }, + 'author': { + 'type': 'string' + }, + 'language': { + 'type': 'string' + }, + 'license': { + 'type': 'string' + }, + 'content-type': { + 'type': 'string' + }, + 'sources': { + 'type': 'object', + 'properties': { + 'lbry_sd_hash': { + 'type': 'string' + }, + 'btih': { + 'type': 'string' + }, + 'url': { + 'type': 'string' + } + }, + 'additionalProperties': False + }, + 'thumbnail': { + 'type': 'string' + }, + 'preview': { + 'type': 'string' + }, + 'fee': { + 'properties': { + 'LBC': {'$ref': '#/definitions/fee_info'}, + 'BTC': {'$ref': '#/definitions/fee_info'}, + 'USD': {'$ref': '#/definitions/fee_info'} + } + }, + 'contact': { + 'type': 'number' + }, + 'pubkey': { + 'type': 'string' + }, + 'license_url': { + 'type': 'string' + }, + 'nsfw': { + 'type': 'boolean', + 'default': False + }, + + }, + 'required': [ + 'ver', 'title', 'description', 'author', 'language', 'license', + 'content-type', 'sources', 'nsfw' + ], + 'additionalProperties': False +} + + +VER_003 = { + '$schema': 'http://json-schema.org/draft-04/schema#', + 'title': 'LBRY metadata schema 0.0.3', + 'definitions': { + 'fee_info': { + 'type': 'object', + 'properties': { + 'amount': { + 'type': 'number', + 'minimum': 0, + 'exclusiveMinimum': True, + }, + 'address': { + 'type': 'string' + } + }, + } + }, + 'type': 'object', + + 'properties': { + 'ver': { + 'type': 'string', + 'enum': ['0.0.3'], + }, + 'title': { + 'type': 'string' + }, + 'description': { + 'type': 'string' + }, + 'author': { + 'type': 'string' + }, + 'language': { + 'type': 'string' + }, + 'license': { + 'type': 'string' + }, + 'content_type': { + 'type': 'string' + }, + 'sources': { + 'type': 'object', + 'properties': { + 'lbry_sd_hash': { + 'type': 'string' + }, + 'btih': { + 'type': 'string' + }, + 'url': { + 'type': 'string' + } + }, + 'additionalProperties': False + }, + 'thumbnail': { + 'type': 'string' + }, + 'preview': { + 'type': 'string' + }, + 'fee': { + 'properties': { + 'LBC': {'$ref': '#/definitions/fee_info'}, + 'BTC': {'$ref': '#/definitions/fee_info'}, + 'USD': {'$ref': '#/definitions/fee_info'} + } + }, + 'contact': { + 'type': 'number' + }, + 'pubkey': { + 'type': 'string' + }, + 'license_url': { + 'type': 'string' + }, + 'nsfw': { + 'type': 'boolean', + 'default': False + }, + 'sig': { + 'type': 'string' + } + }, + 'required': [ + 'ver', 'title', 'description', 'author', 'language', 'license', + 'content_type', 'sources', 'nsfw' + ], + 'additionalProperties': False, + 'dependencies': { + 'pubkey': ['sig'], + 'sig': ['pubkey'] + } +} diff --git a/lbrynet/schema/legacy/migrate.py b/lbrynet/schema/legacy/migrate.py new file mode 100644 index 000000000..006947a2d --- /dev/null +++ b/lbrynet/schema/legacy/migrate.py @@ -0,0 +1,79 @@ +""" +migrate claim json schema (0.0.1-3) to protobuf (0.1.0) +""" + +from lbryschema.legacy import metadata_schemas +from lbryschema.claim import ClaimDict +from .StructuredDict import StructuredDict + + +def migrate_001_to_002(metadata): + metadata['ver'] = '0.0.2' + metadata['nsfw'] = False + + +def migrate_002_to_003(metadata): + metadata['ver'] = '0.0.3' + if 'content-type' in metadata: + metadata['content_type'] = metadata['content-type'] + del metadata['content-type'] + + +class LegacyMetadata(StructuredDict): + current_version = '0.0.3' + + _versions = [ + ('0.0.1', metadata_schemas.VER_001, None), + ('0.0.2', metadata_schemas.VER_002, migrate_001_to_002), + ('0.0.3', metadata_schemas.VER_003, migrate_002_to_003) + ] + + def __init__(self, metadata, migrate=True, target_version=None): + if not isinstance(metadata, dict): + raise TypeError("{} is not a dictionary".format(metadata)) + starting_version = metadata.get('ver', '0.0.1') + + StructuredDict.__init__(self, metadata, starting_version, migrate, target_version) + + +def migrate_003_to_010(value): + migrated_to_003 = LegacyMetadata(value) + metadata = { + "version": "_0_1_0" + } + for k in ["author", "description", "language", "license", "nsfw", "thumbnail", "title", + "preview"]: + if k in migrated_to_003: + metadata.update({k: migrated_to_003[k]}) + + if 'license_url' in migrated_to_003: + metadata['licenseUrl'] = migrated_to_003['license_url'] + + if "fee" in migrated_to_003: + fee = migrated_to_003["fee"] + currency = list(fee.keys())[0] + amount = fee[currency]['amount'] + address = fee[currency]['address'] + metadata.update(dict(fee={"currency": currency, "version": "_0_0_1", + "amount": amount, "address": address})) + source = { + "source": migrated_to_003['sources']['lbry_sd_hash'], + "contentType": migrated_to_003['content_type'], + "sourceType": "lbry_sd_hash", + "version": "_0_0_1" + } + + migrated = { + "version": "_0_0_1", + "claimType": "streamType", + "stream": { + "version": "_0_0_1", + "metadata": metadata, + "source": source + } + } + return ClaimDict.load_dict(migrated) + + +def migrate(value): + return migrate_003_to_010(value) diff --git a/lbrynet/schema/proto/__init__.py b/lbrynet/schema/proto/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/lbrynet/schema/proto/certificate.proto b/lbrynet/schema/proto/certificate.proto new file mode 100644 index 000000000..dc5f66ea8 --- /dev/null +++ b/lbrynet/schema/proto/certificate.proto @@ -0,0 +1,18 @@ +syntax = "proto2"; + +enum KeyType { + UNKNOWN_PUBLIC_KEY_TYPE = 0; + NIST256p = 1; + NIST384p = 2; + SECP256k1 = 3; +} + +message Certificate { + enum Version { + UNKNOWN_VERSION = 0; + _0_0_1 = 1; + } + required Version version = 1; + required KeyType keyType = 2; + required bytes publicKey = 4; +} diff --git a/lbrynet/schema/proto/certificate_pb2.py b/lbrynet/schema/proto/certificate_pb2.py new file mode 100644 index 000000000..c9dc6c79f --- /dev/null +++ b/lbrynet/schema/proto/certificate_pb2.py @@ -0,0 +1,144 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: lbryschema/proto/certificate.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='lbryschema/proto/certificate.proto', + package='', + serialized_pb=_b('\n\"lbryschema/proto/certificate.proto\"\x8e\x01\n\x0b\x43\x65rtificate\x12%\n\x07version\x18\x01 \x02(\x0e\x32\x14.Certificate.Version\x12\x19\n\x07keyType\x18\x02 \x02(\x0e\x32\x08.KeyType\x12\x11\n\tpublicKey\x18\x04 \x02(\x0c\"*\n\x07Version\x12\x13\n\x0fUNKNOWN_VERSION\x10\x00\x12\n\n\x06_0_0_1\x10\x01*Q\n\x07KeyType\x12\x1b\n\x17UNKNOWN_PUBLIC_KEY_TYPE\x10\x00\x12\x0c\n\x08NIST256p\x10\x01\x12\x0c\n\x08NIST384p\x10\x02\x12\r\n\tSECP256k1\x10\x03') +) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +_KEYTYPE = _descriptor.EnumDescriptor( + name='KeyType', + full_name='KeyType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_PUBLIC_KEY_TYPE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NIST256p', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NIST384p', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SECP256k1', index=3, number=3, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=183, + serialized_end=264, +) +_sym_db.RegisterEnumDescriptor(_KEYTYPE) + +KeyType = enum_type_wrapper.EnumTypeWrapper(_KEYTYPE) +UNKNOWN_PUBLIC_KEY_TYPE = 0 +NIST256p = 1 +NIST384p = 2 +SECP256k1 = 3 + + +_CERTIFICATE_VERSION = _descriptor.EnumDescriptor( + name='Version', + full_name='Certificate.Version', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_VERSION', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='_0_0_1', index=1, number=1, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=139, + serialized_end=181, +) +_sym_db.RegisterEnumDescriptor(_CERTIFICATE_VERSION) + + +_CERTIFICATE = _descriptor.Descriptor( + name='Certificate', + full_name='Certificate', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='version', full_name='Certificate.version', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='keyType', full_name='Certificate.keyType', index=1, + number=2, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='publicKey', full_name='Certificate.publicKey', index=2, + number=4, type=12, cpp_type=9, label=2, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _CERTIFICATE_VERSION, + ], + options=None, + is_extendable=False, + extension_ranges=[], + oneofs=[ + ], + serialized_start=39, + serialized_end=181, +) + +_CERTIFICATE.fields_by_name['version'].enum_type = _CERTIFICATE_VERSION +_CERTIFICATE.fields_by_name['keyType'].enum_type = _KEYTYPE +_CERTIFICATE_VERSION.containing_type = _CERTIFICATE +DESCRIPTOR.message_types_by_name['Certificate'] = _CERTIFICATE +DESCRIPTOR.enum_types_by_name['KeyType'] = _KEYTYPE + +Certificate = _reflection.GeneratedProtocolMessageType('Certificate', (_message.Message,), dict( + DESCRIPTOR = _CERTIFICATE, + __module__ = 'lbryschema.proto.certificate_pb2' + # @@protoc_insertion_point(class_scope:Certificate) + )) +_sym_db.RegisterMessage(Certificate) + + +# @@protoc_insertion_point(module_scope) diff --git a/lbrynet/schema/proto/claim.proto b/lbrynet/schema/proto/claim.proto new file mode 100644 index 000000000..5557a30f6 --- /dev/null +++ b/lbrynet/schema/proto/claim.proto @@ -0,0 +1,22 @@ +syntax = "proto2"; + +import "lbryschema/proto/stream.proto"; +import "lbryschema/proto/certificate.proto"; +import "lbryschema/proto/signature.proto"; + +message Claim { + enum Version { + UNKNOWN_VERSION = 0; + _0_0_1 = 1; + } + required Version version = 1; + enum ClaimType { + UNKNOWN_CLAIM_TYPE = 0; + streamType = 1; + certificateType = 2; + } + required ClaimType claimType = 2; + optional Stream stream = 3; + optional Certificate certificate = 4; + optional Signature publisherSignature = 5; +} diff --git a/lbrynet/schema/proto/claim_pb2.py b/lbrynet/schema/proto/claim_pb2.py new file mode 100644 index 000000000..457bd17d5 --- /dev/null +++ b/lbrynet/schema/proto/claim_pb2.py @@ -0,0 +1,156 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: lbryschema/proto/claim.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import lbryschema.proto.stream_pb2 +import lbryschema.proto.certificate_pb2 +import lbryschema.proto.signature_pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='lbryschema/proto/claim.proto', + package='', + serialized_pb=_b('\n\x1clbryschema/proto/claim.proto\x1a\x1dlbryschema/proto/stream.proto\x1a\"lbryschema/proto/certificate.proto\x1a lbryschema/proto/signature.proto\"\xa7\x02\n\x05\x43laim\x12\x1f\n\x07version\x18\x01 \x02(\x0e\x32\x0e.Claim.Version\x12#\n\tclaimType\x18\x02 \x02(\x0e\x32\x10.Claim.ClaimType\x12\x17\n\x06stream\x18\x03 \x01(\x0b\x32\x07.Stream\x12!\n\x0b\x63\x65rtificate\x18\x04 \x01(\x0b\x32\x0c.Certificate\x12&\n\x12publisherSignature\x18\x05 \x01(\x0b\x32\n.Signature\"*\n\x07Version\x12\x13\n\x0fUNKNOWN_VERSION\x10\x00\x12\n\n\x06_0_0_1\x10\x01\"H\n\tClaimType\x12\x16\n\x12UNKNOWN_CLAIM_TYPE\x10\x00\x12\x0e\n\nstreamType\x10\x01\x12\x13\n\x0f\x63\x65rtificateType\x10\x02') + , + dependencies=[lbryschema.proto.stream_pb2.DESCRIPTOR,lbryschema.proto.certificate_pb2.DESCRIPTOR,lbryschema.proto.signature_pb2.DESCRIPTOR,]) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + + + +_CLAIM_VERSION = _descriptor.EnumDescriptor( + name='Version', + full_name='Claim.Version', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_VERSION', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='_0_0_1', index=1, number=1, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=313, + serialized_end=355, +) +_sym_db.RegisterEnumDescriptor(_CLAIM_VERSION) + +_CLAIM_CLAIMTYPE = _descriptor.EnumDescriptor( + name='ClaimType', + full_name='Claim.ClaimType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_CLAIM_TYPE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='streamType', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='certificateType', index=2, number=2, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=357, + serialized_end=429, +) +_sym_db.RegisterEnumDescriptor(_CLAIM_CLAIMTYPE) + + +_CLAIM = _descriptor.Descriptor( + name='Claim', + full_name='Claim', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='version', full_name='Claim.version', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='claimType', full_name='Claim.claimType', index=1, + number=2, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='stream', full_name='Claim.stream', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='certificate', full_name='Claim.certificate', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='publisherSignature', full_name='Claim.publisherSignature', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _CLAIM_VERSION, + _CLAIM_CLAIMTYPE, + ], + options=None, + is_extendable=False, + extension_ranges=[], + oneofs=[ + ], + serialized_start=134, + serialized_end=429, +) + +_CLAIM.fields_by_name['version'].enum_type = _CLAIM_VERSION +_CLAIM.fields_by_name['claimType'].enum_type = _CLAIM_CLAIMTYPE +_CLAIM.fields_by_name['stream'].message_type = lbryschema.proto.stream_pb2._STREAM +_CLAIM.fields_by_name['certificate'].message_type = lbryschema.proto.certificate_pb2._CERTIFICATE +_CLAIM.fields_by_name['publisherSignature'].message_type = lbryschema.proto.signature_pb2._SIGNATURE +_CLAIM_VERSION.containing_type = _CLAIM +_CLAIM_CLAIMTYPE.containing_type = _CLAIM +DESCRIPTOR.message_types_by_name['Claim'] = _CLAIM + +Claim = _reflection.GeneratedProtocolMessageType('Claim', (_message.Message,), dict( + DESCRIPTOR = _CLAIM, + __module__ = 'lbryschema.proto.claim_pb2' + # @@protoc_insertion_point(class_scope:Claim) + )) +_sym_db.RegisterMessage(Claim) + + +# @@protoc_insertion_point(module_scope) diff --git a/lbrynet/schema/proto/fee.proto b/lbrynet/schema/proto/fee.proto new file mode 100644 index 000000000..c666eaa6c --- /dev/null +++ b/lbrynet/schema/proto/fee.proto @@ -0,0 +1,18 @@ +syntax = "proto2"; + +message Fee { + enum Version { + UNKNOWN_VERSION = 0; + _0_0_1 = 1; + } + enum Currency { + UNKNOWN_CURRENCY = 0; + LBC = 1; + BTC = 2; + USD = 3; + } + required Version version = 1; + required Currency currency = 2; + required bytes address = 3; + required float amount = 4; +} diff --git a/lbrynet/schema/proto/fee_pb2.py b/lbrynet/schema/proto/fee_pb2.py new file mode 100644 index 000000000..55493f761 --- /dev/null +++ b/lbrynet/schema/proto/fee_pb2.py @@ -0,0 +1,146 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: lbryschema/proto/fee.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='lbryschema/proto/fee.proto', + package='', + serialized_pb=_b('\n\x1albryschema/proto/fee.proto\"\xcf\x01\n\x03\x46\x65\x65\x12\x1d\n\x07version\x18\x01 \x02(\x0e\x32\x0c.Fee.Version\x12\x1f\n\x08\x63urrency\x18\x02 \x02(\x0e\x32\r.Fee.Currency\x12\x0f\n\x07\x61\x64\x64ress\x18\x03 \x02(\x0c\x12\x0e\n\x06\x61mount\x18\x04 \x02(\x02\"*\n\x07Version\x12\x13\n\x0fUNKNOWN_VERSION\x10\x00\x12\n\n\x06_0_0_1\x10\x01\";\n\x08\x43urrency\x12\x14\n\x10UNKNOWN_CURRENCY\x10\x00\x12\x07\n\x03LBC\x10\x01\x12\x07\n\x03\x42TC\x10\x02\x12\x07\n\x03USD\x10\x03') +) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + + + +_FEE_VERSION = _descriptor.EnumDescriptor( + name='Version', + full_name='Fee.Version', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_VERSION', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='_0_0_1', index=1, number=1, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=135, + serialized_end=177, +) +_sym_db.RegisterEnumDescriptor(_FEE_VERSION) + +_FEE_CURRENCY = _descriptor.EnumDescriptor( + name='Currency', + full_name='Fee.Currency', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_CURRENCY', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LBC', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BTC', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='USD', index=3, number=3, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=179, + serialized_end=238, +) +_sym_db.RegisterEnumDescriptor(_FEE_CURRENCY) + + +_FEE = _descriptor.Descriptor( + name='Fee', + full_name='Fee', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='version', full_name='Fee.version', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='currency', full_name='Fee.currency', index=1, + number=2, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='address', full_name='Fee.address', index=2, + number=3, type=12, cpp_type=9, label=2, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='amount', full_name='Fee.amount', index=3, + number=4, type=2, cpp_type=6, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _FEE_VERSION, + _FEE_CURRENCY, + ], + options=None, + is_extendable=False, + extension_ranges=[], + oneofs=[ + ], + serialized_start=31, + serialized_end=238, +) + +_FEE.fields_by_name['version'].enum_type = _FEE_VERSION +_FEE.fields_by_name['currency'].enum_type = _FEE_CURRENCY +_FEE_VERSION.containing_type = _FEE +_FEE_CURRENCY.containing_type = _FEE +DESCRIPTOR.message_types_by_name['Fee'] = _FEE + +Fee = _reflection.GeneratedProtocolMessageType('Fee', (_message.Message,), dict( + DESCRIPTOR = _FEE, + __module__ = 'lbryschema.proto.fee_pb2' + # @@protoc_insertion_point(class_scope:Fee) + )) +_sym_db.RegisterMessage(Fee) + + +# @@protoc_insertion_point(module_scope) diff --git a/lbrynet/schema/proto/metadata.proto b/lbrynet/schema/proto/metadata.proto new file mode 100644 index 000000000..a9485485a --- /dev/null +++ b/lbrynet/schema/proto/metadata.proto @@ -0,0 +1,212 @@ +syntax = "proto2"; + +import "lbryschema/proto/fee.proto"; + +message Metadata { + enum Version { + UNKNOWN_VERSION = 0; + _0_0_1 = 1; + _0_0_2 = 2; + _0_0_3 = 3; + _0_1_0 = 4; + } + enum Language { + UNKNOWN_LANGUAGE = 0; + en = 1; + aa = 2; + ab = 3; + ae = 4; + af = 5; + ak = 6; + am = 7; + an = 8; + ar = 9; + as = 10; + av = 11; + ay = 12; + az = 13; + ba = 14; + be = 15; + bg = 16; + bh = 17; + bi = 18; + bm = 19; + bn = 20; + bo = 21; + br = 22; + bs = 23; + ca = 24; + ce = 25; + ch = 26; + co = 27; + cr = 28; + cs = 29; + cu = 30; + cv = 31; + cy = 32; + da = 33; + de = 34; + dv = 35; + dz = 36; + ee = 37; + el = 38; + eo = 39; + es = 40; + et = 41; + eu = 42; + fa = 43; + ff = 44; + fi = 45; + fj = 46; + fo = 47; + fr = 48; + fy = 49; + ga = 50; + gd = 51; + gl = 52; + gn = 53; + gu = 54; + gv = 55; + ha = 56; + he = 57; + hi = 58; + ho = 59; + hr = 60; + ht = 61; + hu = 62; + hy = 63; + hz = 64; + ia = 65; + id = 66; + ie = 67; + ig = 68; + ii = 69; + ik = 70; + io = 71; + is = 72; + it = 73; + iu = 74; + ja = 75; + jv = 76; + ka = 77; + kg = 78; + ki = 79; + kj = 80; + kk = 81; + kl = 82; + km = 83; + kn = 84; + ko = 85; + kr = 86; + ks = 87; + ku = 88; + kv = 89; + kw = 90; + ky = 91; + la = 92; + lb = 93; + lg = 94; + li = 95; + ln = 96; + lo = 97; + lt = 98; + lu = 99; + lv = 100; + mg = 101; + mh = 102; + mi = 103; + mk = 104; + ml = 105; + mn = 106; + mr = 107; + ms = 108; + mt = 109; + my = 110; + na = 111; + nb = 112; + nd = 113; + ne = 114; + ng = 115; + nl = 116; + nn = 117; + no = 118; + nr = 119; + nv = 120; + ny = 121; + oc = 122; + oj = 123; + om = 124; + or = 125; + os = 126; + pa = 127; + pi = 128; + pl = 129; + ps = 130; + pt = 131; + qu = 132; + rm = 133; + rn = 134; + ro = 135; + ru = 136; + rw = 137; + sa = 138; + sc = 139; + sd = 140; + se = 141; + sg = 142; + si = 143; + sk = 144; + sl = 145; + sm = 146; + sn = 147; + so = 148; + sq = 149; + sr = 150; + ss = 151; + st = 152; + su = 153; + sv = 154; + sw = 155; + ta = 156; + te = 157; + tg = 158; + th = 159; + ti = 160; + tk = 161; + tl = 162; + tn = 163; + to = 164; + tr = 165; + ts = 166; + tt = 167; + tw = 168; + ty = 169; + ug = 170; + uk = 171; + ur = 172; + uz = 173; + ve = 174; + vi = 175; + vo = 176; + wa = 177; + wo = 178; + xh = 179; + yi = 180; + yo = 181; + za = 182; + zh = 183; + zu = 184; + } + required Version version = 1; + required Language language = 2; + required string title = 3; + required string description = 4; + required string author = 5; + required string license = 6; + required bool nsfw = 7; + + optional Fee fee = 8; + optional string thumbnail = 9; + optional string preview = 10; + optional string licenseUrl = 11; +} diff --git a/lbrynet/schema/proto/metadata_pb2.py b/lbrynet/schema/proto/metadata_pb2.py new file mode 100644 index 000000000..4f000c757 --- /dev/null +++ b/lbrynet/schema/proto/metadata_pb2.py @@ -0,0 +1,934 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: lbryschema/proto/metadata.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import lbryschema.proto.fee_pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='lbryschema/proto/metadata.proto', + package='', + serialized_pb=_b('\n\x1flbryschema/proto/metadata.proto\x1a\x1albryschema/proto/fee.proto\"\xde\x0e\n\x08Metadata\x12\"\n\x07version\x18\x01 \x02(\x0e\x32\x11.Metadata.Version\x12$\n\x08language\x18\x02 \x02(\x0e\x32\x12.Metadata.Language\x12\r\n\x05title\x18\x03 \x02(\t\x12\x13\n\x0b\x64\x65scription\x18\x04 \x02(\t\x12\x0e\n\x06\x61uthor\x18\x05 \x02(\t\x12\x0f\n\x07license\x18\x06 \x02(\t\x12\x0c\n\x04nsfw\x18\x07 \x02(\x08\x12\x11\n\x03\x66\x65\x65\x18\x08 \x01(\x0b\x32\x04.Fee\x12\x11\n\tthumbnail\x18\t \x01(\t\x12\x0f\n\x07preview\x18\n \x01(\t\x12\x12\n\nlicenseUrl\x18\x0b \x01(\t\"N\n\x07Version\x12\x13\n\x0fUNKNOWN_VERSION\x10\x00\x12\n\n\x06_0_0_1\x10\x01\x12\n\n\x06_0_0_2\x10\x02\x12\n\n\x06_0_0_3\x10\x03\x12\n\n\x06_0_1_0\x10\x04\"\x99\x0c\n\x08Language\x12\x14\n\x10UNKNOWN_LANGUAGE\x10\x00\x12\x06\n\x02\x65n\x10\x01\x12\x06\n\x02\x61\x61\x10\x02\x12\x06\n\x02\x61\x62\x10\x03\x12\x06\n\x02\x61\x65\x10\x04\x12\x06\n\x02\x61\x66\x10\x05\x12\x06\n\x02\x61k\x10\x06\x12\x06\n\x02\x61m\x10\x07\x12\x06\n\x02\x61n\x10\x08\x12\x06\n\x02\x61r\x10\t\x12\x06\n\x02\x61s\x10\n\x12\x06\n\x02\x61v\x10\x0b\x12\x06\n\x02\x61y\x10\x0c\x12\x06\n\x02\x61z\x10\r\x12\x06\n\x02\x62\x61\x10\x0e\x12\x06\n\x02\x62\x65\x10\x0f\x12\x06\n\x02\x62g\x10\x10\x12\x06\n\x02\x62h\x10\x11\x12\x06\n\x02\x62i\x10\x12\x12\x06\n\x02\x62m\x10\x13\x12\x06\n\x02\x62n\x10\x14\x12\x06\n\x02\x62o\x10\x15\x12\x06\n\x02\x62r\x10\x16\x12\x06\n\x02\x62s\x10\x17\x12\x06\n\x02\x63\x61\x10\x18\x12\x06\n\x02\x63\x65\x10\x19\x12\x06\n\x02\x63h\x10\x1a\x12\x06\n\x02\x63o\x10\x1b\x12\x06\n\x02\x63r\x10\x1c\x12\x06\n\x02\x63s\x10\x1d\x12\x06\n\x02\x63u\x10\x1e\x12\x06\n\x02\x63v\x10\x1f\x12\x06\n\x02\x63y\x10 \x12\x06\n\x02\x64\x61\x10!\x12\x06\n\x02\x64\x65\x10\"\x12\x06\n\x02\x64v\x10#\x12\x06\n\x02\x64z\x10$\x12\x06\n\x02\x65\x65\x10%\x12\x06\n\x02\x65l\x10&\x12\x06\n\x02\x65o\x10\'\x12\x06\n\x02\x65s\x10(\x12\x06\n\x02\x65t\x10)\x12\x06\n\x02\x65u\x10*\x12\x06\n\x02\x66\x61\x10+\x12\x06\n\x02\x66\x66\x10,\x12\x06\n\x02\x66i\x10-\x12\x06\n\x02\x66j\x10.\x12\x06\n\x02\x66o\x10/\x12\x06\n\x02\x66r\x10\x30\x12\x06\n\x02\x66y\x10\x31\x12\x06\n\x02ga\x10\x32\x12\x06\n\x02gd\x10\x33\x12\x06\n\x02gl\x10\x34\x12\x06\n\x02gn\x10\x35\x12\x06\n\x02gu\x10\x36\x12\x06\n\x02gv\x10\x37\x12\x06\n\x02ha\x10\x38\x12\x06\n\x02he\x10\x39\x12\x06\n\x02hi\x10:\x12\x06\n\x02ho\x10;\x12\x06\n\x02hr\x10<\x12\x06\n\x02ht\x10=\x12\x06\n\x02hu\x10>\x12\x06\n\x02hy\x10?\x12\x06\n\x02hz\x10@\x12\x06\n\x02ia\x10\x41\x12\x06\n\x02id\x10\x42\x12\x06\n\x02ie\x10\x43\x12\x06\n\x02ig\x10\x44\x12\x06\n\x02ii\x10\x45\x12\x06\n\x02ik\x10\x46\x12\x06\n\x02io\x10G\x12\x06\n\x02is\x10H\x12\x06\n\x02it\x10I\x12\x06\n\x02iu\x10J\x12\x06\n\x02ja\x10K\x12\x06\n\x02jv\x10L\x12\x06\n\x02ka\x10M\x12\x06\n\x02kg\x10N\x12\x06\n\x02ki\x10O\x12\x06\n\x02kj\x10P\x12\x06\n\x02kk\x10Q\x12\x06\n\x02kl\x10R\x12\x06\n\x02km\x10S\x12\x06\n\x02kn\x10T\x12\x06\n\x02ko\x10U\x12\x06\n\x02kr\x10V\x12\x06\n\x02ks\x10W\x12\x06\n\x02ku\x10X\x12\x06\n\x02kv\x10Y\x12\x06\n\x02kw\x10Z\x12\x06\n\x02ky\x10[\x12\x06\n\x02la\x10\\\x12\x06\n\x02lb\x10]\x12\x06\n\x02lg\x10^\x12\x06\n\x02li\x10_\x12\x06\n\x02ln\x10`\x12\x06\n\x02lo\x10\x61\x12\x06\n\x02lt\x10\x62\x12\x06\n\x02lu\x10\x63\x12\x06\n\x02lv\x10\x64\x12\x06\n\x02mg\x10\x65\x12\x06\n\x02mh\x10\x66\x12\x06\n\x02mi\x10g\x12\x06\n\x02mk\x10h\x12\x06\n\x02ml\x10i\x12\x06\n\x02mn\x10j\x12\x06\n\x02mr\x10k\x12\x06\n\x02ms\x10l\x12\x06\n\x02mt\x10m\x12\x06\n\x02my\x10n\x12\x06\n\x02na\x10o\x12\x06\n\x02nb\x10p\x12\x06\n\x02nd\x10q\x12\x06\n\x02ne\x10r\x12\x06\n\x02ng\x10s\x12\x06\n\x02nl\x10t\x12\x06\n\x02nn\x10u\x12\x06\n\x02no\x10v\x12\x06\n\x02nr\x10w\x12\x06\n\x02nv\x10x\x12\x06\n\x02ny\x10y\x12\x06\n\x02oc\x10z\x12\x06\n\x02oj\x10{\x12\x06\n\x02om\x10|\x12\x06\n\x02or\x10}\x12\x06\n\x02os\x10~\x12\x06\n\x02pa\x10\x7f\x12\x07\n\x02pi\x10\x80\x01\x12\x07\n\x02pl\x10\x81\x01\x12\x07\n\x02ps\x10\x82\x01\x12\x07\n\x02pt\x10\x83\x01\x12\x07\n\x02qu\x10\x84\x01\x12\x07\n\x02rm\x10\x85\x01\x12\x07\n\x02rn\x10\x86\x01\x12\x07\n\x02ro\x10\x87\x01\x12\x07\n\x02ru\x10\x88\x01\x12\x07\n\x02rw\x10\x89\x01\x12\x07\n\x02sa\x10\x8a\x01\x12\x07\n\x02sc\x10\x8b\x01\x12\x07\n\x02sd\x10\x8c\x01\x12\x07\n\x02se\x10\x8d\x01\x12\x07\n\x02sg\x10\x8e\x01\x12\x07\n\x02si\x10\x8f\x01\x12\x07\n\x02sk\x10\x90\x01\x12\x07\n\x02sl\x10\x91\x01\x12\x07\n\x02sm\x10\x92\x01\x12\x07\n\x02sn\x10\x93\x01\x12\x07\n\x02so\x10\x94\x01\x12\x07\n\x02sq\x10\x95\x01\x12\x07\n\x02sr\x10\x96\x01\x12\x07\n\x02ss\x10\x97\x01\x12\x07\n\x02st\x10\x98\x01\x12\x07\n\x02su\x10\x99\x01\x12\x07\n\x02sv\x10\x9a\x01\x12\x07\n\x02sw\x10\x9b\x01\x12\x07\n\x02ta\x10\x9c\x01\x12\x07\n\x02te\x10\x9d\x01\x12\x07\n\x02tg\x10\x9e\x01\x12\x07\n\x02th\x10\x9f\x01\x12\x07\n\x02ti\x10\xa0\x01\x12\x07\n\x02tk\x10\xa1\x01\x12\x07\n\x02tl\x10\xa2\x01\x12\x07\n\x02tn\x10\xa3\x01\x12\x07\n\x02to\x10\xa4\x01\x12\x07\n\x02tr\x10\xa5\x01\x12\x07\n\x02ts\x10\xa6\x01\x12\x07\n\x02tt\x10\xa7\x01\x12\x07\n\x02tw\x10\xa8\x01\x12\x07\n\x02ty\x10\xa9\x01\x12\x07\n\x02ug\x10\xaa\x01\x12\x07\n\x02uk\x10\xab\x01\x12\x07\n\x02ur\x10\xac\x01\x12\x07\n\x02uz\x10\xad\x01\x12\x07\n\x02ve\x10\xae\x01\x12\x07\n\x02vi\x10\xaf\x01\x12\x07\n\x02vo\x10\xb0\x01\x12\x07\n\x02wa\x10\xb1\x01\x12\x07\n\x02wo\x10\xb2\x01\x12\x07\n\x02xh\x10\xb3\x01\x12\x07\n\x02yi\x10\xb4\x01\x12\x07\n\x02yo\x10\xb5\x01\x12\x07\n\x02za\x10\xb6\x01\x12\x07\n\x02zh\x10\xb7\x01\x12\x07\n\x02zu\x10\xb8\x01') + , + dependencies=[lbryschema.proto.fee_pb2.DESCRIPTOR,]) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + + + +_METADATA_VERSION = _descriptor.EnumDescriptor( + name='Version', + full_name='Metadata.Version', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_VERSION', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='_0_0_1', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='_0_0_2', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='_0_0_3', index=3, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='_0_1_0', index=4, number=4, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=308, + serialized_end=386, +) +_sym_db.RegisterEnumDescriptor(_METADATA_VERSION) + +_METADATA_LANGUAGE = _descriptor.EnumDescriptor( + name='Language', + full_name='Metadata.Language', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_LANGUAGE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='en', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='aa', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ab', index=3, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ae', index=4, number=4, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='af', index=5, number=5, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ak', index=6, number=6, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='am', index=7, number=7, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='an', index=8, number=8, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ar', index=9, number=9, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='as', index=10, number=10, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='av', index=11, number=11, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ay', index=12, number=12, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='az', index=13, number=13, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ba', index=14, number=14, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='be', index=15, number=15, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='bg', index=16, number=16, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='bh', index=17, number=17, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='bi', index=18, number=18, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='bm', index=19, number=19, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='bn', index=20, number=20, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='bo', index=21, number=21, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='br', index=22, number=22, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='bs', index=23, number=23, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ca', index=24, number=24, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ce', index=25, number=25, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ch', index=26, number=26, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='co', index=27, number=27, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='cr', index=28, number=28, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='cs', index=29, number=29, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='cu', index=30, number=30, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='cv', index=31, number=31, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='cy', index=32, number=32, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='da', index=33, number=33, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='de', index=34, number=34, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='dv', index=35, number=35, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='dz', index=36, number=36, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ee', index=37, number=37, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='el', index=38, number=38, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='eo', index=39, number=39, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='es', index=40, number=40, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='et', index=41, number=41, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='eu', index=42, number=42, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='fa', index=43, number=43, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ff', index=44, number=44, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='fi', index=45, number=45, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='fj', index=46, number=46, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='fo', index=47, number=47, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='fr', index=48, number=48, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='fy', index=49, number=49, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ga', index=50, number=50, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='gd', index=51, number=51, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='gl', index=52, number=52, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='gn', index=53, number=53, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='gu', index=54, number=54, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='gv', index=55, number=55, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ha', index=56, number=56, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='he', index=57, number=57, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='hi', index=58, number=58, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ho', index=59, number=59, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='hr', index=60, number=60, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ht', index=61, number=61, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='hu', index=62, number=62, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='hy', index=63, number=63, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='hz', index=64, number=64, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ia', index=65, number=65, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='id', index=66, number=66, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ie', index=67, number=67, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ig', index=68, number=68, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ii', index=69, number=69, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ik', index=70, number=70, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='io', index=71, number=71, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='is', index=72, number=72, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='it', index=73, number=73, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='iu', index=74, number=74, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ja', index=75, number=75, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='jv', index=76, number=76, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ka', index=77, number=77, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='kg', index=78, number=78, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ki', index=79, number=79, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='kj', index=80, number=80, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='kk', index=81, number=81, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='kl', index=82, number=82, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='km', index=83, number=83, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='kn', index=84, number=84, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ko', index=85, number=85, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='kr', index=86, number=86, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ks', index=87, number=87, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ku', index=88, number=88, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='kv', index=89, number=89, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='kw', index=90, number=90, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ky', index=91, number=91, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='la', index=92, number=92, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='lb', index=93, number=93, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='lg', index=94, number=94, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='li', index=95, number=95, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ln', index=96, number=96, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='lo', index=97, number=97, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='lt', index=98, number=98, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='lu', index=99, number=99, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='lv', index=100, number=100, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='mg', index=101, number=101, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='mh', index=102, number=102, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='mi', index=103, number=103, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='mk', index=104, number=104, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ml', index=105, number=105, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='mn', index=106, number=106, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='mr', index=107, number=107, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ms', index=108, number=108, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='mt', index=109, number=109, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='my', index=110, number=110, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='na', index=111, number=111, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='nb', index=112, number=112, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='nd', index=113, number=113, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ne', index=114, number=114, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ng', index=115, number=115, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='nl', index=116, number=116, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='nn', index=117, number=117, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='no', index=118, number=118, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='nr', index=119, number=119, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='nv', index=120, number=120, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ny', index=121, number=121, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='oc', index=122, number=122, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='oj', index=123, number=123, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='om', index=124, number=124, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='or', index=125, number=125, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='os', index=126, number=126, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='pa', index=127, number=127, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='pi', index=128, number=128, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='pl', index=129, number=129, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ps', index=130, number=130, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='pt', index=131, number=131, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='qu', index=132, number=132, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='rm', index=133, number=133, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='rn', index=134, number=134, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ro', index=135, number=135, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ru', index=136, number=136, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='rw', index=137, number=137, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='sa', index=138, number=138, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='sc', index=139, number=139, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='sd', index=140, number=140, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='se', index=141, number=141, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='sg', index=142, number=142, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='si', index=143, number=143, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='sk', index=144, number=144, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='sl', index=145, number=145, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='sm', index=146, number=146, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='sn', index=147, number=147, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='so', index=148, number=148, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='sq', index=149, number=149, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='sr', index=150, number=150, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ss', index=151, number=151, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='st', index=152, number=152, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='su', index=153, number=153, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='sv', index=154, number=154, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='sw', index=155, number=155, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ta', index=156, number=156, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='te', index=157, number=157, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='tg', index=158, number=158, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='th', index=159, number=159, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ti', index=160, number=160, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='tk', index=161, number=161, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='tl', index=162, number=162, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='tn', index=163, number=163, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='to', index=164, number=164, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='tr', index=165, number=165, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ts', index=166, number=166, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='tt', index=167, number=167, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='tw', index=168, number=168, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ty', index=169, number=169, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ug', index=170, number=170, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='uk', index=171, number=171, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ur', index=172, number=172, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='uz', index=173, number=173, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ve', index=174, number=174, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='vi', index=175, number=175, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='vo', index=176, number=176, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='wa', index=177, number=177, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='wo', index=178, number=178, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='xh', index=179, number=179, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='yi', index=180, number=180, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='yo', index=181, number=181, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='za', index=182, number=182, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='zh', index=183, number=183, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='zu', index=184, number=184, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=389, + serialized_end=1950, +) +_sym_db.RegisterEnumDescriptor(_METADATA_LANGUAGE) + + +_METADATA = _descriptor.Descriptor( + name='Metadata', + full_name='Metadata', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='version', full_name='Metadata.version', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='language', full_name='Metadata.language', index=1, + number=2, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='title', full_name='Metadata.title', index=2, + number=3, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='description', full_name='Metadata.description', index=3, + number=4, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='author', full_name='Metadata.author', index=4, + number=5, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='license', full_name='Metadata.license', index=5, + number=6, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='nsfw', full_name='Metadata.nsfw', index=6, + number=7, type=8, cpp_type=7, label=2, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='fee', full_name='Metadata.fee', index=7, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='thumbnail', full_name='Metadata.thumbnail', index=8, + number=9, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='preview', full_name='Metadata.preview', index=9, + number=10, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='licenseUrl', full_name='Metadata.licenseUrl', index=10, + number=11, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _METADATA_VERSION, + _METADATA_LANGUAGE, + ], + options=None, + is_extendable=False, + extension_ranges=[], + oneofs=[ + ], + serialized_start=64, + serialized_end=1950, +) + +_METADATA.fields_by_name['version'].enum_type = _METADATA_VERSION +_METADATA.fields_by_name['language'].enum_type = _METADATA_LANGUAGE +_METADATA.fields_by_name['fee'].message_type = lbryschema.proto.fee_pb2._FEE +_METADATA_VERSION.containing_type = _METADATA +_METADATA_LANGUAGE.containing_type = _METADATA +DESCRIPTOR.message_types_by_name['Metadata'] = _METADATA + +Metadata = _reflection.GeneratedProtocolMessageType('Metadata', (_message.Message,), dict( + DESCRIPTOR = _METADATA, + __module__ = 'lbryschema.proto.metadata_pb2' + # @@protoc_insertion_point(class_scope:Metadata) + )) +_sym_db.RegisterMessage(Metadata) + + +# @@protoc_insertion_point(module_scope) diff --git a/lbrynet/schema/proto/signature.proto b/lbrynet/schema/proto/signature.proto new file mode 100644 index 000000000..1830a7733 --- /dev/null +++ b/lbrynet/schema/proto/signature.proto @@ -0,0 +1,14 @@ +syntax = "proto2"; + +import "lbryschema/proto/certificate.proto"; + +message Signature { + enum Version { + UNKNOWN_VERSION = 0; + _0_0_1 = 1; + } + required Version version = 1; + required KeyType signatureType = 2; + required bytes signature = 3; + required bytes certificateId = 4; +} diff --git a/lbrynet/schema/proto/signature_pb2.py b/lbrynet/schema/proto/signature_pb2.py new file mode 100644 index 000000000..64b9cc13f --- /dev/null +++ b/lbrynet/schema/proto/signature_pb2.py @@ -0,0 +1,116 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: lbryschema/proto/signature.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import lbryschema.proto.certificate_pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='lbryschema/proto/signature.proto', + package='', + serialized_pb=_b('\n lbryschema/proto/signature.proto\x1a\"lbryschema/proto/certificate.proto\"\xa7\x01\n\tSignature\x12#\n\x07version\x18\x01 \x02(\x0e\x32\x12.Signature.Version\x12\x1f\n\rsignatureType\x18\x02 \x02(\x0e\x32\x08.KeyType\x12\x11\n\tsignature\x18\x03 \x02(\x0c\x12\x15\n\rcertificateId\x18\x04 \x02(\x0c\"*\n\x07Version\x12\x13\n\x0fUNKNOWN_VERSION\x10\x00\x12\n\n\x06_0_0_1\x10\x01') + , + dependencies=[lbryschema.proto.certificate_pb2.DESCRIPTOR,]) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + + + +_SIGNATURE_VERSION = _descriptor.EnumDescriptor( + name='Version', + full_name='Signature.Version', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_VERSION', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='_0_0_1', index=1, number=1, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=198, + serialized_end=240, +) +_sym_db.RegisterEnumDescriptor(_SIGNATURE_VERSION) + + +_SIGNATURE = _descriptor.Descriptor( + name='Signature', + full_name='Signature', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='version', full_name='Signature.version', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='signatureType', full_name='Signature.signatureType', index=1, + number=2, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='signature', full_name='Signature.signature', index=2, + number=3, type=12, cpp_type=9, label=2, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='certificateId', full_name='Signature.certificateId', index=3, + number=4, type=12, cpp_type=9, label=2, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _SIGNATURE_VERSION, + ], + options=None, + is_extendable=False, + extension_ranges=[], + oneofs=[ + ], + serialized_start=73, + serialized_end=240, +) + +_SIGNATURE.fields_by_name['version'].enum_type = _SIGNATURE_VERSION +_SIGNATURE.fields_by_name['signatureType'].enum_type = lbryschema.proto.certificate_pb2._KEYTYPE +_SIGNATURE_VERSION.containing_type = _SIGNATURE +DESCRIPTOR.message_types_by_name['Signature'] = _SIGNATURE + +Signature = _reflection.GeneratedProtocolMessageType('Signature', (_message.Message,), dict( + DESCRIPTOR = _SIGNATURE, + __module__ = 'lbryschema.proto.signature_pb2' + # @@protoc_insertion_point(class_scope:Signature) + )) +_sym_db.RegisterMessage(Signature) + + +# @@protoc_insertion_point(module_scope) diff --git a/lbrynet/schema/proto/source.proto b/lbrynet/schema/proto/source.proto new file mode 100644 index 000000000..1e13afa4f --- /dev/null +++ b/lbrynet/schema/proto/source.proto @@ -0,0 +1,16 @@ +syntax = "proto2"; + +message Source { + enum Version { + UNKNOWN_VERSION = 0; + _0_0_1 = 1; + } + required Version version = 1; + enum SourceTypes { + UNKNOWN_SOURCE_TYPE = 0; + lbry_sd_hash = 1; + } + required SourceTypes sourceType = 2; + required bytes source = 3; + required string contentType = 4; +} \ No newline at end of file diff --git a/lbrynet/schema/proto/source_pb2.py b/lbrynet/schema/proto/source_pb2.py new file mode 100644 index 000000000..211b36b73 --- /dev/null +++ b/lbrynet/schema/proto/source_pb2.py @@ -0,0 +1,138 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: lbryschema/proto/source.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='lbryschema/proto/source.proto', + package='', + serialized_pb=_b('\n\x1dlbryschema/proto/source.proto\"\xde\x01\n\x06Source\x12 \n\x07version\x18\x01 \x02(\x0e\x32\x0f.Source.Version\x12\'\n\nsourceType\x18\x02 \x02(\x0e\x32\x13.Source.SourceTypes\x12\x0e\n\x06source\x18\x03 \x02(\x0c\x12\x13\n\x0b\x63ontentType\x18\x04 \x02(\t\"*\n\x07Version\x12\x13\n\x0fUNKNOWN_VERSION\x10\x00\x12\n\n\x06_0_0_1\x10\x01\"8\n\x0bSourceTypes\x12\x17\n\x13UNKNOWN_SOURCE_TYPE\x10\x00\x12\x10\n\x0clbry_sd_hash\x10\x01') +) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + + + +_SOURCE_VERSION = _descriptor.EnumDescriptor( + name='Version', + full_name='Source.Version', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_VERSION', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='_0_0_1', index=1, number=1, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=156, + serialized_end=198, +) +_sym_db.RegisterEnumDescriptor(_SOURCE_VERSION) + +_SOURCE_SOURCETYPES = _descriptor.EnumDescriptor( + name='SourceTypes', + full_name='Source.SourceTypes', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_SOURCE_TYPE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='lbry_sd_hash', index=1, number=1, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=200, + serialized_end=256, +) +_sym_db.RegisterEnumDescriptor(_SOURCE_SOURCETYPES) + + +_SOURCE = _descriptor.Descriptor( + name='Source', + full_name='Source', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='version', full_name='Source.version', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='sourceType', full_name='Source.sourceType', index=1, + number=2, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='source', full_name='Source.source', index=2, + number=3, type=12, cpp_type=9, label=2, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='contentType', full_name='Source.contentType', index=3, + number=4, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _SOURCE_VERSION, + _SOURCE_SOURCETYPES, + ], + options=None, + is_extendable=False, + extension_ranges=[], + oneofs=[ + ], + serialized_start=34, + serialized_end=256, +) + +_SOURCE.fields_by_name['version'].enum_type = _SOURCE_VERSION +_SOURCE.fields_by_name['sourceType'].enum_type = _SOURCE_SOURCETYPES +_SOURCE_VERSION.containing_type = _SOURCE +_SOURCE_SOURCETYPES.containing_type = _SOURCE +DESCRIPTOR.message_types_by_name['Source'] = _SOURCE + +Source = _reflection.GeneratedProtocolMessageType('Source', (_message.Message,), dict( + DESCRIPTOR = _SOURCE, + __module__ = 'lbryschema.proto.source_pb2' + # @@protoc_insertion_point(class_scope:Source) + )) +_sym_db.RegisterMessage(Source) + + +# @@protoc_insertion_point(module_scope) diff --git a/lbrynet/schema/proto/stream.proto b/lbrynet/schema/proto/stream.proto new file mode 100644 index 000000000..3866ca1c2 --- /dev/null +++ b/lbrynet/schema/proto/stream.proto @@ -0,0 +1,15 @@ +syntax = "proto2"; + +import "lbryschema/proto/metadata.proto"; +import "lbryschema/proto/source.proto"; + + +message Stream { + enum Version { + UNKNOWN_VERSION = 0; + _0_0_1 = 1; + } + required Version version = 1; + required Metadata metadata = 2; + required Source source = 3; +} diff --git a/lbrynet/schema/proto/stream_pb2.py b/lbrynet/schema/proto/stream_pb2.py new file mode 100644 index 000000000..88b79a64c --- /dev/null +++ b/lbrynet/schema/proto/stream_pb2.py @@ -0,0 +1,111 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: lbryschema/proto/stream.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import lbryschema.proto.metadata_pb2 +import lbryschema.proto.source_pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='lbryschema/proto/stream.proto', + package='', + serialized_pb=_b('\n\x1dlbryschema/proto/stream.proto\x1a\x1flbryschema/proto/metadata.proto\x1a\x1dlbryschema/proto/source.proto\"\x8c\x01\n\x06Stream\x12 \n\x07version\x18\x01 \x02(\x0e\x32\x0f.Stream.Version\x12\x1b\n\x08metadata\x18\x02 \x02(\x0b\x32\t.Metadata\x12\x17\n\x06source\x18\x03 \x02(\x0b\x32\x07.Source\"*\n\x07Version\x12\x13\n\x0fUNKNOWN_VERSION\x10\x00\x12\n\n\x06_0_0_1\x10\x01') + , + dependencies=[lbryschema.proto.metadata_pb2.DESCRIPTOR,lbryschema.proto.source_pb2.DESCRIPTOR,]) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + + + +_STREAM_VERSION = _descriptor.EnumDescriptor( + name='Version', + full_name='Stream.Version', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_VERSION', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='_0_0_1', index=1, number=1, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=196, + serialized_end=238, +) +_sym_db.RegisterEnumDescriptor(_STREAM_VERSION) + + +_STREAM = _descriptor.Descriptor( + name='Stream', + full_name='Stream', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='version', full_name='Stream.version', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='metadata', full_name='Stream.metadata', index=1, + number=2, type=11, cpp_type=10, label=2, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='source', full_name='Stream.source', index=2, + number=3, type=11, cpp_type=10, label=2, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _STREAM_VERSION, + ], + options=None, + is_extendable=False, + extension_ranges=[], + oneofs=[ + ], + serialized_start=98, + serialized_end=238, +) + +_STREAM.fields_by_name['version'].enum_type = _STREAM_VERSION +_STREAM.fields_by_name['metadata'].message_type = lbryschema.proto.metadata_pb2._METADATA +_STREAM.fields_by_name['source'].message_type = lbryschema.proto.source_pb2._SOURCE +_STREAM_VERSION.containing_type = _STREAM +DESCRIPTOR.message_types_by_name['Stream'] = _STREAM + +Stream = _reflection.GeneratedProtocolMessageType('Stream', (_message.Message,), dict( + DESCRIPTOR = _STREAM, + __module__ = 'lbryschema.proto.stream_pb2' + # @@protoc_insertion_point(class_scope:Stream) + )) +_sym_db.RegisterMessage(Stream) + + +# @@protoc_insertion_point(module_scope) diff --git a/lbrynet/schema/schema/__init__.py b/lbrynet/schema/schema/__init__.py new file mode 100644 index 000000000..aeff1b4bc --- /dev/null +++ b/lbrynet/schema/schema/__init__.py @@ -0,0 +1,102 @@ +V_0_0_1 = "_0_0_1" +V_0_0_2 = "_0_0_2" +V_0_0_3 = "_0_0_3" +V_0_1_0 = "_0_1_0" + + +VERSION_MAP = { + V_0_0_1: 1, + V_0_0_2: 2, + V_0_0_3: 3, + V_0_1_0: 4, +} + +VERSION_NAMES = { + 1: V_0_0_1, + 2: V_0_0_2, + 3: V_0_0_3, + 4: V_0_1_0 +} + +LBC = "LBC" +BTC = "BTC" +USD = "USD" + +CURRENCY_MAP = { + LBC: 1, + BTC: 2, + USD: 3 +} + +CURRENCY_NAMES = { + 1: LBC, + 2: BTC, + 3: USD +} + +ADDRESS_LENGTH = 25 +ADDRESS_CHECKSUM_LENGTH = 4 + +VERSION = "version" +STREAM_TYPE = "streamType" +CERTIFICATE_TYPE = "certificateType" +CLAIM_TYPE = "claimType" +SIGNATURE = "publisherSignature" + +CLAIM_TYPES = { + STREAM_TYPE: "stream", + CERTIFICATE_TYPE: "certificate" +} + +CLAIM_TYPE_NAMES = { + 1: "stream", + 2: "certificate" +} + +LBRY_SD_HASH = "lbry_sd_hash" +LBRY_SD_HASH_LENGTH = 48 + +SOURCE_TYPES = { + LBRY_SD_HASH: 1 +} + +NIST256p = "NIST256p" +NIST384p = "NIST384p" +SECP256k1 = "SECP256k1" + +ECDSA_CURVES = { + NIST256p: 1, + NIST384p: 2, + SECP256k1: 3 +} + +CURVE_NAMES = { + 1: NIST256p, + 2: NIST384p, + 3: SECP256k1 +} + +SHA256 = "sha256" +SHA384 = "sha384" + + +B58_CHARS = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' +assert len(B58_CHARS) == 58 + +PUBKEY_ADDRESS = 0 +SCRIPT_ADDRESS = 5 + +ADDRESS_PREFIXES = { + "lbrycrd_main": { + PUBKEY_ADDRESS: 85, + SCRIPT_ADDRESS: 122 + }, + "lbrycrd_regtest": { + PUBKEY_ADDRESS: 111, + SCRIPT_ADDRESS: 196 + }, + "lbrycrd_testnet": { + PUBKEY_ADDRESS: 111, + SCRIPT_ADDRESS: 196 + }, +} diff --git a/lbrynet/schema/schema/certificate.py b/lbrynet/schema/schema/certificate.py new file mode 100644 index 000000000..03031baa0 --- /dev/null +++ b/lbrynet/schema/schema/certificate.py @@ -0,0 +1,54 @@ +from copy import deepcopy + +from lbryschema.proto import certificate_pb2 as cert_pb +from lbryschema.schema.schema import Schema +from lbryschema.schema import VERSION_MAP, V_0_0_1, ECDSA_CURVES, CURVE_NAMES +from lbryschema.validator import get_key_type_from_dem + + +class _ECDSAKeyHelper(object): + def __init__(self, key): + self._key = key + + @property + def der(self): + return self._key.to_der() + + @property + def curve_name(self): + return self._key.curve.name + + +class Certificate(Schema): + @classmethod + def load(cls, message): + _key = deepcopy(message) + _message_pb = cert_pb.Certificate() + if isinstance(_key, dict): + _message_pb.publicKey = _key.pop("publicKey") + _message_pb.version = VERSION_MAP[_key.pop("version")] + _message_pb.keyType = ECDSA_CURVES[_key.pop("keyType")] + else: + _message_pb.version = _key.version + _message_pb.keyType = _key.keyType + _message_pb.publicKey = _key.publicKey + if _message_pb.keyType not in CURVE_NAMES: + raise Exception("Unknown curve") + if get_key_type_from_dem(_message_pb.publicKey) != _message_pb.keyType: + raise Exception("Curve mismatch") + return cls._load(_key, _message_pb) + + @classmethod + def load_from_key_obj(cls, key, key_type): + if key_type in ECDSA_CURVES: + _key = _ECDSAKeyHelper(key) + else: + raise Exception("Unknown key type: %s" % str(type(key))) + if key_type != _key.curve_name: + raise Exception("Curve mismatch") + msg = { + "version": V_0_0_1, + "keyType": key_type, + "publicKey": _key.der, + } + return cls.load(msg) diff --git a/lbrynet/schema/schema/claim.py b/lbrynet/schema/schema/claim.py new file mode 100644 index 000000000..919032fd2 --- /dev/null +++ b/lbrynet/schema/schema/claim.py @@ -0,0 +1,51 @@ +from copy import deepcopy + +from lbryschema.proto import claim_pb2 as claim_pb +from lbryschema.schema import VERSION_MAP +from lbryschema.schema.signature import Signature +from lbryschema.schema.certificate import Certificate +from lbryschema.schema.schema import Schema +from lbryschema.schema.stream import Stream + + +class Claim(Schema): + CLAIM_TYPE_STREAM = 1 + CLAIM_TYPE_CERT = 2 + + @classmethod + def load(cls, message): + _claim = deepcopy(message) + _message_pb = claim_pb.Claim() + _message_pb.version = VERSION_MAP[_claim.pop("version")] + + if "certificate" in _claim: + _cert = _claim.pop("certificate") + if isinstance(_cert, dict): + cert = Certificate.load(_cert) + else: + cert = _cert + claim_type = Claim.CLAIM_TYPE_CERT + _message_pb.certificate.MergeFrom(cert) + + elif "stream" in _claim: + _stream = _claim.pop("stream") + if isinstance(_stream, dict): + stream = Stream.load(_stream) + else: + stream = _stream + claim_type = Claim.CLAIM_TYPE_STREAM + _message_pb.stream.MergeFrom(stream) + else: + raise AttributeError + + _message_pb.claimType = claim_type + + if "publisherSignature" in _claim: + _publisherSignature = _claim.pop("publisherSignature") + if isinstance(_publisherSignature, dict): + publisherSignature = Signature.load(_publisherSignature) + else: + publisherSignature = _publisherSignature + _message_pb.publisherSignature.MergeFrom(publisherSignature) + + return cls._load(_claim, _message_pb) diff --git a/lbrynet/schema/schema/fee.py b/lbrynet/schema/schema/fee.py new file mode 100644 index 000000000..c2be46196 --- /dev/null +++ b/lbrynet/schema/schema/fee.py @@ -0,0 +1,17 @@ +from copy import deepcopy + +from lbryschema.schema.schema import Schema +from lbryschema.proto import fee_pb2 as fee_pb +from lbryschema.schema import VERSION_MAP, CURRENCY_MAP + + +class Fee(Schema): + @classmethod + def load(cls, message): + _fee = deepcopy(message) + currency = CURRENCY_MAP[_fee.pop('currency')] + _message_pb = fee_pb.Fee() + _message_pb.version = VERSION_MAP[_fee.pop("version")] + _message_pb.currency = currency + _message_pb.address = _fee.pop('address') + return cls._load(_fee, _message_pb) diff --git a/lbrynet/schema/schema/metadata.py b/lbrynet/schema/schema/metadata.py new file mode 100644 index 000000000..cb65bb276 --- /dev/null +++ b/lbrynet/schema/schema/metadata.py @@ -0,0 +1,17 @@ +from copy import deepcopy +from lbryschema.proto import metadata_pb2 as metadata_pb +from lbryschema.schema.fee import Fee +from lbryschema.schema.schema import Schema +from lbryschema.schema import VERSION_MAP + + +class Metadata(Schema): + @classmethod + def load(cls, message): + _metadata = deepcopy(message) + _message_pb = metadata_pb.Metadata() + _message_pb.version = VERSION_MAP[_metadata.pop("version")] + if 'fee' in _metadata: + fee_pb = Fee.load(_metadata.pop('fee')) + _message_pb.fee.CopyFrom(fee_pb) + return cls._load(_metadata, _message_pb) diff --git a/lbrynet/schema/schema/schema.py b/lbrynet/schema/schema/schema.py new file mode 100644 index 000000000..b6eb857cb --- /dev/null +++ b/lbrynet/schema/schema/schema.py @@ -0,0 +1,15 @@ +import json +import google.protobuf.json_format as json_pb # pylint: disable=no-name-in-module +from google.protobuf.message import Message # pylint: disable=no-name-in-module,import-error + + +class Schema(Message): + @classmethod + def load(cls, message): + raise NotImplementedError + + @classmethod + def _load(cls, data, message): + if isinstance(data, dict): + data = json.dumps(data) + return json_pb.Parse(data, message) diff --git a/lbrynet/schema/schema/signature.py b/lbrynet/schema/schema/signature.py new file mode 100644 index 000000000..e4c35e212 --- /dev/null +++ b/lbrynet/schema/schema/signature.py @@ -0,0 +1,17 @@ +from copy import deepcopy + +from lbryschema.proto import signature_pb2 as signature_pb +from lbryschema.schema import VERSION_MAP, ECDSA_CURVES +from lbryschema.schema.schema import Schema + + +class Signature(Schema): + @classmethod + def load(cls, message): + _signature = deepcopy(message) + _message_pb = signature_pb.Signature() + _message_pb.version = VERSION_MAP[_signature.pop("version")] + _message_pb.signatureType = ECDSA_CURVES[_signature.pop("signatureType")] + _message_pb.certificateId = _signature.pop("certificateId") + _message_pb.signature = _signature.pop("signature") + return cls._load(_signature, _message_pb) diff --git a/lbrynet/schema/schema/source.py b/lbrynet/schema/schema/source.py new file mode 100644 index 000000000..550127b39 --- /dev/null +++ b/lbrynet/schema/schema/source.py @@ -0,0 +1,19 @@ +from copy import deepcopy +from lbryschema.proto import source_pb2 as source_pb +from lbryschema.schema import SOURCE_TYPES, LBRY_SD_HASH_LENGTH, VERSION_MAP +from lbryschema.schema.schema import Schema +from lbryschema.error import InvalidSourceHashLength + + +class Source(Schema): + @classmethod + def load(cls, message): + _source = deepcopy(message) + sd_hash = _source.pop('source') + assert len(sd_hash) == LBRY_SD_HASH_LENGTH, InvalidSourceHashLength(len(sd_hash)) + _message_pb = source_pb.Source() + _message_pb.version = VERSION_MAP[_source.pop("version")] + _message_pb.sourceType = SOURCE_TYPES[_source.pop('sourceType')] + _message_pb.source = sd_hash + _message_pb.contentType = _source.pop('contentType') + return cls._load(_source, _message_pb) diff --git a/lbrynet/schema/schema/stream.py b/lbrynet/schema/schema/stream.py new file mode 100644 index 000000000..77a62db4e --- /dev/null +++ b/lbrynet/schema/schema/stream.py @@ -0,0 +1,20 @@ +from copy import deepcopy + +from lbryschema.schema.source import Source +from lbryschema.proto import stream_pb2 as stream_pb +from lbryschema.schema import VERSION_MAP +from lbryschema.schema.metadata import Metadata +from lbryschema.schema.schema import Schema + + +class Stream(Schema): + @classmethod + def load(cls, message): + _claim = deepcopy(message) + source = Source.load(_claim.pop('source')) + metadata = Metadata.load(_claim.pop('metadata')) + _message_pb = stream_pb.Stream() + _message_pb.version = VERSION_MAP[_claim.pop("version")] + _message_pb.source.CopyFrom(source) + _message_pb.metadata.CopyFrom(metadata) + return cls._load(_claim, _message_pb) diff --git a/lbrynet/schema/signature/flags.py b/lbrynet/schema/signature/flags.py new file mode 100644 index 000000000..259be0aff --- /dev/null +++ b/lbrynet/schema/signature/flags.py @@ -0,0 +1,41 @@ +class SignatureSerializationFlag: + UNSIGNED = 0 + ''' + Format: + + or (legacy) + + ''' + ECDSA_LEGACY = 1 + ''' + Old claim format, which carried the signature inside the protobuf. Requires serializing back the claim with + signature stripped out for validation. This process requires knowledge on how a claim is serialized, thus requires + old fixed protobuf schema to work. + + Format: + + Curves: NIST256p, NIST384p, SECP256k1 + Signature content: `r` and `s` in each half of the 64 or 96 bytes (depends on curve) + Signed payload: + 1. Claim transaction output address (raw, decoded using base58) + 2. Stripped out claim protobuf serialization (without the signature) + 3. Certificate claim id (binary, not in network byte order) + ''' + ECDSA_SECP256K1 = 2 + ''' + Format: + + Curve: SECP256K1 + Signature content: 64 bytes total, each half represents `r` and `s` + Signed payload: + 1. raw claim name as bytes + 2. Claim transaction output address (raw, decoded using base58) + 3. Binary payload, independent of serialization (everything after the signature last byte) + 4. Certificate claim id, not in network byte order. + + A certificate can be signed as well, but this serialization model is unaware of content type or protobuf format. + ''' + @classmethod + def is_flag_valid(cls, flag): + # todo: use python 3 enum when fully ported, but not worth now as its an extra dependency for py2 + return 0 <= flag <= 2 \ No newline at end of file diff --git a/lbrynet/schema/signature/serializer.py b/lbrynet/schema/signature/serializer.py new file mode 100644 index 000000000..7ddcb2277 --- /dev/null +++ b/lbrynet/schema/signature/serializer.py @@ -0,0 +1,11 @@ +import struct +from collections import namedtuple +from .flags import SignatureSerializationFlag + + +class Signature(namedtuple("Signature", "flags signature certificate_id")): + def deserialize(cls, payload): + flag = struct.unpack(" 1: + raise ValueError( + "Only one of these may be present at a time: claim_sequence, bid_position, claim_id" + ) + + self.name = name + self.claim_sequence = claim_sequence + self.bid_position = bid_position + self.claim_id = claim_id + self.path = path + + if self.path is not None and not self.is_channel: + raise ValueError("Content claims cannot have paths") + + def __str__(self): + return self.to_uri_string() + + def __eq__(self, other): + for prop in self.__slots__: + if not hasattr(other, prop) or getattr(self, prop) != getattr(other, prop): + return False + return self.__class__ == other.__class__ + + @property + def is_channel(self): + return self.name.startswith(CHANNEL_CHAR) + + def to_uri_string(self): + uri_string = PROTOCOL + "%s" % self.name + + if self.claim_sequence is not None: + uri_string += CLAIM_SEQUENCE_CHAR + "%i" % self.claim_sequence + elif self.bid_position is not None: + uri_string += BID_POSITION_CHAR + "%i" % self.bid_position + elif self.claim_id is not None: + uri_string += CLAIM_ID_CHAR + "%s" % self.claim_id + + if self.path is not None: + uri_string += PATH_CHAR + "%s" % self.path + + return uri_string + + def to_dict(self): + return { + "name": self.name, + 'claim_sequence': self.claim_sequence, + 'bid_position': self.bid_position, + 'claim_id': self.claim_id, + 'path': self.path, + } + + @classmethod + def from_uri_string(cls, uri_string): + """ + Parses LBRY uri into its components + + :param uri_string: format - lbry://name:n$rank#id/path + optional modifiers: + claim_sequence (int): the nth claim to the name + bid_position (int): the bid queue position of the claim for the name + claim_id (str): the claim id for the claim + path (str): claim within a channel + :return: URI + """ + match = re.match(get_schema_regex(), uri_string) + + if match is None: + raise URIParseError('Invalid URI') + + if match.group('content_name') and match.group('path'): + raise URIParseError('Only channels may have paths') + + return cls( + name=match.group("content_or_channel_name"), + claim_sequence=int(match.group("claim_sequence")) if match.group( + "claim_sequence") is not None else None, + bid_position=int(match.group("bid_position")) if match.group( + "bid_position") is not None else None, + claim_id=match.group("claim_id"), + path=match.group("path") + ) + + @classmethod + def from_dict(cls, uri_dict): + """ + Creates URI from dict + + :return: URI + """ + return cls(**uri_dict) + + +def get_schema_regex(): + def _named(name, regex): + return "(?P<" + name + ">" + regex + ")" + + def _group(regex): + return "(?:" + regex + ")" + + # TODO: regex should include the fact that content names cannot have paths + # right now this is only enforced in code, not in the regex + + # Escape constants + claim_id_char = re.escape(CLAIM_ID_CHAR) + claim_sequence_char = re.escape(CLAIM_SEQUENCE_CHAR) + bid_position_char = re.escape(BID_POSITION_CHAR) + channel_char = re.escape(CHANNEL_CHAR) + path_char = re.escape(PATH_CHAR) + protocol = _named("protocol", re.escape(PROTOCOL)) + + # Define basic building blocks + valid_name_char = "[a-zA-Z0-9\-]" # these characters are the only valid name characters + name_content = valid_name_char + '+' + name_min_channel_length = valid_name_char + '{' + str(CHANNEL_NAME_MIN_LENGTH) + ',}' + + positive_number = "[1-9][0-9]*" + number = '\-?' + positive_number + + # Define URI components + content_name = _named("content_name", name_content) + channel_name = _named("channel_name", channel_char + name_min_channel_length) + content_or_channel_name = _named("content_or_channel_name", content_name + "|" + channel_name) + + claim_id_piece = _named("claim_id", "[0-9a-f]{1," + str(CLAIM_ID_MAX_LENGTH) + "}") + claim_id = _group(claim_id_char + claim_id_piece) + + bid_position_piece = _named("bid_position", number) + bid_position = _group(bid_position_char + bid_position_piece) + + claim_sequence_piece = _named("claim_sequence", number) + claim_sequence = _group(claim_sequence_char + claim_sequence_piece) + + modifier = _named("modifier", claim_id + "|" + bid_position + "|" + claim_sequence) + + path_piece = _named("path", name_content) + path = _group(path_char + path_piece) + + # Combine components + uri = _named("uri", ( + '^' + + protocol + '?' + + content_or_channel_name + + modifier + '?' + + path + '?' + + '$' + )) + + return uri + + +def parse_lbry_uri(lbry_uri): + return URI.from_uri_string(lbry_uri) diff --git a/lbrynet/schema/validator.py b/lbrynet/schema/validator.py new file mode 100644 index 000000000..6a766f842 --- /dev/null +++ b/lbrynet/schema/validator.py @@ -0,0 +1,136 @@ +from string import hexdigits +import six +import ecdsa +import hashlib +import binascii + +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.serialization import load_der_public_key +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric import ec +from cryptography.hazmat.primitives.asymmetric.utils import Prehashed +from cryptography.exceptions import InvalidSignature +from ecdsa.util import sigencode_der + +from lbryschema.address import decode_address +from lbryschema.schema import NIST256p, NIST384p, SECP256k1, ECDSA_CURVES, CURVE_NAMES + + +def validate_claim_id(claim_id): + if not len(claim_id) == 40: + raise Exception("Incorrect claimid length: %i" % len(claim_id)) + if isinstance(claim_id, six.binary_type): + claim_id = claim_id.decode('utf-8') + if set(claim_id).difference(hexdigits): + raise Exception("Claim id is not hex encoded") + + +class Validator(object): + CURVE_NAME = None + HASHFUNC = hashlib.sha256 + + def __init__(self, public_key, certificate_claim_id): + validate_claim_id(certificate_claim_id) + if CURVE_NAMES.get(get_key_type_from_dem(public_key)) != self.CURVE_NAME: + raise Exception("Curve mismatch") + self._public_key = public_key + self._certificate_claim_id = certificate_claim_id + + @property + def public_key(self): + return self._public_key + + @property + def certificate_claim_id(self): + return self._certificate_claim_id + + @classmethod + def signing_key_from_pem(cls, pem): + return ecdsa.SigningKey.from_pem(pem, hashfunc=cls.HASHFUNC) + + @classmethod + def signing_key_from_der(cls, der): + return ecdsa.SigningKey.from_der(der, hashfunc=cls.HASHFUNC) + + @classmethod + def load_from_certificate(cls, certificate_claim, certificate_claim_id): + certificate = certificate_claim.certificate + return cls(certificate.publicKey, certificate_claim_id) + + def validate_signature(self, digest, signature): + public_key = load_der_public_key(self.public_key, default_backend()) + if len(signature) == 64: + hash = hashes.SHA256() + elif len(signature) == 96: + hash = hashes.SHA384() + signature = binascii.hexlify(signature) + r = int(signature[:int(len(signature)/2)], 16) + s = int(signature[int(len(signature)/2):], 16) + encoded_sig = sigencode_der(r, s, len(signature)*4) + try: + public_key.verify(encoded_sig, digest, ec.ECDSA(Prehashed(hash))) + return True + except InvalidSignature: + # TODO Fixme. This is what is expected today on the outer calls. This should be implementation independent + # but requires changing everything calling that + from ecdsa import BadSignatureError + raise BadSignatureError + + def validate_claim_signature(self, claim, claim_address): + decoded_address = decode_address(claim_address) + + # extract and serialize the stream from the claim, then check the signature + signature = binascii.unhexlify(claim.signature) + + if signature is None: + raise Exception("No signature to validate") + + to_sign = bytearray() + to_sign.extend(decoded_address) + to_sign.extend(claim.serialized_no_signature) + to_sign.extend(binascii.unhexlify(self.certificate_claim_id)) + + return self.validate_signature(self.HASHFUNC(to_sign).digest(), signature) + + def validate_private_key(self, private_key): + if not isinstance(private_key, ecdsa.SigningKey): + raise TypeError("Not given a signing key, given a %s" % str(type(private_key))) + return private_key.get_verifying_key().to_der() == self.public_key + + +class NIST256pValidator(Validator): + CURVE_NAME = NIST256p + HASHFUNC = hashlib.sha256 + + +class NIST384pValidator(Validator): + CURVE_NAME = NIST384p + HASHFUNC = hashlib.sha384 + + +class SECP256k1Validator(Validator): + CURVE_NAME = SECP256k1 + HASHFUNC = hashlib.sha256 + + +def get_validator(curve): + if curve == NIST256p: + return NIST256pValidator + elif curve == NIST384p: + return NIST384pValidator + elif curve == SECP256k1: + return SECP256k1Validator + else: + raise Exception("Unknown curve: %s" % str(curve)) + + +def get_key_type_from_dem(pubkey_dem): + name = serialization.load_der_public_key(pubkey_dem, default_backend()).curve.name + if name == 'secp256k1': + return ECDSA_CURVES[SECP256k1] + elif name == 'secp256r1': + return ECDSA_CURVES[NIST256p] + elif name == 'secp384r1': + return ECDSA_CURVES[NIST384p] + raise Exception("unexpected curve: %s" % name)