Пример #1
0
def validate_filter_params(from_block, to_block, address, topics):
    # blocks
    if from_block is not None:
        validate_block_number(from_block)
    if to_block is not None:
        validate_block_number(to_block)

    # address
    if address is None:
        pass
    elif is_list_like(address):
        if not address:
            raise ValidationError(
                "Address must be either a single hexidecimal encoded address or "
                "a non-empty list of hexidecimal encoded addresses")
        for sub_address in address:
            validate_account(sub_address)
    elif not is_hex_address(address):
        validate_account(address)

    invalid_topics_message = (
        "Topics must be one of `None`, an array of 32 byte hexidecimal encoded "
        "strings, or an array of arrays of 32 byte hexidecimal strings")
    # topics
    if topics is None:
        pass
    elif not is_list_like(topics):
        raise ValidationError(invalid_topics_message)
    elif is_valid_topic_array(topics):
        return True
    else:
        raise ValidationError(invalid_topics_message)
Пример #2
0
def validate_positive_integer(value):
    error_message = "Value must be positive integers.  Got: {0}".format(
        value, )
    if not is_integer(value) or is_boolean(value):
        raise ValidationError(error_message)
    elif value < 0:
        raise ValidationError(error_message)
Пример #3
0
    def lock_account(self, account):
        self.validator.validate_inbound_account(account)
        raw_account = self.normalizer.normalize_inbound_account(account)

        if raw_account not in self._account_passwords:
            raise ValidationError("Unknown account")
        elif self._account_passwords[raw_account] is None:
            raise ValidationError("Account does not have a password")

        self._account_unlock[raw_account] = False
Пример #4
0
def validate_account(value):
    if not is_text(value):
        raise ValidationError(
            "Address must be 20 bytes encoded as hexidecimal")
    elif not is_hex_address(value):
        raise ValidationError(
            "Address must be 20 bytes encoded as hexidecimal")
    elif is_checksum_formatted_address(
            value) and not is_checksum_address(value):
        raise ValidationError("Address does not validate EIP55 checksum")
Пример #5
0
def validate_block_number(value):
    error_message = (
        "Block number must be a positive integer or one of the strings "
        "'latest', 'earliest', or 'pending'.  Got: {0}".format(value))
    if is_string(value):
        validate_text(value)
        if value not in BLOCK_NUMBER_META_VALUES:
            raise ValidationError(error_message)
    elif not is_integer(value) or is_boolean(value):
        raise ValidationError(error_message)
    elif value < 0:
        raise ValidationError(error_message)
Пример #6
0
def validate_uint(max_val, value):
    validate_positive_integer(value)
    if value > max_val:
        bitsize = int(math.log2(max_val))
        raise ValidationError(
            "Value exceeds maximum {:d} bit integer size:  {}".format(
                bitsize, value))
Пример #7
0
def validate_no_extra_keys(value, allowed_keys):
    extra_keys = tuple(sorted(set(value.keys()).difference(allowed_keys)))
    if extra_keys:
        raise ValidationError(
            "Only the keys '{0}' are allowed.  Got extra keys: '{1}'".format(
                "/".join(tuple(sorted(allowed_keys))),
                "/".join(extra_keys),
            ))
Пример #8
0
def validate_any(value, validators):
    errors = _accumulate_errors(value, validators)
    if len(errors) == len(validators):
        item_error_messages = tuple(" - [{0}]: {1}".format(idx, str(err))
                                    for idx, err in errors)
        error_message = ("Value did not pass any of the provided validators:\n"
                         "{0}".format("\n".join(item_error_messages)))
        raise ValidationError(error_message)
Пример #9
0
def validate_has_required_keys(value, required_keys):
    missing_keys = tuple(sorted(set(required_keys).difference(value.keys())))
    if missing_keys:
        raise ValidationError(
            "Blocks must contain all of the keys '{0}'.  Missing the keys: '{1}'"
            .format(
                "/".join(tuple(sorted(required_keys))),
                "/".join(missing_keys),
            ))
Пример #10
0
def validate_timestamp(value):
    validate_positive_integer(value)

    if value >= MAX_TIMESTAMP:
        raise ValidationError(
            "Timestamp values must be less than {0}.  Got {1}".format(
                MAX_TIMESTAMP,
                value,
            ))
Пример #11
0
def validate_array(value, validator):
    validate_is_list_like(value)

    item_errors = _accumulate_array_errors(value, validator)
    if item_errors:
        item_messages = tuple("[{0}]: {1}".format(index, str(err))
                              for index, err in sorted(item_errors))
        error_message = ("The following items failed to validate\n"
                         "- {0}".format("\n - ".join(item_messages)))
        raise ValidationError(error_message)
