Пример #1
0
def produce_source_map(code, interface_codes=None):
    global_ctx = GlobalContext.get_global_context(
        parser.parse_to_ast(code), interface_codes=interface_codes)
    asm_list = compile_lll.compile_to_assembly(
        optimizer.optimize(
            parse_to_lll(code,
                         runtime_only=True,
                         interface_codes=interface_codes)))
    c, line_number_map = compile_lll.assembly_to_evm(asm_list)
    source_map = {
        "globals": {},
        "locals": {},
        "line_number_map": line_number_map
    }
    source_map["globals"] = {
        name: serialise_var_rec(var_record)
        for name, var_record in global_ctx._globals.items()
    }
    # Fetch context for each function.
    lll = parser.parse_tree_to_lll(
        parser.parse_to_ast(code),
        code,
        interface_codes=interface_codes,
        runtime_only=True,
    )
    contexts = {
        f.func_name: f.context
        for f in lll.args[1:] if hasattr(f, "context")
    }

    prev_func_name = None
    for _def in global_ctx._defs:
        if _def.name != "__init__":
            func_info = {"from_lineno": _def.lineno, "variables": {}}
            # set local variables for specific function.
            context = contexts[_def.name]
            func_info["variables"] = {
                var_name: serialise_var_rec(var_rec)
                for var_name, var_rec in context.vars.items()
            }

            source_map["locals"][_def.name] = func_info
            # set to_lineno
            if prev_func_name:
                source_map["locals"][prev_func_name]["to_lineno"] = _def.lineno
            prev_func_name = _def.name

    source_map["locals"][_def.name]["to_lineno"] = len(code.splitlines())

    return source_map
Пример #2
0
def __compile(code, interface_codes=None, *args, **kwargs):
    ast = parser.parse_to_ast(code)
    lll = parser.parse_tree_to_lll(ast,
                                   code,
                                   interface_codes=interface_codes,
                                   runtime_only=kwargs.get(
                                       'bytecode_runtime', False))
    opt_lll = optimizer.optimize(lll)
    asm = compile_lll.compile_to_assembly(opt_lll)

    def find_nested_opcode(asm_list, key):
        if key in asm_list:
            return True
        else:
            sublists = [sub for sub in asm_list if isinstance(sub, list)]
            return any(find_nested_opcode(x, key) for x in sublists)

    if find_nested_opcode(asm, 'DEBUG'):
        print('Please note this code contains DEBUG opcode.')
        print(
            'This will only work in a support EVM. This FAIL on any other nodes.'
        )

    c, line_number_map = compile_lll.assembly_to_evm(asm)
    return c
Пример #3
0
def test_basic_grammar(lark_grammar):
    code = """
    a: uint256
    b: uint128
    """
    code_func = """
    @public
    def one_two_three() -> uint256:
        return 123123123
    """

    assert lark_grammar.parse(textwrap.dedent(code) + "\n")
    assert parser.parse_to_ast(textwrap.dedent(code))

    assert lark_grammar.parse(textwrap.dedent(code_func) + "\n")
    assert parser.parse_to_ast(textwrap.dedent(code_func))
Пример #4
0
def extract_interface_str(code, contract_name, interface_codes=None):
    sigs = sig_utils.mk_full_signature(
        parser.parse_to_ast(code),
        sig_formatter=lambda x, y: (x, y),
        interface_codes=interface_codes,
    )
    events = [sig for sig, _ in sigs if isinstance(sig, EventSignature)]
    functions = [sig for sig, _ in sigs if isinstance(sig, FunctionSignature)]
    out = ""
    # Print events.
    for idx, event in enumerate(events):
        if idx == 0:
            out += "# Events\n\n"
        event_args_str = ', '.join([arg.name + ': ' + str(arg.typ) for arg in event.args])
        out += f"{event.name}: event({{{event_args_str}}})\n"

    # Print functions.
    def render_decorator(sig):
        o = "\n"
        if sig.const:
            o += "@constant\n"
        if not sig.private:
            o += "@public\n"
        return o

    for idx, func in enumerate(functions):
        if idx == 0:
            out += "\n# Functions\n"
        if not func.private and func.name != '__init__':
            args = ", ".join([arg.name + ": " + str(arg.typ) for arg in func.args])
            out += f"{render_decorator(func)}def {func.name}({args}){render_return(func)}:\n    pass\n"  # noqa: E501
    out += "\n"

    return out
