Ejemplo n.º 1
0
    def createFilter(
            self, *,  # PEP 3102
            argument_filters=None,
            fromBlock=None,
            toBlock="latest",
            address=None,
            topics=None):
        """
        Create filter object that tracks logs emitted by this contract event.
        :param filter_params: other parameters to limit the events
        """
        if fromBlock is None:
            raise TypeError("Missing mandatory keyword argument to createFilter: fromBlock")

        if argument_filters is None:
            argument_filters = dict()

        _filters = dict(**argument_filters)

        event_abi = self._get_event_abi()

        check_for_forbidden_api_filter_arguments(event_abi, _filters)

        _, event_filter_params = construct_event_filter_params(
            self._get_event_abi(),
            contract_address=self.address,
            argument_filters=_filters,
            fromBlock=fromBlock,
            toBlock=toBlock,
            address=address,
            topics=topics,
        )

        filter_builder = EventFilterBuilder(event_abi)
        filter_builder.address = event_filter_params.get('address')
        filter_builder.fromBlock = event_filter_params.get('fromBlock')
        filter_builder.toBlock = event_filter_params.get('toBlock')
        match_any_vals = {
            arg: value for arg, value in _filters.items()
            if not is_array_type(filter_builder.args[arg].arg_type) and is_list_like(value)
        }
        for arg, value in match_any_vals.items():
            filter_builder.args[arg].match_any(*value)

        match_single_vals = {
            arg: value for arg, value in _filters.items()
            if not is_array_type(filter_builder.args[arg].arg_type) and not is_list_like(value)
        }
        for arg, value in match_single_vals.items():
            filter_builder.args[arg].match_single(value)

        log_filter = filter_builder.deploy(self.web3)
        log_filter.log_entry_formatter = get_event_data(self._get_event_abi())
        log_filter.builder = filter_builder

        return log_filter
Ejemplo n.º 2
0
def construct_event_filter_params(event_abi,
                                  contract_address=None,
                                  argument_filters=None,
                                  topics=None,
                                  fromBlock=None,
                                  toBlock=None,
                                  address=None):
    filter_params = {}
    topic_set = construct_event_topic_set(event_abi, argument_filters)

    if topics is not None:
        if len(topic_set) > 1:
            raise TypeError(
                "Merging the topics argument with topics generated "
                "from argument_filters is not supported.")
        topic_set = topics

    if len(topic_set) == 1 and is_list_like(topic_set[0]):
        filter_params['topics'] = topic_set[0]
    else:
        filter_params['topics'] = topic_set

    if address and contract_address:
        if is_list_like(address):
            filter_params['address'] = address + [contract_address]
        elif is_string(address):
            filter_params['address'] = [address, contract_address]
        else:
            raise ValueError(
                "Unsupported type for `address` parameter: {0}".format(type(address))
            )
    elif address:
        filter_params['address'] = address
    elif contract_address:
        filter_params['address'] = contract_address

    if 'address' not in filter_params:
        pass
    elif is_list_like(filter_params['address']):
        for addr in filter_params['address']:
            validate_address(addr)
    else:
        validate_address(filter_params['address'])

    if fromBlock is not None:
        filter_params['fromBlock'] = fromBlock

    if toBlock is not None:
        filter_params['toBlock'] = toBlock

    data_filters_set = construct_event_data_set(event_abi, argument_filters)

    return data_filters_set, filter_params
Ejemplo n.º 3
0
    def test_eth_newFilter(self, web3: "Web3") -> None:
        filter = web3.eth.filter({})

        changes = web3.eth.getFilterChanges(filter.filter_id)
        assert is_list_like(changes)
        assert not changes

        logs = web3.eth.getFilterLogs(filter.filter_id)
        assert is_list_like(logs)
        assert not logs

        result = web3.eth.uninstallFilter(filter.filter_id)
        assert result is True
Ejemplo n.º 4
0
    def test_eth_newFilter(self, web3):
        filter = web3.eth.filter({})

        changes = web3.eth.getFilterChanges(filter.filter_id)
        assert is_list_like(changes)
        assert not changes

        logs = web3.eth.getFilterLogs(filter.filter_id)
        assert is_list_like(logs)
        assert not logs

        result = web3.eth.uninstallFilter(filter.filter_id)
        assert result is True
Ejemplo n.º 5
0
def construct_event_filter_params(event_abi,
                                  contract_address=None,
                                  argument_filters=None,
                                  topics=None,
                                  fromBlock=None,
                                  toBlock=None,
                                  address=None):
    filter_params = {}

    if topics is None:
        topic_set = construct_event_topic_set(event_abi, argument_filters)
    else:
        topic_set = [topics] + construct_event_topic_set(
            event_abi, argument_filters)

    if len(topic_set) == 1 and is_list_like(topic_set[0]):
        filter_params['topics'] = topic_set[0]
    else:
        filter_params['topics'] = topic_set

    if address and contract_address:
        if is_list_like(address):
            filter_params['address'] = address + [contract_address]
        elif is_string(address):
            filter_params['address'] = [address, contract_address]
        else:
            raise ValueError(
                "Unsupported type for `address` parameter: {0}".format(
                    type(address)))
    elif address:
        filter_params['address'] = address
    elif contract_address:
        filter_params['address'] = contract_address

    if 'address' not in filter_params:
        pass
    elif is_list_like(filter_params['address']):
        for addr in filter_params['address']:
            validate_address(addr)
    else:
        validate_address(filter_params['address'])

    if fromBlock is not None:
        filter_params['fromBlock'] = fromBlock

    if toBlock is not None:
        filter_params['toBlock'] = toBlock

    data_filters_set = construct_event_data_set(event_abi, argument_filters)

    return data_filters_set, filter_params
Ejemplo n.º 6
0
 def providers(self, value):
     if not is_list_like(value):
         providers = [value]
     else:
         providers = value
     self._providers = providers
     self._generate_request_functions()
