diff --git a/rebar.config b/rebar.config index 6349a32..15fb233 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "53a055b"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "29b5ee3"}}} , {getopt, "1.0.1"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index a88c51a..4d651bc 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.1.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"53a055b90a7201761ab7bc2c55d6ddf5a1f38f27"}}, + {ref,"29b5ee3e68086e0f0170d3c70e92bbfa210cbae6"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 5da40e0..e7cb013 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -31,7 +31,9 @@ map_get | map_get_d | map_set | map_from_list | map_to_list | map_delete | map_member | map_size | string_length | string_concat | bits_set | bits_clear | bits_test | bits_sum | - bits_intersection | bits_union | bits_difference | contract_address. + bits_intersection | bits_union | bits_difference | + contract_to_address | crypto_ecverify | crypto_ecverify_secp256k1 | + crypto_sha3 | crypto_sha256 | crypto_blake2b. -type flit() :: {int, integer()} | {string, binary()} @@ -315,8 +317,10 @@ type_to_fcode(Env, Sub, {tuple_t, _, Types}) -> type_to_fcode(Env, Sub, {record_t, Fields}) -> FieldType = fun({field_t, _, _, Ty}) -> Ty end, type_to_fcode(Env, Sub, {tuple_t, [], lists:map(FieldType, Fields)}); +type_to_fcode(_Env, _Sub, {bytes_t, _, 32}) -> hash; +type_to_fcode(_Env, _Sub, {bytes_t, _, 64}) -> signature; type_to_fcode(_Env, _Sub, {bytes_t, _, _N}) -> - string; %% TODO: add bytes type to FATE? + string; %% TODO: add bytes type to FATE type_to_fcode(_Env, Sub, {tvar, _, X}) -> maps:get(X, Sub, {tvar, X}); type_to_fcode(Env, Sub, {fun_t, _, Named, Args, Res}) -> @@ -386,7 +390,7 @@ expr_to_fcode(Env, _Type, {tuple, _, Es}) -> expr_to_fcode(Env, Type, {proj, _Ann, Rec = {typed, _, _, RecType}, {id, _, X}}) -> case RecType of {con, _, _} when X == "address" -> - {op, contract_address, [expr_to_fcode(Env, Rec)]}; + {op, contract_to_address, [expr_to_fcode(Env, Rec)]}; {con, _, _} -> {fun_t, _, Named, Args, _} = Type, Arity = length(Named) + length(Args), @@ -758,7 +762,8 @@ op_builtins() -> [map_from_list, map_to_list, map_delete, map_member, map_size, string_length, string_concat, string_sha3, string_sha256, string_blake2b, bits_set, bits_clear, bits_test, bits_sum, bits_intersection, bits_union, - bits_difference, int_to_str, address_to_str]. + bits_difference, int_to_str, address_to_str, crypto_ecverify, + crypto_ecverify_secp256k1, crypto_sha3, crypto_sha256, crypto_blake2b]. builtin_to_fcode(map_delete, [Key, Map]) -> {op, map_delete, [Map, Key]}; diff --git a/src/aeso_compiler.erl b/src/aeso_compiler.erl index 18f6bb3..dbcfa0c 100644 --- a/src/aeso_compiler.erl +++ b/src/aeso_compiler.erl @@ -111,10 +111,18 @@ from_string1(aevm, ContractString, Options) -> type_info => TypeInfo }}; from_string1(fate, ContractString, Options) -> - Ast = parse(ContractString, Options), - TypedAst = aeso_ast_infer_types:infer(Ast, Options), - FCode = aeso_ast_to_fcode:ast_to_fcode(TypedAst, Options), - {ok, aeso_fcode_to_fate:compile(FCode, Options)}. + Ast = parse(ContractString, Options), + TypedAst = aeso_ast_infer_types:infer(Ast, Options), + FCode = aeso_ast_to_fcode:ast_to_fcode(TypedAst, Options), + FateCode = aeso_fcode_to_fate:compile(FCode, Options), + ByteCode = aeb_fate_code:serialize(FateCode, []), + {ok, Version} = version(), + {ok, #{byte_code => ByteCode, + compiler_version => Version, + contract_source => ContractString, + type_info => [], + fate_code => FateCode + }}. -spec string_to_icode(string(), [option()]) -> map(). string_to_icode(ContractString, Options) -> diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index d20a8b9..1efc581 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -95,6 +95,12 @@ Op =:= 'BITS_OR' orelse Op =:= 'BITS_AND' orelse Op =:= 'BITS_DIFF' orelse + Op =:= 'SHA3' orelse + Op =:= 'SHA256' orelse + Op =:= 'BLAKE2B' orelse + Op =:= 'ECVERIFY' orelse + Op =:= 'ECVERIFY_SECP256K1' orelse + Op =:= 'CONTRACT_TO_ADDRESS' orelse false)). -record(env, { contract, vars = [], locals = [], tailpos = true }). @@ -491,16 +497,6 @@ builtin_to_scode(_Env, aens_transfer, [_, _, _, _] = _Args) -> ?TODO(fate_aens_transfer_instruction); builtin_to_scode(_Env, aens_revoke, [_, _, _] = _Args) -> ?TODO(fate_aens_revoke_instruction); -builtin_to_scode(_Env, crypto_ecverify, [_, _, _] = _Args) -> - ?TODO(fate_crypto_ecverify_instruction); -builtin_to_scode(_Env, crypto_ecverify_secp256k1, [_, _, _] = _Args) -> - ?TODO(fate_crypto_ecverify_secp256k1_instruction); -builtin_to_scode(_Env, crypto_sha3, [_] = _Args) -> - ?TODO(fate_crypto_sha3_instruction); -builtin_to_scode(_Env, crypto_sha256, [_] = _Args) -> - ?TODO(fate_crypto_sha256_instruction); -builtin_to_scode(_Env, crypto_blake2b, [_] = _Args) -> - ?TODO(fate_crypto_blake2b_instruction); builtin_to_scode(_Env, auth_tx_hash, []) -> ?TODO(fate_auth_tx_hash_instruction). @@ -540,7 +536,15 @@ op_to_scode(bits_union) -> aeb_fate_ops:bits_or(?a, ?a, ?a); op_to_scode(bits_difference) -> aeb_fate_ops:bits_diff(?a, ?a, ?a); op_to_scode(address_to_str) -> aeb_fate_ops:addr_to_str(?a, ?a); op_to_scode(int_to_str) -> aeb_fate_ops:int_to_str(?a, ?a); -op_to_scode(contract_address) -> ?TODO(fate_contract_to_address_conversion). +op_to_scode(contract_to_address) -> aeb_fate_ops:contract_to_address(?a, ?a); +op_to_scode(crypto_ecverify) -> aeb_fate_ops:ecverify(?a, ?a, ?a, ?a); +op_to_scode(crypto_ecverify_secp256k1) -> aeb_fate_ops:ecverify_secp256k1(?a, ?a, ?a, ?a); +op_to_scode(crypto_sha3) -> aeb_fate_ops:sha3(?a, ?a); +op_to_scode(crypto_sha256) -> aeb_fate_ops:sha256(?a, ?a); +op_to_scode(crypto_blake2b) -> aeb_fate_ops:blake2b(?a, ?a); +op_to_scode(string_sha3) -> aeb_fate_ops:sha3(?a, ?a); +op_to_scode(string_sha256) -> aeb_fate_ops:sha256(?a, ?a); +op_to_scode(string_blake2b) -> aeb_fate_ops:blake2b(?a, ?a). %% PUSH and STORE ?a are the same, so we use STORE to make optimizations %% easier, and specialize to PUSH (which is cheaper) at the end. @@ -759,6 +763,12 @@ attributes(I) -> {'BITS_OR', A, B, C} -> Pure(A, [B, C]); {'BITS_AND', A, B, C} -> Pure(A, [B, C]); {'BITS_DIFF', A, B, C} -> Pure(A, [B, C]); + {'SHA3', A, B} -> Pure(A, [B]); + {'SHA256', A, B} -> Pure(A, [B]); + {'BLAKE2B', A, B} -> Pure(A, [B]); + {'ECVERIFY', A, B, C, D} -> Pure(A, [B, C, D]); + {'ECVERIFY_SECP256K1', A, B, C, D} -> Pure(A, [B, C, D]); + {'CONTRACT_TO_ADDRESS', A, B} -> Pure(A, [B]); {'ADDRESS', A} -> Pure(A, []); {'BALANCE', A} -> Impure(A, []); {'BALANCE_OTHER', A, B} -> Impure(A, [B]); diff --git a/test/aeso_compiler_tests.erl b/test/aeso_compiler_tests.erl index 331e996..dfca755 100644 --- a/test/aeso_compiler_tests.erl +++ b/test/aeso_compiler_tests.erl @@ -23,7 +23,7 @@ simple_compile_test_() -> contract_source := _, type_info := _} when Backend == aevm -> ?assertMatch(Code when is_binary(Code), ByteCode); - Code when Backend == fate, is_tuple(Code) -> + #{fate_code := Code} when Backend == fate -> Code1 = aeb_fate_code:deserialize(aeb_fate_code:serialize(Code)), ?assertMatch({X, X}, {Code1, Code}); ErrBin ->