Пример #1
0
 def _validate_outputs(self) -> None:
     if 'outputs' not in self.request:
         raise InvalidSignatureRequest("no outputs")
     self.outputs = self.request['outputs']
     if not isinstance(self.outputs, list):
         raise InvalidSignatureRequest("outputs is not an array")
     if len(self.outputs) == 0:
         raise InvalidSignatureRequest("at least one output is required")
     for output in self.outputs:
         self._validate_output(output)
Пример #2
0
    def _validate_output(self, output: Dict) -> None:
        if 'address' not in output:
            raise InvalidSignatureRequest("no address in output")
        if not isinstance(output['address'], (str, )):
            err_msg = "output addresses must be base58-encoded strings"
            raise InvalidSignatureRequest(err_msg)

        if output['address'][:2] in ('bc', 'tb'):
            err_msg = "bech32 addresses are unsupported (output)"
            raise InvalidSignatureRequest(err_msg)
        try:
            base58.CBase58Data(output['address'])
        except base58.InvalidBase58Error:
            err_msg = "output addresses must be base58-encoded strings"
            raise InvalidSignatureRequest(err_msg)
        except base58.Base58ChecksumError:
            err_msg = "invalid output address checksum"
            raise InvalidSignatureRequest(err_msg)
        try:
            CBitcoinAddress(output['address'])
        except CBitcoinAddressError:
            err_msg = "invalid output address (check mainnet vs. testnet)"
            raise InvalidSignatureRequest(err_msg)

        if 'amount' not in output:
            raise InvalidSignatureRequest("no amount in output")
        if type(output['amount']) != int:
            err_msg = "output amount must be an integer (satoshis)"
            raise InvalidSignatureRequest(err_msg)
        if output['amount'] <= 0:
            raise InvalidSignatureRequest("invalid output amount")
Пример #3
0
    def _validate_input(self, input: Dict) -> None:
        if 'amount' not in input:
            raise InvalidSignatureRequest("no amount in input")
        if type(input['amount']) != int:
            err_msg = "input amount must be an integer (satoshis)"
            raise InvalidSignatureRequest(err_msg)
        if input['amount'] <= 0:
            raise InvalidSignatureRequest("invalid input amount")

        if 'txid' not in input:
            raise InvalidSignatureRequest("no txid in input")
        if len(input['txid']) != 64:
            raise InvalidSignatureRequest("txid must be 64 characters")
        try:
            binascii.unhexlify(input['txid'].encode('utf8'))
        except ValueError:
            err_msg = "input TXIDs must be hexadecimal strings"
            raise InvalidSignatureRequest(err_msg)

        if 'index' not in input:
            raise InvalidSignatureRequest("no index in input")
        if type(input['index']) != int:
            err_msg = "input index must be an integer"
            raise InvalidSignatureRequest(err_msg)
        if input['index'] < 0:
            raise InvalidSignatureRequest("invalid input index")
Пример #4
0
 def _validate_input_groups(self) -> None:
     if 'inputs' not in self.request:
         raise InvalidSignatureRequest("no input groups")
     input_groups = self.request['inputs']
     if not isinstance(input_groups, list):
         raise InvalidSignatureRequest("input groups is not an array")
     if len(input_groups) == 0:
         raise InvalidSignatureRequest(
             "at least one input group is required")
     self.inputs = []
     for input_group in input_groups:
         self._validate_input_group(input_group)
Пример #5
0
def decode_qr_code_data(encoded: bytes) -> str:
    try:
        compressed_bytes = b32decode(encoded)
        try:
            decompressed_bytes = decompress(compressed_bytes)
            try:
                data = decompressed_bytes.decode('utf-8')
                return data
            except UnicodeError:
                raise InvalidSignatureRequest("Not valid UTF-8")
        except LZMAError:
            raise InvalidSignatureRequest("Not LZMA compressed")
    except (TypeError, Base32DecodeError):
        raise InvalidSignatureRequest("Not Base32")
Пример #6
0
def encode_qr_code_data(decoded: str) -> bytes:
    try:
        uncompressed_bytes = decoded.encode('utf-8')
        try:
            compressed_bytes = compress(uncompressed_bytes,
                                        format=FORMAT_ALONE)
            try:
                data = b32encode(compressed_bytes)
                return data
            except TypeError:
                raise InvalidSignatureRequest("Failed to Base32-encode")
        except LZMAError:
            raise InvalidSignatureRequest("Failed to LZMA-compress")
    except UnicodeError:
        raise InvalidSignatureRequest("Failed to encode as UTF-8")
Пример #7
0
def decode_qr_code_data(encoded: bytes) -> str:
    if not isinstance(encoded, (bytes,)):
        raise InvalidSignatureRequest("Can only decode bytes")
    if encoded == b'':
        raise InvalidSignatureRequest("Cannot decode empty bytes")
    try:
        compressed_bytes = b32decode(encoded)
        try:
            decompressed_bytes = decompress(compressed_bytes)
            try:
                data = decompressed_bytes.decode('utf-8')
                return data
            except UnicodeError:
                raise InvalidSignatureRequest("Not valid UTF-8")
        except OSError:
            raise InvalidSignatureRequest("Not gzipped")
    except (TypeError, Base32DecodeError):
        raise InvalidSignatureRequest("Not Base32")
Пример #8
0
def encode_qr_code_data(decoded: str) -> bytes:
    if not isinstance(decoded, (str,)):
        raise InvalidSignatureRequest("Can only encode strings")
    if decoded.strip() == '':
        raise InvalidSignatureRequest("Cannot encode empty string")
    try:
        uncompressed_bytes = decoded.encode('utf-8')
        try:
            compressed_bytes = compress(uncompressed_bytes)
            try:
                data = b32encode(compressed_bytes)
                return data
            except TypeError:
                raise InvalidSignatureRequest("Failed to Base32-encode")
        except OSError:
            raise InvalidSignatureRequest("Failed to gzip")
    except UnicodeError:
        raise InvalidSignatureRequest("Failed to encode as UTF-8")
Пример #9
0
 def _validate_input_group(self, input_group: list) -> None:
     if len(input_group) < 3:
         raise InvalidSignatureRequest(
             "input group must include redeem script, BIP32 path, and at least one input"
         )
     redeem_script = input_group[0]
     self._validate_redeem_script(redeem_script)
     bip32_path = input_group[1]
     self.validate_bip32_path(bip32_path)
     address = generate_multisig_address(redeem_script, self.testnet)
     for input in input_group[2:]:
         self._validate_input(input)
         input['redeem_script'] = redeem_script
         input['bip32_path'] = bip32_path
         input['address'] = address
         self.inputs.append(input)
Пример #10
0
 def _validate_fee(self) -> None:
     sum_inputs = sum([input['amount'] for input in self.inputs])
     sum_outputs = sum([output['amount'] for output in self.outputs])
     self.fee = sum_inputs - sum_outputs
     if self.fee < 0:
         raise InvalidSignatureRequest("fee cannot be negative")
Пример #11
0
 def _validate_redeem_script(self, redeem_script: bytes) -> None:
     try:
         binascii.unhexlify(redeem_script.encode('utf8'))
     except (ValueError, AttributeError):
         raise InvalidSignatureRequest("redeem script is not valid hex")
Пример #12
0
 def test_InvalidSignatureRequest_raisable_with_message(self):
     with pytest.raises(InvalidSignatureRequest) as e_info:
         raise InvalidSignatureRequest("test")
     assert str(e_info.value) == "Invalid signature request: test."