Ejemplo n.º 7
0
def generate_cache_key(value):
    """
    Generates a cache key for the *args and **kwargs
    """
    if is_bytes(value):
        return hashlib.md5(value).hexdigest()
    elif is_text(value):
        return generate_cache_key(force_bytes(value))
    elif is_boolean(value) or is_null(value) or is_number(value):
        return generate_cache_key(repr(value))
    elif is_dict(value):
        return generate_cache_key((
            (key, value[key])
            for key
            in sorted(value.keys())
        ))
    elif is_list_like(value) or isinstance(value, Generator):
        return generate_cache_key("".join((
            generate_cache_key(item)
            for item
            in value
        )))
    else:
        raise TypeError("Cannot generate cache key for value {0} of type {1}".format(
            value,
            type(value),
        ))
Ejemplo n.º 8
0
def normalize_filter_params(from_block, to_block, address, topics):
    yield from_block
    yield to_block

    if address is None:
        yield address
    elif is_address(address):
        yield to_canonical_address(address)
    elif is_list_like(address):
        yield tuple(to_canonical_address(item) for item in address)
    else:
        raise TypeError(
            "Address is not in a recognized format: {0}".format(address))

    if topics is None:
        yield topics
    elif is_flat_topic_array(topics):
        yield tuple(decode_hex(item) for item in topics)
    elif all(is_flat_topic_array(item) for item in topics):
        yield tuple(
            tuple(decode_hex(sub_item) for sub_item in item)
            for item in topics)
    else:
        raise TypeError(
            "Topics are not in a recognized format: {0}".format(address))
Ejemplo n.º 9
0
def bytes_repr(value):
    if is_bytes(value):
        yield value
    elif is_text(value):
        yield to_bytes(text=value)
    elif is_list_like(value):
        yield b''.join((
            b'(',
            b','.join(bytes_repr(item) for item in value),
            b')',
        ))
    elif is_dict(value):
        yield b''.join((
            b'{',
            b','.join((
                b":".join((bytes_repr(key), bytes_repr(item)))
                for key, item
                in value.items()
            )),
            b'}',
        ))
    elif is_integer(value):
        yield to_bytes(value)
    elif is_null(value):
        yield 'None@{}'.format(id(value))
    else:
        raise TypeError("Unsupported type for bytes_repr: {}".format(type(value)))
Ejemplo n.º 10
0
def get_netting_channel_closed_events(
    chain: BlockChainService,
    token_network_address: Address,
    netting_channel_identifier: ChannelID,
    contract_manager: ContractManager,
    from_block: BlockSpecification = 0,
    to_block: BlockSpecification = 'latest',
) -> List[Dict]:
    closed_event_abi = contract_manager.get_event_abi(
        CONTRACT_TOKEN_NETWORK,
        ChannelEvent.CLOSED,
    )

    topic_set = construct_event_topic_set(
        event_abi=closed_event_abi,
        arguments={'channel_identifier': netting_channel_identifier},
    )

    if len(topic_set) == 1 and is_list_like(topic_set[0]):
        topics = topic_set[0]
    else:
        topics = topic_set

    return get_contract_events(
        chain=chain,
        abi=contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK),
        contract_address=token_network_address,
        topics=topics,
        from_block=from_block,
        to_block=to_block,
    )
Ejemplo n.º 11
0
def construct_event_topic_set(event_abi, arguments=None):
    if arguments is None:
        arguments = {}
    if isinstance(arguments, (list, tuple)):
        if len(arguments) != len(event_abi['inputs']):
            raise ValueError(
                "When passing an argument list, the number of arguments must "
                "match the event constructor.")
        arguments = {
            arg['name']: [arg_value]
            for arg, arg_value in zip(event_abi['inputs'], arguments)
        }

    normalized_args = {
        key: value if is_list_like(value) else [value]
        for key, value in arguments.items()
    }

    event_topic = encode_hex(event_abi_to_log_topic(event_abi))
    indexed_args = get_indexed_event_inputs(event_abi)
    zipped_abi_and_args = [(arg, normalized_args.get(arg['name'], [None]))
                           for arg in indexed_args]
    encoded_args = [[
        None if option is None else encode_hex(
            encode_single(arg['type'], option)) for option in arg_options
    ] for arg, arg_options in zipped_abi_and_args]

    topics = list(normalize_topic_list([event_topic] + encoded_args))
    return topics
Ejemplo n.º 12
0
def construct_event_data_set(event_abi, arguments=None):
    if arguments is None:
        arguments = {}
    if isinstance(arguments, (list, tuple)):
        if len(arguments) != len(event_abi['inputs']):
            raise ValueError(
                "When passing an argument list, the number of arguments must "
                "match the event constructor.")
        arguments = {
            arg['name']: [arg_value]
            for arg, arg_value in zip(event_abi['inputs'], arguments)
        }

    normalized_args = {
        key: value if is_list_like(value) else [value]
        for key, value in arguments.items()
    }

    non_indexed_args = exclude_indexed_event_inputs(event_abi)
    zipped_abi_and_args = [(arg, normalized_args.get(arg['name'], [None]))
                           for arg in non_indexed_args]
    encoded_args = [[
        None if option is None else encode_hex(
            encode_single(arg['type'], option)) for option in arg_options
    ] for arg, arg_options in zipped_abi_and_args]

    data = [
        list(permutation) if any(value is not None
                                 for value in permutation) else []
        for permutation in itertools.product(*encoded_args)
    ]
    return data
Ejemplo n.º 13
0
def _decode_auth(encoded_packet: bytes) -> Tuple[Union[AuthHeader, Nonce], int]:
    try:
        decoded_auth, _, message_start_index = rlp.codec.consume_item(encoded_packet, TAG_SIZE)
    except DecodingError as error:
        raise ValidationError("Packet authentication section is not proper RLP") from error

    if is_bytes(decoded_auth):
        validate_nonce(decoded_auth)
        return Nonce(decoded_auth), message_start_index
    elif is_list_like(decoded_auth):
        validate_length(decoded_auth, 5, "auth header")
        for index, element in enumerate(decoded_auth):
            if not is_bytes(element):
                raise ValidationError(f"Element {index} in auth header is not bytes: {element}")
        auth_header = AuthHeader(
            auth_tag=decoded_auth[0],
            id_nonce=decoded_auth[1],
            auth_scheme_name=decoded_auth[2],
            ephemeral_public_key=decoded_auth[3],
            encrypted_auth_response=decoded_auth[4],
        )
        validate_auth_header(auth_header)
        return auth_header, message_start_index
    else:
        raise Exception("unreachable: RLP can only encode bytes and lists")
