def generate_lll_nodes( source_code: str, global_ctx: GlobalContext) -> Tuple[parser.LLLnode, parser.LLLnode]: """ Generate the intermediate representation (LLL) from the contextualized AST. This phase also includes LLL-level optimizations. This function returns two values, one for generating deployment bytecode and the other for generating runtime bytecode. The remaining compilation phases may be called with either value, depending on the desired final output. Arguments --------- source_code : str Vyper source code. global_ctx : GlobalContext Contextualized Vyper AST Returns ------- (LLLnode, LLLnode) LLL to generate deployment bytecode LLL to generate runtime bytecode """ lll_nodes, lll_runtime = parser.parse_tree_to_lll(source_code, global_ctx) lll_nodes = optimizer.optimize(lll_nodes) lll_runtime = optimizer.optimize(lll_runtime) return lll_nodes, lll_runtime
def transpile(clss, target="deploy"): if target not in ["deploy", "abi", "bytecode", "lll", "vyper", "vy"]: raise ValueError("Unrecognized target for transpilation") if type(clss) is Lll: #todo: need to rework this if target == "bytecode": asm = compile_to_assembly(clss.node) return '0x' + assembly_to_evm(asm).hex() raise ValueError("lll can only be compiled to bytecode for now") vyp = python_to_vyper(clss) if target == "vyper" or target == "vy": return vyp if target == "bytecode": return Bytecode('0x' + compiler.compile(str(vyp)).hex()) if target == "abi": return Abi(compiler.mk_full_signature(str(vyp))) if target == "deploy": abi = Abi(compiler.mk_full_signature(str(vyp))) bytecode = Bytecode('0x' + compiler.compile(str(vyp)).hex()) return Deploy(abi, bytecode) return Lll(optimizer.optimize(parse_to_lll(str(vyp))))
def get_compiler_gas_estimate(code, func): lll_nodes = optimizer.optimize(parse_to_lll(code)) if func: return compiler.utils.build_gas_estimates(lll_nodes)[func] + 22000 else: return sum( compiler.utils.build_gas_estimates(lll_nodes).values()) + 22000
def generate_validation_code(address): valcode = generate_pure_ecrecover_LLL_source(address) lll_node = LLLnode.from_list(valcode) optimized = optimizer.optimize(lll_node) assembly = compile_lll.compile_to_assembly(optimized) evm = compile_lll.assembly_to_evm(assembly) return evm
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
def compile(endpoint): if endpoint not in ['compile', 'compile-k']: abort(500) source = request.form.get('source', '') try: if endpoint == 'compile': abi = compiler.mk_full_signature(source) abi_code = 200 else: raise Exception('Not available') except Exception as e: abi = str(e) abi_code = 500 try: if endpoint == 'compile': json_abi = json.dumps(compiler.mk_full_signature(source)) json_abi_code = 200 else: raise Exception('Not available') except Exception as e: json_abi = str(e) json_abi_code = 500 try: if endpoint == 'compile': bytecode = '0x' + compiler.compile(source).hex() bytecode_code = 200 else: raise Exception('Not available') except Exception as e: bytecode = str(e) bytecode_code = 500 try: if endpoint == 'compile': ir = optimizer.optimize(parse_to_lll(source)) ir = str(ir) ir_code = 200 else: raise Exception('Not available') #ast = parse(source) #print("lala") #print(ast) #ir = viper2lll(ast) #ir_code = 200 except Exception as e: ir = str(e) ir_code = 500 r_dict = { 'result': { 'abi': abi, 'abi_code': abi_code, 'json': json_abi, 'json_code': json_abi_code, 'bytecode': bytecode, 'bytecode_code': bytecode_code, 'lll': ir, 'lll_code': ir_code } } return make_response(jsonify(r_dict), 200)
def test_sha3_32(): lll = ["sha3_32", 0] evm = [ "PUSH1", 0, "PUSH1", 192, "MSTORE", "PUSH1", 32, "PUSH1", 192, "SHA3" ] assert compile_lll.compile_to_assembly(LLLnode.from_list(lll)) == evm assert compile_lll.compile_to_assembly( optimizer.optimize(LLLnode.from_list(lll))) == evm
def test_sha3_32(): lll = ['sha3_32', 0] evm = [ 'PUSH1', 0, 'PUSH1', 192, 'MSTORE', 'PUSH1', 32, 'PUSH1', 192, 'SHA3' ] assert compile_lll.compile_to_assembly(LLLnode.from_list(lll)) == evm assert compile_lll.compile_to_assembly( optimizer.optimize(LLLnode.from_list(lll))) == evm
def get_source_map(code): asm_list = compile_lll.compile_to_assembly( optimizer.optimize(parser.parse_to_lll(code, runtime_only=True))) c, line_number_map = compile_lll.assembly_to_evm(asm_list) # Sort line_number_map out = OrderedDict() keylist = line_number_map.keys() for k in sorted(keylist): out[k] = line_number_map[k] return out
def lll_compiler(lll, *args, **kwargs): lll = optimizer.optimize(LLLnode.from_list(lll)) bytecode, _ = compile_lll.assembly_to_evm(compile_lll.compile_to_assembly(lll)) abi = kwargs.get('abi') or [] contract = w3.eth.contract(bytecode=bytecode, abi=abi) deploy_transaction = { 'data': contract._encode_constructor_data(args, kwargs) } tx = w3.eth.sendTransaction(deploy_transaction) address = w3.eth.getTransactionReceipt(tx)['contractAddress'] contract = w3.eth.contract(address, abi=abi, bytecode=bytecode, ContractFactoryClass=VyperContract) return contract
def lll_compiler(lll, *args, **kwargs): lll = optimizer.optimize(LLLnode.from_list(lll)) bytecode, _ = compile_lll.assembly_to_evm(compile_lll.compile_to_assembly(lll)) abi = kwargs.get("abi") or [] c = w3.eth.contract(abi=abi, bytecode=bytecode) deploy_transaction = c.constructor() tx_hash = deploy_transaction.transact() address = w3.eth.getTransactionReceipt(tx_hash)["contractAddress"] contract = w3.eth.contract( address, abi=abi, bytecode=bytecode, ContractFactoryClass=VyperContract, ) return contract
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
def gas_estimate(origcode, *args, **kwargs): o = {} code = optimizer.optimize(parser.parse_to_lll(origcode, *args, **kwargs)) # Extract the stuff inside the LLL bracket if code.value == 'seq': if len(code.args) > 0 and code.args[-1].value == 'return': code = code.args[-1].args[1].args[0] assert code.value == 'seq' for arg in code.args: if arg.func_name is not None: o[arg.func_name] = arg.total_gas return o
def compile(code, *args, **kwargs): lll = optimizer.optimize(parser.parse_tree_to_lll(parser.parse(code), code, runtime_only=kwargs.get('bytecode_runtime', False))) asm = compile_lll.compile_to_assembly(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 not this code contains DEBUG opcode.') print('This will only work in a support EVM. This FAIL on any other nodes.') return compile_lll.assembly_to_evm(asm)
def get_source_map(code, contract_name, interface_codes=None): asm_list = compile_lll.compile_to_assembly( optimizer.optimize( parser.parse_to_lll(code, runtime_only=True, interface_codes=interface_codes))) c, line_number_map = compile_lll.assembly_to_evm(asm_list) # Sort line_number_map out = OrderedDict() for k in sorted(line_number_map.keys()): out[k] = line_number_map[k] out['pc_pos_map_compressed'] = compress_source_map(code, out['pc_pos_map'], out['pc_jump_map']) out['pc_pos_map'] = dict((k, v) for k, v in out['pc_pos_map'].items() if v) return out
def compile_valcode_to_evm_bytecode(valcode_type, address): valcodes = generate_all_valcodes(address) valcode = valcodes[valcode_type] # We assume bytes are compiled evm code if type(valcode) is bytes: return valcode # We assume lists are uncompiled LLL seqs elif type(valcode) is list: lll_node = LLLnode.from_list(valcode) optimized = optimizer.optimize(lll_node) assembly = compile_lll.compile_to_assembly(optimized) evm = compile_lll.assembly_to_evm(assembly) return evm # Any other types are unacceptable else: raise ValueError('Valcode must be of types list (uncompiled LLL), or ' 'bytes (compiled bytecode). Given: ' '{}'.format(type(valcode)))
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
def compile_to_lll(input_file, output_formats, show_gas_estimates=False): with open(input_file) as fh: s_expressions = parse_s_exp(fh.read()) if show_gas_estimates: LLLnode.repr_show_gas = True compiler_data = {} lll = LLLnode.from_list(s_expressions[0]) if "ir" in output_formats: compiler_data["ir"] = lll if "opt_ir" in output_formats: compiler_data["opt_ir"] = optimizer.optimize(lll) asm = compile_lll.compile_to_assembly(lll) if "asm" in output_formats: compiler_data["asm"] = asm if "bytecode" in output_formats: (bytecode, _srcmap) = compile_lll.assembly_to_evm(asm) compiler_data["bytecode"] = "0x" + bytecode.hex() return compiler_data
def lll_to_evm(lll): return compile_lll.assembly_to_evm(compile_lll.compile_to_assembly(optimizer.optimize(lll)))
out[k] = line_number_map[k] return out output_formats_map = { 'abi': lambda code, contract_name, interface_codes: mk_full_signature( code, interface_codes=interface_codes), 'bytecode': lambda code, contract_name, interface_codes: '0x' + __compile( code, interface_codes=interface_codes).hex(), 'bytecode_runtime': lambda code, contract_name, interface_codes: '0x' + __compile( code, bytecode_runtime=True, interface_codes=interface_codes).hex(), 'ir': lambda code, contract_name, interface_codes: optimizer.optimize( parser.parse_to_lll(code, interface_codes=interface_codes)), 'asm': lambda code, contract_name, interface_codes: get_asm( compile_lll.compile_to_assembly( optimizer.optimize( parser.parse_to_lll(code, interface_codes=interface_codes)))), 'source_map': lambda code, contract_name, interface_codes: get_source_map( code, contract_name, interface_codes=interface_codes), 'method_identifiers': lambda code, contract_name, interface_codes: parser.mk_method_identifiers( code, interface_codes=interface_codes), 'interface': lambda code, contract_name, interface_codes: extract_interface_str( code, contract_name, interface_codes=interface_codes), 'external_interface':
def _mk_asm_output(code, contract_name, interface_codes, source_id): return get_asm( compile_lll.compile_to_assembly( optimizer.optimize( parser.parse_to_lll(code, interface_codes=interface_codes))))
def _mk_ir_output(code, contract_name, interface_codes, source_id): return optimizer.optimize( parser.parse_to_lll(code, interface_codes=interface_codes))
'mstore', add(sub(data, ['mload', position_offset]), ['mload', i]), add(['mload', add(positions, ['mload', i])], ['mload', position_offset]) ], # ~mstore(data - positionOffset + i, ~mload(positions + i) + positionOffset) ['mstore', i, sub(['mload', i], 32)], ] ], [ 'mstore', sub(data, 32), add(['mload', position_offset], ['mload', data_pos]) ], [ 'return', sub(data, ['mload', position_offset]), add(['mload', position_offset], ['mload', data_pos]) ] ], [0] ] ] ]) rlp_decoder_lll = optimizer.optimize(rlp_decoder_lll) rlp_decoder_bytes, _ = compile_lll.assembly_to_evm( compile_lll.compile_to_assembly(rlp_decoder_lll))
runtime_only=True, interface_codes=interface_codes))) c, line_number_map = compile_lll.assembly_to_evm(asm_list) # Sort line_number_map out = OrderedDict() keylist = line_number_map.keys() for k in sorted(keylist): out[k] = line_number_map[k] return out output_formats_map = { 'abi': lambda code, contract_name, interface_codes: mk_full_signature(code, interface_codes=interface_codes), 'bytecode': lambda code, contract_name, interface_codes: '0x' + __compile(code, interface_codes=interface_codes).hex(), 'bytecode_runtime': lambda code, contract_name, interface_codes: '0x' + __compile(code, bytecode_runtime=True, interface_codes=interface_codes).hex(), 'ir': lambda code, contract_name, interface_codes: optimizer.optimize(parser.parse_to_lll(code, interface_codes=interface_codes)), 'asm': lambda code, contract_name, interface_codes: get_asm(compile_lll.compile_to_assembly(optimizer.optimize(parser.parse_to_lll(code, interface_codes=interface_codes)))), 'source_map': lambda code, contract_name, interface_codes: get_source_map(code, contract_name, interface_codes=interface_codes), 'method_identifiers': lambda code, contract_name, interface_codes: parser.mk_method_identifiers(code, interface_codes=interface_codes), 'interface': lambda code, contract_name, interface_codes: extract_interface_str(code, contract_name, interface_codes=interface_codes), 'external_interface': lambda code, contract_name, interface_codes: extract_external_interface(code, contract_name, interface_codes=interface_codes), } def compile_codes(codes, output_formats=['bytecode'], output_type='list', exc_handler=None, interface_codes=None): out = OrderedDict() for contract_name, code in codes.items(): for output_format in output_formats: if output_format not in output_formats_map: raise Exception('Unsupported format type %s.' % output_format)
def test_lll_compile_fail(lll): optimized = optimizer.optimize(LLLnode.from_list(lll[0])) optimized.repr_show_gas = True hand_optimized = LLLnode.from_list(lll[1]) hand_optimized.repr_show_gas = True assert optimized == hand_optimized
def lll_compiler(lll): lll = optimizer.optimize(LLLnode.from_list(lll)) byte_code = compile_lll.assembly_to_evm(compile_lll.compile_to_assembly(lll)) t.s.tx(to=b'', data=byte_code)
out = OrderedDict() keylist = line_number_map.keys() for k in sorted(keylist): out[k] = line_number_map[k] return out output_formats_map = { 'abi': lambda code: mk_full_signature(code), 'bytecode': lambda code: '0x' + __compile(code).hex(), 'bytecode_runtime': lambda code: '0x' + __compile(code, bytecode_runtime=True).hex(), 'ir': lambda code: optimizer.optimize(parser.parse_to_lll(code)), 'asm': lambda code: get_asm( compile_lll.compile_to_assembly( optimizer.optimize(parser.parse_to_lll(code)))), 'source_map': get_source_map, 'method_identifiers': lambda code: parser.mk_method_identifiers(code) } def compile_codes(codes, output_formats=['bytecode'], output_type='list', exc_handler=None):