Beispiel #1
0
    def encode_param_array(self, args, param_entity):
        if len(args) == 0:
            raise Exception('Empty arrays not allowed.')

        first_arg_type = type(args[0])
        for arg in args:
            if type(arg) != first_arg_type:
                raise Exception('Array arguments are not of same type.')

        resolved_type = utils.resolve_type(param_entity['type'], self.aliases)
        elem_type, array_sizes = utils.factorize_array_type_str(resolved_type)

        if not utils.check_array(args, elem_type, array_sizes):
            raise Exception('Array check failed for "{}".'.format(
                param_entity['type']))

        res_buff = []
        for arg in utils.flatten_array(args, param_entity['name'],
                                       resolved_type):
            res_buff.append(
                self.encode_param(arg['value'], {
                    'name': arg['name'],
                    'type': arg['type']
                }))
        return ''.join(res_buff)
Beispiel #2
0
def build_type_classes(desc):
    # TODO: Type class constructors shold accept primitive types like ints and bytes where applicable.
    #       They also should accept lists.
    struct_classes = build_struct_classes(desc)

    alias_classes = dict()
    aliases = desc['alias'] if 'alias' in desc else []
    final_type_resolver = build_type_resolver(aliases)

    for alias in aliases:
        alias_name = alias['name']
        final_type = final_type_resolver(alias_name)
        if utils.is_struct_type(final_type):
            struct_name = utils.get_struct_name_by_type(final_type)
            def constructor(self, struct_obj):
                # TODO: Solve recursion problem with calling super constructor.
                #       For now value is set manualy.
                #super(self.__class__, self).__init__(struct_obj)
                assert isinstance(struct_obj, dict)
                self.value = struct_obj
                self.type_str = alias_name
                self._type_resolver = final_type_resolver
                self.bind()
            alias_class_atribs = dict()
            alias_class_atribs['__init__'] = constructor
            alias_classes[alias_name] = type(alias_name, (struct_classes[struct_name],), alias_class_atribs)
        elif utils.is_array_type(final_type):
            elem_type_name, _ = utils.factorize_array_type_str(final_type)
            if elem_type_name in types.BASIC_SCRYPT_TYPES:
                alias_classes[alias_name] = list()
            elif utils.is_struct_type(elem_type_name):
                struct_name = utils.get_struct_name_by_type(elem_type_name)
                alias_classes[alias_name] = list()
        else:
            if final_type in types.BASIC_SCRYPT_TYPES:
                def constructor(self, struct_obj):
                    # TODO: Solve recursion problem with calling super constructor.
                    #       For now value is set manualy.
                    #super(self.__class__, self).__init__(struct_obj)
                    assert isinstance(struct_obj, dict)
                    self.value = struct_obj
                    self.type_str = alias_name
                    self._type_resolver = final_type_resolver
                    self.bind()
                alias_class_atribs = dict()
                alias_class_atribs['__init__'] = constructor
                alias_classes[alias_name] = type(alias_name, (types.BASIC_SCRYPT_TYPES[final_type],), alias_class_atribs)
            else:
                raise Exception('Could not resolve alias "{}" for type "{}".'.format(alias_name, alias['type']))

    return {**alias_classes, **struct_classes}
Beispiel #3
0
 def resolver_func(alias):
     if utils.is_struct_type(alias):
         alias = utils.get_struct_name_by_type(alias)
     array_type = ''
     if utils.is_array_type(alias):
         elem_type_name, sizes = utils.factorize_array_type_str(alias)
         if utils.is_struct_type(elem_type_name):
             alias = utils.get_struct_name_by_type(elem_type_name)
         else:
             alias = elem_type_name
         array_type_buff = []
         for size in sizes:
             array_type_buff.append('[{}]'.format(size))
         array_type = ''.join(array_type_buff)
     if alias in types.BASIC_SCRYPT_TYPES:
         return '{}{}'.format(alias, array_type)
     if alias in resolved_types:
         return '{}{}'.format(resolved_types[alias], array_type)
     return 'struct {} {{}}{}'.format(alias, array_type)
    def resolve_array_type_w_const_int(contract_name, type_str,
                                       static_int_consts):
        # Resolves array declaration string with static constants as sizes.
        # e.g. 'int[N][2]' -> 'int[5][2]'
        elem_type_name, array_sizes = utils.factorize_array_type_str(type_str)

        # Resolve all constants to integers.
        sizes = []
        for size_str in array_sizes:
            if size_str.isdigit():
                sizes.append(int(size_str))
            else:
                if size_str.find('.') > 0:
                    sizes.append(static_int_consts[size_str])
                else:
                    sizes.append(static_int_consts['{}.{}'.format(
                        contract_name, size_str)])

        return utils.to_literal_array_type(elem_type_name, sizes)
    def resolve_abi_param_type(contract_name, type_str, aliases,
                               static_int_consts):
        if utils.is_array_type(type_str):
            resolved_type = CompilerWrapper.resolve_array_type_w_const_int(
                contract_name, type_str, static_int_consts)
        else:
            resolved_type = utils.resolve_type(type_str, aliases)

        if utils.is_struct_type(resolved_type):
            return utils.get_struct_name_by_type(resolved_type)
        elif utils.is_array_type(resolved_type):
            elem_type_name, array_sizes = utils.factorize_array_type_str(
                resolved_type)

            if utils.is_struct_type(elem_type_name):
                elem_type_name = utils.get_struct_name_by_type(resolved_type)

            return utils.to_literal_array_type(elem_type_name, array_sizes)

        return resolved_type