Ejemplo n.º 14
0
def is_encodable(_type, value):
    if not isinstance(_type, str):
        raise ValueError("is_encodable only accepts type strings")

    base, sub, arrlist = process_type(_type)

    if arrlist:
        if not is_list_like(value):
            return False
        if arrlist[-1] and len(value) != arrlist[-1][0]:
            return False
        sub_type = (base, sub, arrlist[:-1])
        return all(is_encodable(collapse_type(*sub_type), sub_value) for sub_value in value)
    elif base == 'address' and is_ens_name(value):
        # ENS names can be used anywhere an address is needed
        # Web3.py will resolve the name to an address before encoding it
        return True
    elif base == 'bytes' and isinstance(value, str):
        # Hex-encoded bytes values can be used anywhere a bytes value is needed
        if is_hex(value) and len(value) % 2 == 0:
            # Require hex-encoding of full bytes (even length)
            bytes_val = to_bytes(hexstr=value)
            return eth_abi_is_encodable(_type, bytes_val)
        else:
            return False
    elif base == 'string' and isinstance(value, bytes):
        # bytes that were encoded with utf-8 can be used anywhere a string is needed
        try:
            string_val = to_text(value)
        except UnicodeDecodeError:
            return False
        else:
            return eth_abi_is_encodable(_type, string_val)
    else:
        return eth_abi_is_encodable(_type, value)
Ejemplo n.º 15
0
def stringify(value):
    if is_bytes(value):
        yield value
    elif is_text(value):
        yield force_bytes(value)
    elif is_list_like(value):
        yield b''.join((
            b'(',
            b','.join((stringify(item) for item in value)),
            b')',
        ))
    elif is_dict(value):
        yield b''.join((
            b'{',
            b','.join((b":".join((stringify(key), stringify(item)))
                       for key, item in value.items())),
            b'}',
        ))
    elif is_integer(value):
        yield force_bytes(str(value))
    elif is_null(value):
        yield 'None@{0}'.format(id(value))
    else:
        raise TypeError("Unsupported type for stringification: {0}".format(
            type(value)))
Ejemplo n.º 16
0
def generate_cache_key(value):
    """
    Generates a cache key for the *args and **kwargs
    """
    if is_bytes(value):
        return hashlib.md5(value).hexdigest()
    elif is_text(value):
        return generate_cache_key(force_bytes(value))
    elif is_boolean(value) or is_null(value) or is_number(value):
        return generate_cache_key(repr(value))
    elif is_dict(value):
        return generate_cache_key((
            (key, value[key])
            for key
            in sorted(value.keys())
        ))
    elif is_list_like(value) or isinstance(value, Generator):
        return generate_cache_key("".join((
            generate_cache_key(item)
            for item
            in value
        )))
    else:
        raise TypeError("Cannot generate cache key for value {0} of type {1}".format(
            value,
            type(value),
        ))
Ejemplo n.º 17
0
def get_netting_channel_deposit_events(
        chain: BlockChainService,
        token_network_address: Address,
        netting_channel_identifier: ChannelID,
        contract_manager: ContractManager,
        from_block: BlockSpecification = GENESIS_BLOCK_NUMBER,
        to_block: BlockSpecification = 'latest',
) -> List[Dict]:
    deposit_event_abi = contract_manager.get_event_abi(
        CONTRACT_TOKEN_NETWORK,
        ChannelEvent.DEPOSIT,
    )
    topic_set = construct_event_topic_set(
        event_abi=deposit_event_abi,
        arguments={'channel_identifier': netting_channel_identifier},
    )

    if len(topic_set) == 1 and is_list_like(topic_set[0]):
        topics = topic_set[0]
    else:
        topics = topic_set

    return get_contract_events(
        chain,
        contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK),
        token_network_address,
        topics,
        from_block,
        to_block,
    )
Ejemplo n.º 18
0
def get_netting_channel_deposit_events(
        chain: BlockChainService,
        token_network_address: Address,
        netting_channel_identifier: ChannelID,
        contract_manager: ContractManager,
        from_block: BlockSpecification = GENESIS_BLOCK_NUMBER,
        to_block: BlockSpecification = 'latest',
) -> List[Dict]:
    deposit_event_abi = contract_manager.get_event_abi(
        CONTRACT_TOKEN_NETWORK,
        ChannelEvent.DEPOSIT,
    )
    topic_set = construct_event_topic_set(
        event_abi=deposit_event_abi,
        arguments={'channel_identifier': netting_channel_identifier},
    )

    if len(topic_set) == 1 and is_list_like(topic_set[0]):
        topics = topic_set[0]
    else:
        topics = topic_set

    return get_contract_events(
        chain,
        contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK),
        token_network_address,
        topics,
        from_block,
        to_block,
    )
Ejemplo n.º 19
0
def is_encodable(_type, value):
    try:
        base, sub, arrlist = _type
    except ValueError:
        base, sub, arrlist = process_type(_type)

    if arrlist:
        if not is_list_like(value):
            return False
        if arrlist[-1] and len(value) != arrlist[-1][0]:
            return False
        sub_type = (base, sub, arrlist[:-1])
        return all(is_encodable(sub_type, sub_value) for sub_value in value)
    elif base == 'address' and is_ens_name(value):
        # ENS names can be used anywhere an address is needed
        # Web3.py will resolve the name to an address before encoding it
        return True
    elif base == 'bytes' and isinstance(value, str):
        # Hex-encoded bytes values can be used anywhere a bytes value is needed
        if is_hex(value) and len(value) % 2 == 0:
            # Require hex-encoding of full bytes (even length)
            bytes_val = to_bytes(hexstr=value)
            return eth_abi_is_encodable(_type, bytes_val)
        else:
            return False
    elif base == 'string' and isinstance(value, bytes):
        # bytes that were encoded with utf-8 can be used anywhere a string is needed
        try:
            string_val = to_text(value)
        except UnicodeDecodeError:
            return False
        else:
            return eth_abi_is_encodable(_type, string_val)
    else:
        return eth_abi_is_encodable(_type, value)