Пример #12
0
    def unlock_account(self, account, password, unlock_seconds=None):
        self.validator.validate_inbound_account(account)
        raw_account = self.normalizer.normalize_inbound_account(account)
        try:
            account_password = self._account_passwords[raw_account]
        except KeyError:
            raise ValidationError("Unknown account")

        if account_password is None:
            raise ValidationError("Account does not have a password")

        if account_password != password:
            raise ValidationError("Wrong password")

        if unlock_seconds is None:
            unlock_until = None
        else:
            unlock_until = time.time() + unlock_seconds

        self._account_unlock[raw_account] = unlock_until
Пример #13
0
def validate_dict(value, key_validators):
    validate_is_dict(value)
    validate_no_extra_keys(value, key_validators.keys())
    validate_has_required_keys(value, key_validators.keys())

    key_errors = _accumulate_dict_errors(value, key_validators)
    if key_errors:
        key_messages = tuple("{0}: {1}".format(key, str(err))
                             for key, err in sorted(key_errors.items()))
        error_message = ("The following keys failed to validate\n"
                         "- {0}".format("\n - ".join(key_messages)))
        raise ValidationError(error_message)
Пример #14
0
 def time_travel(self, to_timestamp):
     self.validator.validate_inbound_timestamp(to_timestamp)
     # make sure we are not traveling back in time as this is not possible.
     current_timestamp = self.get_block_by_number('pending')['timestamp']
     if to_timestamp == current_timestamp:
         # no change, return immediately
         return
     elif to_timestamp < current_timestamp:
         raise ValidationError(
             "Space time continuum distortion detected.  Traveling backwards "
             "in time violates interdimensional ordinance 31415-926.")
     else:
         self.backend.time_travel(to_timestamp)
Пример #15
0
    def get_transaction_receipt(self, transaction_hash):
        self.validator.validate_inbound_transaction_hash(transaction_hash)
        raw_transaction_hash = self.normalizer.normalize_inbound_transaction_hash(
            transaction_hash, )
        raw_receipt = self.backend.get_transaction_receipt(
            raw_transaction_hash)
        self.validator.validate_outbound_receipt(raw_receipt)
        receipt = self.normalizer.normalize_outbound_receipt(raw_receipt)

        # Assume backend supports Byzantium
        status = to_int(receipt.pop('state_root'))
        if status > 1:
            raise ValidationError(
                'Invalid status value: only 0 or 1 are valid')
        return assoc(receipt, 'status', status)
Пример #16
0
    def add_account(self, private_key, password=None):
        # TODO: validation
        self.validator.validate_inbound_private_key(private_key)
        raw_private_key = self.normalizer.normalize_inbound_private_key(
            private_key)
        raw_account = private_key_to_address(raw_private_key)
        account = self.normalizer.normalize_outbound_account(raw_account)
        if any((is_same_address(account, value)
                for value in self.get_accounts())):
            raise ValidationError("Account already present in account list")

        self.backend.add_account(raw_private_key)
        self._account_passwords[raw_account] = password
        # TODO: outbound normalization
        return account
Пример #17
0
    def mine_blocks(self, num_blocks=1, coinbase=None):
        if coinbase is None:
            raw_coinbase = None
        else:
            self.validator.validate_inbound_account(coinbase)
            raw_coinbase = self.normalizer.normalize_inbound_account(coinbase)

        if not self.auto_mine_transactions:
            self._pop_pending_transactions_to_pending_block()

        raw_block_hashes = self.backend.mine_blocks(num_blocks, raw_coinbase)

        if len(raw_block_hashes) != num_blocks:
            raise ValidationError(
                "Invariant: tried to mine {0} blocks.  Got {1} mined block hashes."
                .format(
                    num_blocks,
                    len(raw_block_hashes),
                ))

        for raw_block_hash in raw_block_hashes:
            self.validator.validate_outbound_block_hash(raw_block_hash)
        block_hashes = [
            self.normalizer.normalize_outbound_block_hash(raw_block_hash)
            for raw_block_hash in raw_block_hashes
        ]

        # feed the block hashes to any block filters
        for block_hash in block_hashes:
            block = self.get_block_by_hash(block_hash)

            for _, block_filter in self._block_filters.items():
                raw_block_hash = self.normalizer.normalize_inbound_block_hash(
                    block_hash)
                block_filter.add(raw_block_hash)

            self._process_block_logs(block)

        return block_hashes
Пример #18
0
def validate_is_dict(value):
    if not is_dict(value):
        raise ValidationError("Value must be a dictionary.  Got: {0}".format(
            type(value)))
Пример #19
0
def validate_32_byte_hex_value(value, name):
    error_message = ("{0} must be a hexidecimal encoded 32 byte string.  Got: "
                     "{1}".format(name, value))
    if not is_32byte_hex_string(value):
        raise ValidationError(error_message)