Пример #5
0
def generate_inline_function(code, variables, memory_allocator):
    ast_code = parse_to_ast(code)
    new_context = Context(vars=variables,
                          global_ctx=GlobalContext(),
                          memory_allocator=memory_allocator,
                          origcode=code)
    generated_lll = parse_body(ast_code, new_context)
    return new_context, generated_lll
Пример #6
0
def mk_full_signature(code, *args, **kwargs):
    abi = parser.mk_full_signature(parser.parse_to_ast(code), *args, **kwargs)
    # Add gas estimates for each function to ABI
    gas_estimates = gas_estimate(code, *args, **kwargs)
    for idx, func in enumerate(abi):
        func_name = func.get('name', '').split('(')[0]
        # Skip __init__, has no estimate
        if func_name in gas_estimates:
            abi[idx]['gas'] = gas_estimates[func_name]
    return abi
Пример #7
0
def extract_sigs(sig_code):
    if sig_code['type'] == 'vyper':
        return parser.mk_full_signature(parser.parse_to_ast(sig_code['code']),
                                        sig_formatter=lambda x, y: x)
    elif sig_code['type'] == 'json':
        return mk_full_signature_from_json(sig_code['code'])
    else:
        raise Exception(
            ("Unknown interface signature type '{}' supplied. "
             "'vyper' & 'json' are supported").format(sig_code['type']))
Пример #8
0
def produce_source_map(code):
    global_ctx = GlobalContext.get_global_context(parser.parse_to_ast(code))
    asm_list = compile_lll.compile_to_assembly(
        optimizer.optimize(parse_to_lll(code, runtime_only=True)))
    c, line_number_map = compile_lll.assembly_to_evm(asm_list)
    source_map = {
        'globals': {},
        'locals': {},
        'line_number_map': line_number_map
    }
    source_map['globals'] = {
        name: serialise_var_rec(var_record)
        for name, var_record in global_ctx._globals.items()
    }
    # Fetch context for each function.
    lll = parser.parse_tree_to_lll(parser.parse_to_ast(code),
                                   code,
                                   runtime_only=True)
    contexts = {
        f.func_name: f.context
        for f in lll.args[1:] if hasattr(f, 'context')
    }

    prev_func_name = None
    for _def in global_ctx._defs:
        if _def.name != '__init__':
            func_info = {'from_lineno': _def.lineno, 'variables': {}}
            # set local variables for specific function.
            context = contexts[_def.name]
            func_info['variables'] = {
                var_name: serialise_var_rec(var_rec)
                for var_name, var_rec in context.vars.items()
            }

            source_map['locals'][_def.name] = func_info
            # set to_lineno
            if prev_func_name:
                source_map['locals'][prev_func_name]['to_lineno'] = _def.lineno
            prev_func_name = _def.name

    source_map['locals'][_def.name]['to_lineno'] = len(code.splitlines())

    return source_map
Пример #9
0
def extract_file_interface_imports(code):
    ast_tree = parser.parse_to_ast(code)
    imports_dict = {}
    for item in ast_tree:
        if isinstance(item, ast.Import):
            for a_name in item.names:
                if not a_name.asname:
                    raise StructureException('Interface statement requires an accompanying `as` statement.', item)
                if a_name.asname in imports_dict:
                    raise StructureException('Interface with Alias {} already exists'.format(a_name.asname), item)
                imports_dict[a_name.asname] = a_name.name
    return imports_dict