Ejemplo n.º 20
0
def construct_event_topic_set(event_abi, arguments=None):
    if arguments is None:
        arguments = {}
    if isinstance(arguments, (list, tuple)):
        if len(arguments) != len(event_abi['inputs']):
            raise ValueError(
                "When passing an argument list, the number of arguments must "
                "match the event constructor."
            )
        arguments = {
            arg['name']: [arg_value]
            for arg, arg_value
            in zip(event_abi['inputs'], arguments)
        }

    normalized_args = {
        key: value if is_list_like(value) else [value]
        for key, value in arguments.items()
    }

    event_topic = encode_hex(event_abi_to_log_topic(event_abi))
    indexed_args = get_indexed_event_inputs(event_abi)
    zipped_abi_and_args = [
        (arg, normalized_args.get(arg['name'], [None]))
        for arg in indexed_args
    ]
    encoded_args = [
        [
            None if option is None else encode_hex(encode_single(arg['type'], option))
            for option in arg_options]
        for arg, arg_options in zipped_abi_and_args
    ]

    topics = list(normalize_topic_list([event_topic] + encoded_args))
    return topics
Ejemplo n.º 21
0
def get_netting_channel_settled_events(
        chain: BlockChainService,
        token_network_address: Address,
        netting_channel_identifier: ChannelID,
        from_block: BlockSpecification = 0,
        to_block: BlockSpecification = 'latest',
) -> List[Dict]:
    settled_event_abi = CONTRACT_MANAGER.get_event_abi(
        CONTRACT_TOKEN_NETWORK,
        ChannelEvent.SETTLED,
    )
    topic_set = construct_event_topic_set(
        event_abi=settled_event_abi,
        arguments={'channel_identifier': netting_channel_identifier},
    )

    if len(topic_set) == 1 and is_list_like(topic_set[0]):
        topics = topic_set[0]
    else:
        topics = topic_set

    return get_contract_events(
        chain,
        CONTRACT_MANAGER.get_contract_abi(CONTRACT_TOKEN_NETWORK),
        token_network_address,
        topics,
        from_block,
        to_block,
    )
def test_auth_header_preparation_without_enr(tag,
                                             auth_tag,
                                             id_nonce,
                                             initiator_key,
                                             auth_response_key,
                                             ephemeral_public_key):
    message = PingMessage(
        request_id=5,
        enr_seq=1,
    )
    id_nonce_signature = b"\x00" * 32

    packet = AuthHeaderPacket.prepare(
        tag=tag,
        auth_tag=auth_tag,
        id_nonce=id_nonce,
        message=message,
        initiator_key=initiator_key,
        id_nonce_signature=id_nonce_signature,
        auth_response_key=auth_response_key,
        enr=None,
        ephemeral_public_key=ephemeral_public_key
    )

    decrypted_auth_response = aesgcm_decrypt(
        key=auth_response_key,
        nonce=ZERO_NONCE,
        cipher_text=packet.auth_header.encrypted_auth_response,
        authenticated_data=b"",
    )
    decoded_auth_response = rlp.decode(decrypted_auth_response)
    assert is_list_like(decoded_auth_response) and len(decoded_auth_response) == 3
    assert decoded_auth_response[0] == int_to_big_endian(AUTH_RESPONSE_VERSION)
    assert decoded_auth_response[1] == id_nonce_signature
    assert decoded_auth_response[2] == []
Ejemplo n.º 23
0
def get_netting_channel_deposit_events(
    proxy_manager: ProxyManager,
    token_network_address: TokenNetworkAddress,
    netting_channel_identifier: ChannelID,
    contract_manager: ContractManager,
    from_block: BlockSpecification = GENESIS_BLOCK_NUMBER,
    to_block: BlockSpecification = "latest",
) -> List[Dict]:
    deposit_event_abi = contract_manager.get_event_abi(CONTRACT_TOKEN_NETWORK,
                                                       ChannelEvent.DEPOSIT)
    topic_set = construct_event_topic_set(
        event_abi=deposit_event_abi,
        arguments={"channel_identifier": netting_channel_identifier})

    if len(topic_set) == 1 and is_list_like(topic_set[0]):
        topics = topic_set[0]
    else:
        topics = topic_set

    return get_contract_events(
        proxy_manager,
        contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK),
        Address(token_network_address),
        topics,
        from_block,
        to_block,
    )
Ejemplo n.º 24
0
    def decrypt_auth_response(
            self, auth_response_key: AES128Key) -> Tuple[bytes, Optional[ENR]]:
        """Extract id nonce signature and optional ENR from auth header packet."""
        plain_text = aesgcm_decrypt(
            key=auth_response_key,
            nonce=ZERO_NONCE,
            cipher_text=self.auth_header.encrypted_auth_response,
            authenticated_data=self.tag,
        )

        try:
            decoded_rlp = rlp.decode(plain_text)
        except DecodingError as error:
            raise ValidationError(
                f"Auth response does not contain valid RLP: {encode_hex(plain_text)}"
            )

        if not is_list_like(decoded_rlp):
            raise ValidationError(
                f"Auth response contains bytes instead of list: {encode_hex(decoded_rlp)}"
            )

        if len(decoded_rlp) != 2:
            raise ValidationError(
                f"Auth response is a list of {len(decoded_rlp)} instead of two elements"
            )
        id_nonce_signature, serialized_enr = decoded_rlp

        if not is_bytes(id_nonce_signature):
            raise ValidationError(
                f"Id nonce signature is a list instead of bytes: {id_nonce_signature}"
            )

        if not is_list_like(serialized_enr):
            raise ValidationError(
                f"ENR is bytes instead of list: {encode_hex(serialized_enr)}")

        if len(serialized_enr) == 0:
            enr = None
        else:
            try:
                enr = ENR.deserialize(serialized_enr)
            except DeserializationError as error:
                raise ValidationError(
                    "ENR in auth response is not properly encoded") from error

        return id_nonce_signature, enr
Ejemplo n.º 25
0
 def wrapper(*args, **kwargs):
     value = fn(*args, **kwargs)
     if is_string(value):
         return os.path.relpath(value)
     elif is_list_like(value):
         return type(value)([os.path.relpath(path) for path in value])
     else:
         raise TypeError("Unsupported type: {0}".format(type(value)))
Ejemplo n.º 26
0
 def test_personal_list_wallets(self, web3: "Web3") -> None:
     wallets = web3.geth.personal.list_wallets()
     assert is_list_like(wallets)
     assert len(wallets) > 0
     assert is_checksum_address(wallets[0]['accounts'][0]['address'])
     assert is_string(wallets[0]['accounts'][0]['url'])
     assert is_string(wallets[0]['status'])
     assert is_string(wallets[0]['url'])