Пример #20
0
def validate_raw_transaction(raw_transaction):
    if not is_text(raw_transaction) or not is_hex(raw_transaction):
        raise ValidationError(
            "Raw Transaction must be a hexidecimal encoded string.  Got: "
            "{0}".format(raw_transaction))
Пример #21
0
def validate_transaction(value, txn_type):
    if txn_type not in ALLOWED_TRANSACTION_TYPES:
        raise TypeError(
            "the `txn_type` parameter must be one of send/call/estimate")
    if not is_dict(value):
        raise ValidationError(
            "Transaction must be a dictionary.  Got: {0}".format(type(value)))

    unknown_keys = tuple(
        sorted(
            set(value.keys()).difference(TRANSACTION_TYPE_INFO[txn_type], )))
    if unknown_keys:
        raise ValidationError(
            "Only the keys '{0}' are allowed.  Got extra keys: '{1}'".format(
                "/".join(tuple(sorted(TRANSACTION_TYPE_INFO[txn_type]))),
                "/".join(unknown_keys),
            ))

    if txn_type == 'send':
        required_keys = {'from', 'gas'}
    elif txn_type == 'send_signed':
        required_keys = {'from', 'gas'} | SIGNED_TRANSACTION_KEYS
    elif txn_type in {'estimate', 'call'}:
        required_keys = set(['from'])
    else:
        raise Exception("Invariant: code path should be unreachable")

    missing_required_keys = tuple(
        sorted(required_keys.difference(value.keys())))
    if missing_required_keys:
        raise ValidationError(
            "Transaction is missing the required keys: '{0}'".format(
                "/".join(missing_required_keys), ))

    if 'from' in value:
        validate_account(value['from'])

    if 'to' in value and value['to'] != '':
        validate_account(value['to'])
    elif 'to' in value and value['to'] == '':
        validate_text(value['to'])

    if 'gas' in value:
        validate_uint256(value['gas'])

    if 'gas_price' in value:
        validate_uint256(value['gas_price'])

    if 'value' in value:
        validate_uint256(value['value'])

    if 'nonce' in value:
        validate_uint256(value['nonce'])

    if 'data' in value:
        bad_data_message = (
            "Transaction data must be a hexidecimal encoded string.  Got: "
            "{0}".format(value['data']))
        if not is_text(value['data']):
            raise ValidationError(bad_data_message)
        elif not remove_0x_prefix(value['data']):
            pass
        elif not is_hex(value['data']):
            raise ValidationError(bad_data_message)
        try:
            decode_hex(value['data'])
        except (binascii.Error, TypeError):
            # TypeError is for python2
            # binascii.Error is for python3
            raise ValidationError(bad_data_message)

    if txn_type == 'send_signed':
        validate_uint256(value['r'])
        validate_uint256(value['s'])
        validate_uint8(value['v'])
Пример #22
0
def validate_private_key(value):
    if not is_text(value) or not is_hex(value) or not len(
            remove_0x_prefix(value)) == 64:
        raise ValidationError(
            "Private keys must be 32 bytes encoded as hexidecimal")
Пример #23
0
def validate_text(value):
    if not is_text(value):
        raise ValidationError(
            "Value must be a text string.  Got type: {0}".format(type(value)))
Пример #24
0
def validate_32_byte_string(value):
    validate_bytes(value)
    if len(value) != 32:
        raise ValidationError(
            "Must be of length 32.  Got: {0} of length {1}".format(value, len(value))
        )
Пример #25
0
def validate_nonce(value):
    validate_bytes(value)
    if len(value) != 8:
        raise ValidationError(
            "Must be of length 8.  Got: {0} of lenght {1}".format(value, len(value))
        )
Пример #26
0
def validate_log_entry_type(value):
    if value not in {"pending", "mined"}:
        raise ValidationError("Log entry type must be one of 'pending' or 'mined'")
Пример #27
0
def validate_canonical_address(value):
    validate_bytes(value)
    if not is_canonical_address(value):
        raise ValidationError("Value must be a 20 byte string")
Пример #28
0
def validate_logs_bloom(value):
    validate_positive_integer(value)
    if value > UINT2048_MAX:
        raise ValidationError("Value exceeds 2048 bit integer size: {0}".format(value))
Пример #29
0
def validate_signature_v(value):
    validate_positive_integer(value)

    if value not in [0, 1, 27, 28] and value not in range(35, UINT256_MAX + 1):
        raise ValidationError("The `v` portion of the signature must be 0, 1, 27, 28 or >= 35")
Пример #30
0
def validate_is_list_like(value):
    if not is_list_like(value):
        raise ValidationError(
            "Value must be a sequence type.  Got: {0}".format(type(value)))