Пример #10
0
def extract_sigs(sig_code):
    if sig_code['type'] == 'vyper':
        interface_ast = parser.parse_to_ast(sig_code['code'])
        return sig_utils.mk_full_signature(
            [i for i in interface_ast if not isinstance(i, (ast.Import, ast.ImportFrom))],
            sig_formatter=lambda x, y: x
        )
    elif sig_code['type'] == 'json':
        return mk_full_signature_from_json(sig_code['code'])
    else:
        raise Exception(
            (f"Unknown interface signature type '{sig_code['type']}' supplied. "
             "'vyper' & 'json' are supported")
        )
Пример #11
0
def extract_sigs(sig_code):
    if sig_code['type'] == 'vyper':
        interface_ast = [
            i for i in parser.parse_to_ast(sig_code['code'])
            if isinstance(i, ast.FunctionDef) or (
                isinstance(i, ast.AnnAssign) and i.target.id != "implements")
        ]
        return sig_utils.mk_full_signature(interface_ast,
                                           sig_formatter=lambda x, y: x)
    elif sig_code['type'] == 'json':
        return mk_full_signature_from_json(sig_code['code'])
    else:
        raise Exception((
            f"Unknown interface signature type '{sig_code['type']}' supplied. "
            "'vyper' & 'json' are supported"))
Пример #12
0
def mk_full_signature(code, *args, **kwargs):
    abi = parser.mk_full_signature(parser.parse_to_ast(code), *args, **kwargs)
    # Add gas estimates for each function to ABI
    gas_estimates = gas_estimate(code, *args, **kwargs)
    for func in abi:
        try:
            func_signature = func['name']
        except KeyError:
            # constructor and fallback functions don't have a name
            continue

        func_name, _, _ = func_signature.partition('(')
        # This check ensures we skip __init__ since it has no estimate
        if func_name in gas_estimates:
            # TODO: mutation
            func['gas'] = gas_estimates[func_name]
    return abi
Пример #13
0
def extract_file_interface_imports(code: SourceCode) -> InterfaceImports:
    ast_tree = parser.parse_to_ast(code)

    imports_dict: InterfaceImports = {}
    for item in ast_tree:
        if isinstance(item, ast.Import):
            for a_name in item.names:  # type: ignore
                if not a_name.asname:
                    raise StructureException(
                        'Interface statement requires an accompanying `as` statement.',
                        item,
                    )
                if a_name.asname in imports_dict:
                    raise StructureException(
                        f'Interface with alias {a_name.asname} already exists',
                        item,
                    )
                imports_dict[a_name.asname] = a_name.name.replace('.', '/')
        elif isinstance(item, ast.ImportFrom):
            for a_name in item.names:  # type: ignore
                if a_name.asname:
                    raise StructureException("From imports cannot use aliases",
                                             item)
            level = item.level  # type: ignore
            module = item.module or ""  # type: ignore
            if not level and module == 'vyper.interfaces':
                continue

            base_path = ""
            if level > 1:
                base_path = "../" * (level - 1)
            elif level == 1:
                base_path = "./"
            base_path = f"{base_path}{module.replace('.','/')}/"

            for a_name in item.names:  # type: ignore
                if a_name.name in imports_dict:
                    raise StructureException(
                        f'Interface with name {a_name.name} already exists',
                        item,
                    )
                imports_dict[a_name.name] = f"{base_path}{a_name.name}"

    return imports_dict