Ejemplo n.º 27
0
def topic_to_name(param):
    if is_list_like(param):
        return [topic_to_name(t) for t in param]
    if isinstance(param, bytes):
        topic_int = big_endian_to_int(param)
        return chr(topic_int + 65)
    else:
        return param
Ejemplo n.º 28
0
 def encode_elements(cls, value):
     if not is_list_like(value):
         raise EncodingTypeError(
             "Cannot encode value of type {0} using array encoder.  Must be "
             "a list-like object such as an array or tuple".format(
                 type(value), ))
     encoded_elements = b''.join((cls.item_encoder(item) for item in value))
     return encoded_elements
def test_auth_header_preparation(tag,
                                 auth_tag,
                                 id_nonce,
                                 initiator_key,
                                 auth_response_key,
                                 ephemeral_public_key):
    enr = ENR(
        sequence_number=1,
        signature=b"",
        kv_pairs={
            b"id": b"v4",
            b"secp256k1": b"\x02" * 33,
        }
    )
    message = PingMessage(
        request_id=5,
        enr_seq=enr.sequence_number,
    )
    id_nonce_signature = b"\x00" * 32

    packet = AuthHeaderPacket.prepare(
        tag=tag,
        auth_tag=auth_tag,
        id_nonce=id_nonce,
        message=message,
        initiator_key=initiator_key,
        id_nonce_signature=id_nonce_signature,
        auth_response_key=auth_response_key,
        enr=enr,
        ephemeral_public_key=ephemeral_public_key
    )

    assert packet.tag == tag
    assert packet.auth_header.auth_tag == auth_tag
    assert packet.auth_header.id_nonce == id_nonce
    assert packet.auth_header.auth_scheme_name == AUTH_SCHEME_NAME
    assert packet.auth_header.ephemeral_public_key == ephemeral_public_key

    decrypted_auth_response = aesgcm_decrypt(
        key=auth_response_key,
        nonce=ZERO_NONCE,
        cipher_text=packet.auth_header.encrypted_auth_response,
        authenticated_data=b"",
    )
    decoded_auth_response = rlp.decode(decrypted_auth_response)
    assert is_list_like(decoded_auth_response) and len(decoded_auth_response) == 3
    assert decoded_auth_response[0] == int_to_big_endian(AUTH_RESPONSE_VERSION)
    assert decoded_auth_response[1] == id_nonce_signature
    assert ENR.deserialize(decoded_auth_response[2]) == enr

    decrypted_message = aesgcm_decrypt(
        key=initiator_key,
        nonce=auth_tag,
        cipher_text=packet.encrypted_message,
        authenticated_data=tag,
    )
    assert decrypted_message[0] == message.message_type
    assert rlp.decode(decrypted_message[1:], PingMessage) == message
Ejemplo n.º 30
0
 def test_personal_listAccounts(self, webu):
     accounts = webu.personal.listAccounts
     assert is_list_like(accounts)
     assert len(accounts) > 0
     assert all((
         is_checksum_address(item)
         for item
         in accounts
     ))
Ejemplo n.º 31
0
    def validate_value(self, value):
        if not is_list_like(value):
            self.invalidate_value(
                value,
                msg="must be list-like such as array or tuple",
            )

        for item in value:
            self.item_encoder.validate_value(item)
Ejemplo n.º 32
0
    def validate_value(self, value):
        if not is_list_like(value):
            self.invalidate_value(
                value,
                msg="must be list-like such as array or tuple",
            )

        for item in value:
            self.item_encoder.validate_value(item)
Ejemplo n.º 33
0
def is_encodable(_type, value):
    try:
        base, sub, arrlist = _type
    except ValueError:
        base, sub, arrlist = process_type(_type)

    if arrlist:
        if not is_list_like(value):
            return False
        if arrlist[-1] and len(value) != arrlist[-1][0]:
            return False
        sub_type = (base, sub, arrlist[:-1])
        return all(is_encodable(sub_type, sub_value) for sub_value in value)
    elif base == 'bool':
        return is_boolean(value)
    elif base == 'uint':
        if not is_integer(value):
            return False
        exp = int(sub)
        if value < 0 or value >= 2**exp:
            return False
        return True
    elif base == 'int':
        if not is_integer(value):
            return False
        exp = int(sub)
        if value <= -1 * 2**(exp - 1) or value >= 2**(exp - 1):
            return False
        return True
    elif base == 'string':
        if not is_string(value):
            return False
        return True
    elif base == 'bytes':
        if not is_string(value):
            return False

        if not sub:
            return True

        max_length = int(sub)
        if isinstance(value, str):
            decodable = is_hex(value) and len(value) % 2 == 0
            return decodable and len(decode_hex(value)) <= max_length
        elif isinstance(value, bytes):
            return len(value) <= max_length
        else:
            False
    elif base == 'address':
        if is_ens_name(value):
            return True
        elif is_address(value):
            return True
        else:
            return False
    else:
        raise ValueError("Unsupported type")
Ejemplo n.º 34
0
 def test_personal_list_accounts(self, web3: "Web3") -> None:
     accounts = web3.geth.personal.list_accounts()
     assert is_list_like(accounts)
     assert len(accounts) > 0
     assert all((
         is_checksum_address(item)
         for item
         in accounts
     ))
Ejemplo n.º 35
0
def validate_abi(abi):
    """
    Helper function for validating an ABI
    """
    if not is_list_like(abi):
        raise TypeError("'abi' is not a list")
    for e in abi:
        if not is_dict(e):
            raise TypeError("The elements of 'abi' are not all dictionaries")
Ejemplo n.º 36
0
    def validate_value(self, value):
        if not is_list_like(value):
            raise EncodingTypeError(
                "Cannot encode value of type {0} using array encoder.  Must be "
                "a list-like object such as an array or tuple".format(
                    type(value), ))

        for item in value:
            self.item_encoder.validate_value(item)
Ejemplo n.º 37
0
def validate_abi(abi):
    """
    Helper function for validating an ABI
    """
    if not is_list_like(abi):
        raise ValueError("'abi' is not a list")
    for e in abi:
        if not is_dict(e):
            raise ValueError("The elements of 'abi' are not all dictionaries")