Beispiel #6
0
    def get_ls_code_part(self, contract, hex_script, *args):
        abi_constructor = self.abi_constructor()
        c_params = abi_constructor.get('params', [])

        if len(args) != len(c_params):
            raise Exception('Wrong number of arguments passed to constructor. ' \
                    'Expected {}, but got {}.'.format(len(c_params), len(args)))

        _c_params = []
        _args = []
        for idx, param in enumerate(c_params):
            arg = args[idx]
            arg = utils.primitives_to_scrypt_types(arg)
            resolved_type = utils.resolve_type(param['type'], self.aliases)
            is_param_statefull = param['state']
            if utils.is_array_type(resolved_type):
                elem_type, array_sizes = utils.factorize_array_type_str(
                    resolved_type)

                if not utils.check_array(arg, elem_type, array_sizes):
                    raise Exception(
                        'Constructors parameter with index {} should be array of type "{}".'
                        .format(idx, resolved_type))
                flattened_arr = utils.flatten_array(arg, param['name'],
                                                    resolved_type)
                for obj in flattened_arr:
                    _c_params.append({
                        'name': obj['name'],
                        'type': obj['type'],
                        'state': is_param_statefull
                    })
                    _args.append(obj['value'])
            elif utils.is_struct_type(resolved_type):
                if arg.final_type != resolved_type:
                    raise Exception('Constructors parameter with index {} should be struct of type "{}". ' \
                            'Got struct of type "{}" instead.'.format(idx, param['type'], arg.type_str))

                flattened_struct = utils.flatten_struct(arg, param['name'])
                for obj in flattened_struct:
                    _c_params.append({
                        'name': obj['name'],
                        'type': obj['type'],
                        'state': is_param_statefull
                    })
                    _args.append(obj['value'])
            else:
                _c_params.append(param)
                _args.append(arg)

            if is_param_statefull:
                # If a statefull variable, set the passed value as a member of the contract object.
                setattr(contract, param['name'], arg)

        finalized_hex_script = hex_script
        for idx, param in enumerate(_c_params):
            if not '<{}>'.format(param['name']) in hex_script:
                raise Exception(
                    'Missing "{}" contract constructor parameter in passed args.'
                    .format(param['name']))
            param_regex = re.compile(
                escape_str_for_regex('<{}>'.format(param['name'])))
            if param['state']:
                # State variables need only a placeholder value as they will get replaced during script execution.
                #finalized_hex_script = re.sub(param_regex, '0100', finalized_hex_script)
                finalized_hex_script = re.sub(
                    param_regex, self.encode_param(_args[idx], param),
                    finalized_hex_script)
            else:
                finalized_hex_script = re.sub(
                    param_regex, self.encode_param(_args[idx], param),
                    finalized_hex_script)

        finalized_hex_script = re.sub('<__codePart__>', '00',
                                      finalized_hex_script)

        # Replace inline assembly variable placeholders in locking script with the actual arguments.
        # TODO: Check if each value is instance of ScryptType
        if contract.inline_asm_vars:
            for key, val in contract.inline_asm_vars.items():
                param_regex = re.compile(
                    escape_str_for_regex('<{}>'.format(key)))
                finalized_hex_script = re.sub(param_regex, val.hex,
                                              finalized_hex_script)

        return Script.from_hex(finalized_hex_script)
Beispiel #7
0
    def get_ls_data_part(self,
                         contract,
                         custom_vals_dict=None,
                         first_call=None):
        abi_constructor = self.abi_constructor()
        c_params = abi_constructor.get('params', [])

        state_buff = []

        first_call = first_call if first_call is not None else contract.first_call
        if first_call:
            state_buff.append('01')
        else:
            state_buff.append('00')

        for param in c_params:
            if not param['state']:
                continue

            param_name = param['name']
            resolved_type = utils.resolve_type(param['type'], self.aliases)

            if custom_vals_dict:
                val = custom_vals_dict[param_name]
            else:
                val = getattr(contract, param_name, None)
                if not val:
                    raise Exception(
                        'Statefull variable "{}" has no value.'.format(
                            param_name))

            val = utils.primitives_to_scrypt_types(val)

            # Do type checking.
            if utils.is_array_type(resolved_type):
                elem_type, array_sizes = utils.factorize_array_type_str(
                    resolved_type)
                if not utils.check_array(val, elem_type, array_sizes):
                    raise Exception(
                        'Statefull variable "{}" should be array of type "{}".'
                        .format(param_name, resolved_type))
            elif utils.is_struct_type(resolved_type):
                if val.final_type != resolved_type:
                    raise Exception('Statefull variable "{}" should be struct of type "{}". ' \
                            'Got struct of type "{}" instead.'.format(param_name, param['type'], val.type_str))
            else:
                if val.final_type != resolved_type:
                    raise Exception('Statefull variable "{}" should be of type "{}". ' \
                            'Got object of type "{}" instead.'.format(param_name, param['type'], val.type_str))

            state_buff.append(serializer.serialize(val).hex())

        # State length and state version.
        state_len = 0
        for elem in state_buff:
            state_len += len(elem) // 2
        if state_len > 0:
            size_bytes = state_len.to_bytes(4, 'little')
            state_buff.append(size_bytes.hex())
            state_buff.append(
                CONTRACT_STATE_VERSION.to_bytes(1, 'little').hex())

        return Script.from_hex(''.join(state_buff))