Пример #14
0
def extract_external_interface(code, contract_name):
    sigs = parser.mk_full_signature(parser.parse_to_ast(code), sig_formatter=lambda x, y: (x, y))
    functions = [sig for sig, _ in sigs if isinstance(sig, FunctionSignature)]
    cname = os.path.basename(contract_name).split('.')[0].capitalize()

    out = ""
    offset = 4 * " "
    for idx, func in enumerate(functions):
        if idx == 0:
            out += "\n# External Contracts\ncontract %s:\n" % cname
        if not func.private and func.name != '__init__':
            out += offset + "def {name}({args}){ret}: {func_type}\n".format(
                name=func.name,
                args=", ".join([arg.name + ": " + str(arg.typ) for arg in func.args]),
                ret=render_return(func),
                func_type="constant" if func.const else "modifying",
            )
    out += "\n"
    return out
Пример #15
0
def extract_external_interface(code, contract_name, interface_codes=None):
    sigs = sig_utils.mk_full_signature(
        parser.parse_to_ast(code),
        sig_formatter=lambda x, y: (x, y),
        interface_codes=interface_codes,
    )
    functions = [sig for sig, _ in sigs if isinstance(sig, FunctionSignature)]
    cname = Path(contract_name).stem.capitalize()

    out = ""
    offset = 4 * " "
    for idx, func in enumerate(functions):
        if idx == 0:
            out += f"\n# External Contracts\ncontract {cname}:\n"
        if not func.private and func.name != '__init__':
            args = ", ".join([arg.name + ": " + str(arg.typ) for arg in func.args])
            func_type = "constant" if func.const else "modifying"
            out += offset + f"def {func.name}({args}){render_return(func)}: {func_type}\n"
    out += "\n"
    return out
Пример #16
0
def mk_method_identifiers(code, interface_codes=None):
    from vyper.parser.parser import parse_to_ast
    o = {}
    global_ctx = GlobalContext.get_global_context(
        parse_to_ast(code),
        interface_codes=interface_codes,
    )

    for code in global_ctx._defs:
        sig = FunctionSignature.from_definition(
            code,
            sigs=global_ctx._contracts,
            custom_units=global_ctx._custom_units,
            constants=global_ctx._constants,
        )
        if not sig.private:
            default_sigs = generate_default_arg_sigs(code,
                                                     global_ctx._contracts,
                                                     global_ctx)
            for s in default_sigs:
                o[s.sig] = hex(s.method_id)

    return o
Пример #17
0
def extract_interface_str(code, contract_name):
    sigs = parser.mk_full_signature(parser.parse_to_ast(code), sig_formatter=lambda x, y: (x, y))
    events = [sig for sig, _ in sigs if isinstance(sig, EventSignature)]
    functions = [sig for sig, _ in sigs if isinstance(sig, FunctionSignature)]
    out = ""
    # Print events.
    for idx, event in enumerate(events):
        if idx == 0:
            out += "# Events\n\n"
        out += "{event_name}: event({{{args}}})\n".format(
            event_name=event.name,
            args=", ".join([arg.name + ": " + str(arg.typ) for arg in event.args])
        )

    # Print functions.
    def render_decorator(sig):
        o = "\n"
        if sig.const:
            o += "@constant\n"
        if not sig.private:
            o += "@public\n"
        return o

    for idx, func in enumerate(functions):
        if idx == 0:
            out += "\n# Functions\n"
        if not func.private and func.name != '__init__':
            out += "{decorator}def {name}({args}){ret}:\n    pass\n".format(
                decorator=render_decorator(func),
                name=func.name,
                args=", ".join([arg.name + ": " + str(arg.typ) for arg in func.args]),
                ret=render_return(func)
            )
    out += "\n"

    return out
Пример #18
0
def test_grammar_bruteforce(code):
    if utf8_encodable(code):
        tree = parser.parse_to_ast(code + "\n")
        assert isinstance(tree, list)
Пример #19
0
def _mk_ast_dict(code, contract_name, interface_codes):
    o = {
        'contract_name': contract_name,
        'ast': ast_to_dict(parser.parse_to_ast(code))
    }
    return o
Пример #20
0
def extract_sigs(code):
    sigs = parser.mk_full_signature(parser.parse_to_ast(code),
                                    sig_formatter=lambda x, y: x)
    return sigs