Ejemplo n.º 38
0
 def test_personal_listAccounts(self, web3):
     accounts = web3.personal.listAccounts
     assert is_list_like(accounts)
     assert len(accounts) > 0
     assert all((
         is_checksum_address(item)
         for item
         in accounts
     ))
Ejemplo n.º 39
0
def is_encodable(_type, value):
    try:
        base, sub, arrlist = _type
    except ValueError:
        base, sub, arrlist = process_type(_type)

    if arrlist:
        if not is_list_like(value):
            return False
        if arrlist[-1] and len(value) != arrlist[-1][0]:
            return False
        sub_type = (base, sub, arrlist[:-1])
        return all(is_encodable(sub_type, sub_value) for sub_value in value)
    elif base == 'bool':
        return is_boolean(value)
    elif base == 'uint':
        if not is_integer(value):
            return False
        exp = int(sub)
        if value < 0 or value >= 2**exp:
            return False
        return True
    elif base == 'int':
        if not is_integer(value):
            return False
        exp = int(sub)
        if value <= -1 * 2**(exp - 1) or value >= 2**(exp - 1):
            return False
        return True
    elif base == 'string':
        if not is_string(value):
            return False
        return True
    elif base == 'bytes':
        if not is_string(value):
            return False

        if not sub:
            return True

        max_length = int(sub)
        if isinstance(value, str):
            decodable = is_hex(value) and len(value) % 2 == 0
            return decodable and len(decode_hex(value)) <= max_length
        elif isinstance(value, bytes):
            return len(value) <= max_length
        else:
            return False
    elif base == 'address':
        if is_ens_name(value):
            return True
        elif is_address(value):
            return True
        else:
            return False
    else:
        raise ValueError("Unsupported type")
Ejemplo n.º 40
0
 def match(filename, pattern):
     if is_list_like(pattern):
         return any([fnmatch.fnmatch(filename, p) for p in pattern])
     elif is_string(pattern):
         return fnmatch.fnmatch(filename, pattern)
     else:
         raise TypeError(
             "Pattern must either be a string pattern or a list of patterns." +
             "  Got {0}".format(pattern)
         )
Ejemplo n.º 41
0
 def test_eth_accounts(self, web3):
     accounts = web3.eth.accounts
     assert is_list_like(accounts)
     assert len(accounts) != 0
     assert all((
         is_checksum_address(account)
         for account
         in accounts
     ))
     assert web3.eth.coinbase in accounts
Ejemplo n.º 42
0
 def test_vns_accounts(self, web3):
     accounts = web3.vns.accounts
     assert is_list_like(accounts)
     assert len(accounts) != 0
     assert all((
         is_checksum_address(account)
         for account
         in accounts
     ))
     assert web3.vns.coinbase in accounts
Ejemplo n.º 43
0
 def test_eth_accounts(self, web3):
     accounts = web3.eth.accounts
     assert is_list_like(accounts)
     assert len(accounts) != 0
     assert all((
         is_address(account)
         for account
         in accounts
     ))
     assert web3.eth.coinbase in accounts
Ejemplo n.º 44
0
 def wrapper(*args, **kwargs):
     value = fn(*args, **kwargs)
     if is_string(value):
         return os.path.relpath(value)
     elif is_list_like(value):
         return type(value)([
             os.path.relpath(path) for path in value
         ])
     else:
         raise TypeError("Unsupported type: {0}".format(type(value)))
Ejemplo n.º 45
0
def construct_event_filter_params(event_abi,
                                  contract_address=None,
                                  argument_filters=None,
                                  topics=None,
                                  fromBlock=None,
                                  toBlock=None,
                                  address=None):
    filter_params = {}

    if topics is None:
        topic_set = construct_event_topic_set(event_abi, argument_filters)
    else:
        topic_set = [topics] + construct_event_topic_set(event_abi, argument_filters)

    if len(topic_set) == 1 and is_list_like(topic_set[0]):
        filter_params['topics'] = topic_set[0]
    else:
        filter_params['topics'] = topic_set

    if address and contract_address:
        if is_list_like(address):
            filter_params['address'] = address + [contract_address]
        elif is_string(address):
            filter_params['address'] = [address, contract_address]
        else:
            raise ValueError(
                "Unsupported type for `address` parameter: {0}".format(type(address))
            )
    elif address:
        filter_params['address'] = address
    elif contract_address:
        filter_params['address'] = contract_address

    if fromBlock is not None:
        filter_params['fromBlock'] = fromBlock

    if toBlock is not None:
        filter_params['toBlock'] = toBlock

    data_filters_set = construct_event_data_set(event_abi, argument_filters)

    return data_filters_set, filter_params
Ejemplo n.º 46
0
def validate_abi_value(abi_type, value):
    """
    Helper function for validating a value against the expected abi_type
    Note: abi_type 'bytes' must either be python3 'bytes' object or ''
    """
    if is_array_type(abi_type) and is_list_like(value):
        # validate length
        specified_length = length_of_array_type(abi_type)
        if specified_length is not None:
            if specified_length < 1:
                raise TypeError(
                    "Invalid abi-type: {abi_type}. Length of fixed sized arrays"
                    "must be greater than 0."
                    .format(abi_type=abi_type)
                )
            if specified_length != len(value):
                raise TypeError(
                    "The following array length does not the length specified"
                    "by the abi-type, {abi_type}: {value}"
                    .format(abi_type=abi_type, value=value)
                )

        # validate sub_types
        sub_type = sub_type_of_array_type(abi_type)
        for v in value:
            validate_abi_value(sub_type, v)
        return
    elif is_bool_type(abi_type) and is_boolean(value):
        return
    elif is_uint_type(abi_type) and is_integer(value) and value >= 0:
        return
    elif is_int_type(abi_type) and is_integer(value):
        return
    elif is_address_type(abi_type):
        validate_address(value)
        return
    elif is_bytes_type(abi_type):
        if sys.version_info.major >= 3 and is_bytes(value):
            return
        elif is_string(value):
            if is_0x_prefixed(value):
                return
            else:
                raise TypeError(
                    "ABI values of abi-type 'bytes' must be either"
                    "a python3 'bytes' object or an '0x' prefixed string."
                )
    elif is_string_type(abi_type) and is_string(value):
        return

    raise TypeError(
        "The following abi value is not a '{abi_type}': {value}"
        .format(abi_type=abi_type, value=value)
    )
