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'] = claim_value['source'][ 'source'].encode('hex') 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.message) claim_value['metadata']['fee']['address'] = address elif claim_type == CLAIM_TYPES[CERTIFICATE_TYPE]: public_key = claim_value["publicKey"] claim_value["publicKey"] = public_key.encode('hex') if SIGNATURE in claim_dictionary: encoded_sig = claim_dictionary[SIGNATURE]['signature'].encode('hex') encoded_cert_id = claim_dictionary[SIGNATURE]['certificateId'].encode( 'hex') claim_dictionary[SIGNATURE]['signature'] = encoded_sig claim_dictionary[SIGNATURE]['certificateId'] = encoded_cert_id claim_dictionary[claim_type] = claim_value return claim_dictionary
def migrate_json_claim_value(decoded_json): try: if 'fee' in decoded_json: old_fee = decoded_json['fee'] if not old_fee[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) # see if we were given a hex string, try decoding it skip_hex = sum(1 if char not in hex_chars else 0 for char in claim_value) if not skip_hex: try: decoded = claim_value.decode('hex') claim_value = decoded except (TypeError, ValueError): pass if claim_value.startswith("{"): # try deserializing protobuf, if that fails try parsing from json try: decoded_json = json.loads(claim_value) except (ValueError, TypeError): try: decoded_claim = ClaimDict.deserialize(claim_value) return decoded_claim except (DecodeError, InvalidAddress, KeyError): raise DecodeError() migrated_claim = migrate_json_claim_value(decoded_json) return migrated_claim else: try: decoded_claim = ClaimDict.deserialize(claim_value) return decoded_claim except (DecodeError, InvalidAddress, KeyError): try: decoded_json = json.loads(claim_value) except (ValueError, TypeError): raise DecodeError() migrated_claim = migrate_json_claim_value(decoded_json) return migrated_claim
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)
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(err.message)