def parse_payload(self, reader, *args): """ Parse a fulfillment payload. Read a fulfillment payload from a Reader and populate this object with that fulfillment. Args: reader (Reader): Source to read the fulfillment payload from. """ if not isinstance(reader, Reader): raise TypeError('reader must be a Reader instance') self.threshold = reader.read_var_uint() condition_count = reader.read_var_uint() for i in range(condition_count): weight = reader.read_var_uint() # reader, weight = read_weight(reader) fulfillment = reader.read_var_octet_string() condition = reader.read_var_octet_string() if len(fulfillment) and len(condition): raise TypeError('Subconditions may not provide both subcondition and fulfillment.') elif len(fulfillment): self.add_subfulfillment(Fulfillment.from_binary(fulfillment), weight) elif len(condition): self.add_subcondition(Condition.from_binary(condition), weight) else: raise TypeError('Subconditions must provide either subcondition or fulfillment.')
def test_from_dict(minimal_ed25519): from cryptoconditions import from_dict from cryptoconditions.fulfillment import Fulfillment fulfillment = Fulfillment.from_uri(minimal_ed25519.fulfillment) fulfillment_from_dict = from_dict(fulfillment.to_dict()) assert fulfillment_from_dict.condition_uri == fulfillment.condition_uri
def parse_payload(self, reader, *args): """ Parse a fulfillment payload. Read a fulfillment payload from a Reader and populate this object with that fulfillment. Args: reader (Reader): Source to read the fulfillment payload from. """ if not isinstance(reader, Reader): raise TypeError('reader must be a Reader instance') self.threshold = reader.read_var_uint() condition_count = reader.read_var_uint() for i in range(condition_count): weight = reader.read_var_uint() fulfillment = reader.read_var_octet_string() condition = reader.read_var_octet_string() if len(fulfillment) and len(condition): raise TypeError('Subconditions may not provide both subcondition and fulfillment.') elif len(fulfillment): self.add_subfulfillment(Fulfillment.from_binary(fulfillment), weight) elif len(condition): self.add_subcondition(Condition.from_binary(condition), weight) else: raise TypeError('Subconditions must provide either subcondition or fulfillment.')
def parse_dict(self, data): """ Generate fulfillment payload from a dict Args: data (dict): description of the fulfillment Returns: Fulfillment """ if not isinstance(data, dict): raise TypeError('reader must be a dict instance') self.threshold = data['threshold'] for subfulfillments in data['subfulfillments']: weight = subfulfillments['weight'] if subfulfillments['type'] == FULFILLMENT: self.add_subfulfillment(Fulfillment.from_dict(subfulfillments), weight) elif subfulfillments['type'] == CONDITION: self.add_subcondition(Condition.from_dict(subfulfillments), weight) else: raise TypeError( 'Subconditions must provide either subcondition or fulfillment.' )
def add_subfulfillment(self, subfulfillment): """ Add a fulfilled subcondition. When constructing a threshold fulfillment, this method allows you to provide a fulfillment for one of the subconditions. Note that you do **not** have to add the subcondition if you're adding the fulfillment. The condition can be calculated from the fulfillment and will be added automatically. Args: subfulfillment (:class:`~cryptoconditions.fulfillment.Fulfillment or :obj:`str`): Fulfillment object or URI string representing a new subfulfillment to be added. """ if isinstance(subfulfillment, str): subfulfillment = Fulfillment.from_uri(subfulfillment) elif not isinstance(subfulfillment, Fulfillment): raise TypeError( 'Subfulfillments must be URIs or objects of type Fulfillment') self.subconditions.append({ 'type': FULFILLMENT, 'body': subfulfillment })
def add_subfulfillment(self, subfulfillment, weight=1): """ Add a fulfilled subcondition. When constructing a threshold fulfillment, this method allows you to provide a fulfillment for one of the subconditions. Note that you do **not** have to add the subcondition if you're adding the fulfillment. The condition can be calculated from the fulfillment and will be added automatically. Args: subfulfillment (Fulfillment): Fulfillment to add weight (int): Integer weight of the subcondition. """ if isinstance(subfulfillment, str): subfulfillment = Fulfillment.from_uri(subfulfillment) elif not isinstance(subfulfillment, Fulfillment): raise TypeError('Subfulfillments must be URIs or objects of type Fulfillment') if not isinstance(weight, int): raise ValueError('Invalid weight, not an integer: {}'.format(weight)) self.subconditions.append( { 'type': FULFILLMENT, 'body': subfulfillment, 'weight': weight })
def add_subfulfillment(self, subfulfillment, weight=1): """ Add a fulfilled subcondition. When constructing a threshold fulfillment, this method allows you to provide a fulfillment for one of the subconditions. Note that you do **not** have to add the subcondition if you're adding the fulfillment. The condition can be calculated from the fulfillment and will be added automatically. Args: subfulfillment (Fulfillment): Fulfillment to add weight (int): Integer weight of the subcondition. """ if isinstance(subfulfillment, str): subfulfillment = Fulfillment.from_uri(subfulfillment) elif not isinstance(subfulfillment, Fulfillment): raise TypeError('Subfulfillments must be URIs or objects of type Fulfillment') if not isinstance(weight, int) or weight < 1: # TODO: Add a more helpful error message. raise ValueError('Invalid weight: {}'.format(weight)) self.subconditions.append( { 'type': FULFILLMENT, 'body': subfulfillment, 'weight': weight })
def test_add_subfulfillment_as_object(self, minimal_threshold): from cryptoconditions.types.threshold import ThresholdSha256 from cryptoconditions.fulfillment import Fulfillment threshold_obj = ThresholdSha256( threshold=minimal_threshold.json['threshold']) subfulfillment_object = Fulfillment.from_json( minimal_threshold.json['subfulfillments'][0]) threshold_obj.add_subfulfillment(subfulfillment_object) threshold_obj.serialize_uri == minimal_threshold.fulfillment
def validate_fulfillment(serialized_fulfillment, serialized_condition, message=None): fulfillment = Fulfillment.from_uri(serialized_fulfillment) condition_uri = fulfillment.condition_uri if condition_uri != serialized_condition: raise ValidationError( 'Fulfillment does not match condition (expected: {}, actual: {})'. format(serialized_condition, condition_uri)) return fulfillment.validate(message=message)
def validate_fulfillment(serialized_fulfillment, serialized_condition, message=None): fulfillment = Fulfillment.from_uri(serialized_fulfillment) condition_uri = fulfillment.condition_uri if condition_uri != serialized_condition: raise ValidationError( 'Fulfillment does not match condition (expected: {}, actual: {})' .format(serialized_condition, condition_uri) ) return fulfillment.validate(message=message)
def test_validate_threshold_exceeded(self, basic_threshold): from cryptoconditions.exceptions import ValidationError from cryptoconditions.fulfillment import Fulfillment from cryptoconditions.types.threshold import ThresholdSha256 threshold_obj = ThresholdSha256(threshold=2) for subfulfillment in basic_threshold.json['subfulfillments']: threshold_obj.add_subfulfillment( Fulfillment.from_json(subfulfillment)) with raises(ValidationError) as exc: threshold_obj.validate() assert exc.value.args == ('Fulfillment is not minimal',)
def test_validate_threshold_exceeded(self, basic_threshold): from cryptoconditions.exceptions import ValidationError from cryptoconditions.fulfillment import Fulfillment from cryptoconditions.types.threshold import ThresholdSha256 threshold_obj = ThresholdSha256(threshold=2) for subfulfillment in basic_threshold.json['subfulfillments']: threshold_obj.add_subfulfillment( Fulfillment.from_json(subfulfillment)) with raises(ValidationError) as exc: threshold_obj.validate() assert exc.value.args == ('Fulfillment is not minimal', )
def add_subfulfillment_uri(self, subfulfillment_uri): """ Add a fulfilled subcondition. This will automatically parse the URI and call addSubfulfillment. Args: subfulfillment_uri (str): Subfulfillment URI. """ if not isinstance(subfulfillment_uri, str): raise TypeError('Subfulfillment must be provided as a URI string, was: {}'.format(subfulfillment_uri)) self.add_subfulfillment(Fulfillment.from_uri(subfulfillment_uri))
def add_subfulfillment_uri(self, subfulfillment_uri): """ Add a fulfilled subcondition. This will automatically parse the URI and call addSubfulfillment. Args: subfulfillment_uri (str): Subfulfillment URI. """ if not isinstance(subfulfillment_uri, str): raise TypeError('Subfulfillment must be provided as a URI string') self.add_subfulfillment(Fulfillment.from_uri(subfulfillment_uri))
def parse_asn1_dict_payload(self, data): self.threshold = len(data['subfulfillments']) for subfulfillment in data['subfulfillments']: self.subconditions.append({ 'type': FULFILLMENT, 'body': Fulfillment.from_asn1_dict(subfulfillment), }) for subcondition in data['subconditions']: self.subconditions.append({ 'type': CONDITION, 'body': Condition.from_asn1_dict(subcondition), })
def test_parse_json_with_subconditions(self, minimal_threshold): from cryptoconditions.fulfillment import Fulfillment from cryptoconditions.types.threshold import ThresholdSha256 subfulfillment = Fulfillment.from_json( minimal_threshold.json.pop('subfulfillments')[0]) subcondition_object = subfulfillment.condition minimal_threshold.json['subconditions'] = [ subcondition_object.to_json() ] threshold_obj = ThresholdSha256() threshold_obj.parse_json(minimal_threshold.json) assert len(threshold_obj.subconditions) == 1 assert (threshold_obj.subconditions[0]['body'].serialize_uri() == subfulfillment.condition_uri)
def parse_dict(self, data): """ Generate fulfillment payload from a dict Args: data (dict): description of the fulfillment Returns: Fulfillment """ self.threshold = data['threshold'] for subfulfillments in data.get('subfulfillments', ()): self.add_subfulfillment(Fulfillment.from_dict(subfulfillments)) for subconditions in data.get('subconditions', ()): self.add_subcondition(Condition.from_dict(subfulfillments))
def _set_subfulfillment(self, subfulfillment): """Set the (fulfilled) subcondition. When constructing a prefix fulfillment, this method allows you to pass in a fulfillment for the condition that will receive the prefixed message. Note that you only have to add either the subcondition or a subfulfillment, but not both. Args: subfulfillment {Fulfillment|str}: Fulfillment object or URI string representing the fulfillment to use as the subcondition. """ if isinstance(subfulfillment, str): subfulfillment = Fulfillment.from_uri(subfulfillment) elif not isinstance(subfulfillment, Fulfillment): raise Exception( 'Subfulfillments must be URIs or objects of type Fulfillment') self._subcondition = subfulfillment
def parse_json(self, json_data): """ Generate fulfillment payload from a json Args: json_data: json description of the fulfillment Returns: Fulfillment """ if not isinstance(json_data, dict): raise TypeError('reader must be a dict instance') self.threshold = json_data['threshold'] for subfulfillments_json in json_data['subfulfillments']: weight = subfulfillments_json['weight'] if subfulfillments_json['type'] == FULFILLMENT: self.add_subfulfillment(Fulfillment.from_json(subfulfillments_json), weight) elif subfulfillments_json['type'] == CONDITION: self.add_subcondition(Condition.from_json(subfulfillments_json), weight) else: raise TypeError('Subconditions must provide either subcondition or fulfillment.')
def add_subfulfillment(self, subfulfillment): """ Add a fulfilled subcondition. When constructing a threshold fulfillment, this method allows you to provide a fulfillment for one of the subconditions. Note that you do **not** have to add the subcondition if you're adding the fulfillment. The condition can be calculated from the fulfillment and will be added automatically. Args: subfulfillment (:class:`~cryptoconditions.fulfillment.Fulfillment or :obj:`str`): Fulfillment object or URI string representing a new subfulfillment to be added. """ if isinstance(subfulfillment, str): subfulfillment = Fulfillment.from_uri(subfulfillment) elif not isinstance(subfulfillment, Fulfillment): raise TypeError('Subfulfillments must be URIs or objects of type Fulfillment') self.subconditions.append( {'type': FULFILLMENT, 'body': subfulfillment})
def parse_asn1_dict_payload(self, data): self.prefix = data['prefix'] self.max_message_length = data['maxMessageLength'] self._set_subfulfillment( Fulfillment.from_asn1_dict(data['subfulfillment']))
def fulfillment_to_condition(serialized_fulfillment): fulfillment = Fulfillment.from_uri(serialized_fulfillment) return fulfillment.condition_uri
def parse_json(self, data): self.prefix = urlsafe_b64decode(base64_add_padding(data['prefix'])) self.max_message_length = data['maxMessageLength'] self._set_subfulfillment(Fulfillment.from_json(data['subfulfillment']))
def from_dict(data): fulfillment = Fulfillment.from_dict(data) return fulfillment