Ejemplo n.º 47
0
def check_for_forbidden_api_filter_arguments(event_abi, _filters):
    name_indexed_inputs = {_input['name']: _input for _input in event_abi['inputs']}

    for filter_name, filter_value in _filters.items():
        _input = name_indexed_inputs[filter_name]
        if is_array_type(_input['type']):
            raise TypeError(
                "createFilter no longer supports array type filter arguments. "
                "see the build_filter method for filtering array type filters.")
        if is_list_like(filter_value) and is_dynamic_sized_type(_input['type']):
            raise TypeError(
                "createFilter no longer supports setting filter argument options for dynamic sized "
                "types. See the build_filter method for setting filters with the match_any "
                "method.")
Ejemplo n.º 48
0
    def test_eth_newPendingTransactionFilter(self, web3):
        filter = web3.eth.filter('pending')
        assert is_string(filter.filter_id)

        changes = web3.eth.getFilterChanges(filter.filter_id)
        assert is_list_like(changes)
        assert not changes

        # TODO: figure out why this fails in go-ethereum
        # logs = web3.eth.getFilterLogs(filter.filter_id)
        # assert is_list_like(logs)
        # assert not logs

        result = web3.eth.uninstallFilter(filter.filter_id)
        assert result is True
Ejemplo n.º 49
0
def inputPostFormatter(post):
    """
    Formats the input of a whisper post and converts all values to HEX
    """

    post["ttl"] = from_decimal(post["ttl"])
    post["workToProve"] = from_decimal(post.get("workToProve", 0))
    post["priority"] = from_decimal(post["priority"])

    if not is_list_like(post.get("topics")):
        post["topics"] = [post["topics"]] if post.get("topics") else []

    post["topics"] = [topic if is_0x_prefixed(topic) else encode_hex(topic)
                      for topic in post["topics"]]

    return post
Ejemplo n.º 50
0
def validate_abi(abi):
    """
    Helper function for validating an ABI
    """
    if not is_list_like(abi):
        raise ValueError("'abi' is not a list")

    if not all(is_dict(e) for e in abi):
        raise ValueError("'abi' is not a list of dictionaries")

    functions = filter_by_type('function', abi)
    selectors = groupby(
        compose(encode_hex, function_abi_to_4byte_selector),
        functions
    )
    duplicates = valfilter(lambda funcs: len(funcs) > 1, selectors)
    if duplicates:
        raise ValueError(
            'Abi contains functions with colliding selectors. '
            'Functions {0}'.format(_prepare_selector_collision_msg(duplicates))
        )
Ejemplo n.º 51
0
def construct_event_data_set(event_abi, arguments=None):
    if arguments is None:
        arguments = {}
    if isinstance(arguments, (list, tuple)):
        if len(arguments) != len(event_abi['inputs']):
            raise ValueError(
                "When passing an argument list, the number of arguments must "
                "match the event constructor."
            )
        arguments = {
            arg['name']: [arg_value]
            for arg, arg_value
            in zip(event_abi['inputs'], arguments)
        }

    normalized_args = {
        key: value if is_list_like(value) else [value]
        for key, value in arguments.items()
    }

    non_indexed_args = exclude_indexed_event_inputs(event_abi)
    zipped_abi_and_args = [
        (arg, normalized_args.get(arg['name'], [None]))
        for arg in non_indexed_args
    ]
    encoded_args = [
        [
            None if option is None else encode_hex(encode_single(arg['type'], option))
            for option in arg_options]
        for arg, arg_options in zipped_abi_and_args
    ]

    topics = [
        list(permutation)
        if any(value is not None for value in permutation)
        else []
        for permutation in itertools.product(*encoded_args)
    ]
    return topics
Ejemplo n.º 52
0
    def validate_value(self, value):
        if not is_list_like(value):
            self.invalidate_value(
                value,
                msg="must be list-like object such as array or tuple",
            )

        if len(value) != len(self.encoders):
            self.invalidate_value(
                value,
                exc=ValueOutOfBounds,
                msg="value has {} items when {} were expected".format(
                    len(value),
                    len(self.encoders),
                ),
            )

        for item, encoder in zip(value, self.encoders):
            try:
                encoder.validate_value(item)
            except AttributeError:
                encoder(item)
Ejemplo n.º 53
0
 def providers(self, value):
     if not is_list_like(value):
         providers = [value]
     else:
         providers = value
     self._providers = providers
Ejemplo n.º 54
0
    def __init__(self,
                 *args,
                 **kwargs):
        """Create a new smart contract proxy object.

        :param address: Contract address as 0x hex string
        """
        code = kwargs.pop('code', empty)
        code_runtime = kwargs.pop('code_runtime', empty)
        source = kwargs.pop('source', empty)
        abi = kwargs.pop('abi', empty)
        address = kwargs.pop('address', empty)

        if self.web3 is None:
            raise AttributeError(
                'The `Contract` class has not been initialized.  Please use the '
                '`web3.contract` interface to create your contract class.'
            )

        arg_0, arg_1, arg_2, arg_3, arg_4 = tuple(itertools.chain(
            args,
            itertools.repeat(empty, 5),
        ))[:5]

        if is_list_like(arg_0):
            if abi:
                raise TypeError("The 'abi' argument was found twice")
            abi = arg_0
        elif is_address(arg_0):
            if address:
                raise TypeError("The 'address' argument was found twice")
            address = arg_0

        if is_address(arg_1):
            if address:
                raise TypeError("The 'address' argument was found twice")
            address = arg_1

        if arg_2 is not empty:
            if code:
                raise TypeError("The 'code' argument was found twice")
            code = arg_2

        if arg_3 is not empty:
            if code_runtime:
                raise TypeError("The 'code_runtime' argument was found twice")
            code_runtime = arg_3

        if arg_4 is not empty:
            if source:
                raise TypeError("The 'source' argument was found twice")
            source = arg_4

        if any((abi, code, code_runtime, source)):
            warnings.warn(DeprecationWarning(
                "The arguments abi, code, code_runtime, and source have been "
                "deprecated and will be removed from the Contract class "
                "constructor in future releases.  Update your code to use the "
                "Contract.factory method."
            ))

        if abi is not empty:
            self.abi = abi
        if code is not empty:
            self.bytecode = code
        if code_runtime is not empty:
            self.bytecode_runtime = code_runtime
        if source is not empty:
            self._source = source

        if address is not empty:
            self.address = address
        else:
            warnings.warn(DeprecationWarning(
                "The address argument is now required for contract class "
                "instantiation.  Please update your code to reflect this change"
            ))
Ejemplo n.º 55
0
def is_array_of_dicts(value):
    if not is_list_like(value):
        return False
    return all((is_dict(item) for item in value))
Ejemplo n.º 56
0
def upgrade_v4_to_v5(v4_config):
    """
    Upgrade a v4 config file to a v5 config file.
    """
    errors = get_validation_errors(v4_config, version=V4)
    if errors:
        raise ValueError(
            "Cannot upgrade invalid config.  Please ensure that your current "
            "configuration file is valid:\n\n{0}".format(
                format_errors(errors),
            )
        )

    v4_default_config = load_default_config(version=V4)
    v5_default_config = load_default_config(version=V5)

    if v4_config == v4_default_config:
        return v5_default_config

    upgraded_v4_config = copy.deepcopy(v4_config)

    # new configuration values whos keys were not present in the previous
    # configuration.
    for key_path in NEW_V5_PATHS:
        if has_nested_key(upgraded_v4_config, key_path):
            continue
        set_nested_key(
            upgraded_v4_config,
            key_path,
            get_nested_key(v5_default_config, key_path),
        )

    # keys in the new configuration that were relocated.
    for old_path, new_path in MOVED_V4_PATHS.items():
        default_value = get_nested_key(v5_default_config, new_path)

        if has_nested_key(upgraded_v4_config, old_path):
            existing_value = pop_nested_key(upgraded_v4_config, old_path)

            if is_dict(default_value) and is_dict(existing_value):
                merged_value = deep_merge_dicts(default_value, existing_value)
            elif is_list_like(default_value) and is_list_like(existing_value):
                merged_value = list(set(itertools.chain(default_value, existing_value)))
            else:
                raise ValueError(
                    "Unable to merge {0} with {1}".format(
                        type(default_value),
                        type(existing_value),
                    )
                )

            set_nested_key(
                upgraded_v4_config,
                new_path,
                merged_value,
            )
        else:
            set_nested_key(
                upgraded_v4_config,
                new_path,
                default_value,
            )

    # keys from the previous configuration that were changed.
    for key_path in MODIFIED_V4_PATHS:
        new_default = get_nested_key(v5_default_config, key_path)
        if key_path not in upgraded_v4_config:
            set_nested_key(
                upgraded_v4_config,
                key_path,
                new_default,
            )
        else:
            current_value = get_nested_key(upgraded_v4_config, key_path)
            old_default = get_nested_key(v4_default_config, key_path)
            if current_value == old_default:
                set_nested_key(
                    upgraded_v4_config,
                    key_path,
                    new_default,
                )

    # bump the version
    set_nested_key(upgraded_v4_config, 'version', V5)

    errors = get_validation_errors(upgraded_v4_config, version=V5)
    if errors:
        raise ValueError(
            "Upgraded configuration did not pass validation:\n\n"
            "\n=============Original-Configuration============\n"
            "{0}"
            "\n=============Upgraded-Configuration============\n"
            "{1}"
            "\n=============Validation-Errors============\n"
            "{2}".format(
                pprint.pformat(dict(v4_config)),
                pprint.pformat(dict(upgraded_v4_config)),
                format_errors(errors),
            )
        )

    return upgraded_v4_config
Ejemplo n.º 57
0
def upgrade_v3_to_v4(v3_config):
    """
    Upgrade a v3 config file to a v4 config file.
    """
    errors = get_validation_errors(v3_config, version=V3)
    if errors:
        raise ValueError(
            "Cannot upgrade invalid config.  Please ensure that your current "
            "configuration file is valid:\n\n{0}".format(
                format_errors(errors),
            )
        )

    v3_default_config = load_default_config(version=V3)
    v4_default_config = load_default_config(version=V4)

    if v3_config == v3_default_config:
        return v4_default_config

    upgraded_v3_config = copy.deepcopy(v3_config)

    for key_path in NEW_V4_PATHS:
        if has_nested_key(upgraded_v3_config, key_path):
            continue
        set_nested_key(
            upgraded_v3_config,
            key_path,
            get_nested_key(v4_default_config, key_path),
        )

    for old_path, new_path in MOVED_V3_PATHS.items():
        default_value = get_nested_key(v4_default_config, new_path)

        if has_nested_key(upgraded_v3_config, old_path):
            existing_value = pop_nested_key(upgraded_v3_config, old_path)

            if is_dict(default_value) and is_dict(existing_value):
                merged_value = deep_merge_dicts(default_value, existing_value)
            elif is_list_like(default_value) and is_list_like(existing_value):
                merged_value = list(set(itertools.chain(default_value, existing_value)))
            else:
                raise ValueError(
                    "Unable to merge {0} with {1}".format(
                        type(default_value),
                        type(existing_value),
                    )
                )

            set_nested_key(
                upgraded_v3_config,
                new_path,
                merged_value,
            )
        else:
            set_nested_key(
                upgraded_v3_config,
                new_path,
                default_value,
            )

    # bump the version
    set_nested_key(upgraded_v3_config, 'version', V4)

    errors = get_validation_errors(upgraded_v3_config, version=V4)
    if errors:
        raise ValueError(
            "Upgraded configuration did not pass validation:\n\n"
            "\n=============Original-Configuration============\n"
            "{0}"
            "\n=============Upgraded-Configuration============\n"
            "{1}"
            "\n=============Validation-Errors============\n"
            "{2}".format(
                pprint.pformat(dict(v3_config)),
                pprint.pformat(dict(upgraded_v3_config)),
                format_errors(errors),
            )
        )

    return upgraded_v3_config
Ejemplo n.º 58
0
def is_array_of_strings(value):
    if not is_list_like(value):
        return False
    return all((is_string(item) for item in value))
Ejemplo n.º 59
0
def pop_singlets(seq):
    yield from (i[0] if is_list_like(i) and len(i) == 1 else i for i in seq)