diff --git a/rebar.config b/rebar.config index bd0dda0..232d506 100644 --- a/rebar.config +++ b/rebar.config @@ -3,7 +3,7 @@ {erl_opts, [debug_info]}. {deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", - {ref, "2555868"}}} + {ref, "08a09b0"}}} , {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 a2d120e..c78d71d 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.1.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"2555868990ac2a08876e86b1b798b4750273591f"}}, + {ref,"08a09b065b9c5c4d1c499372a90914c80349dace"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", diff --git a/src/aeso_ast_infer_types.erl b/src/aeso_ast_infer_types.erl index a24aaea..7f6bc2b 100644 --- a/src/aeso_ast_infer_types.erl +++ b/src/aeso_ast_infer_types.erl @@ -404,7 +404,7 @@ global_env() -> ContractScope = #scope { funs = MkDefs( [{"address", Address}, - %% {"owner", Int}, %% Not in EVM + {"creator", Address}, {"balance", Int}]) }, CallScope = #scope @@ -424,7 +424,9 @@ global_env() -> {"get_question", Fun([Oracle(Q, R), Query(Q, R)], Q)}, {"respond", SignFun([Oracle(Q, R), Query(Q, R), R], Unit)}, {"extend", SignFun([Oracle(Q, R), TTL], Unit)}, - {"get_answer", Fun([Oracle(Q, R), Query(Q, R)], option_t(Ann, R))}]) }, + {"get_answer", Fun([Oracle(Q, R), Query(Q, R)], option_t(Ann, R))}, + {"check", Fun([Oracle(Q, R)], Bool)}, + {"check_query", Fun([Oracle(Q,R), Query(Q, R)], Bool)}]) }, AENSScope = #scope { funs = MkDefs( @@ -482,7 +484,9 @@ global_env() -> %% Conversion IntScope = #scope{ funs = MkDefs([{"to_str", Fun1(Int, String)}]) }, - AddressScope = #scope{ funs = MkDefs([{"to_str", Fun1(Address, String)}]) }, + AddressScope = #scope{ funs = MkDefs([{"to_str", Fun1(Address, String)}, + {"is_oracle", Fun1(Address, Bool)}, + {"is_contract", Fun1(Address, Bool)}]) }, #env{ scopes = #{ [] => TopScope diff --git a/src/aeso_ast_to_icode.erl b/src/aeso_ast_to_icode.erl index bb7447a..7ff8d6a 100644 --- a/src/aeso_ast_to_icode.erl +++ b/src/aeso_ast_to_icode.erl @@ -152,6 +152,7 @@ ast_body(?qid_app(["Chain", "block_hash"], [Height], _, _), Icode) -> ast_body(?qid_app(["Call", "gas_left"], [], _, _), _Icode) -> prim_gas_left; ast_body({qid, _, ["Contract", "address"]}, _Icode) -> prim_contract_address; +ast_body({qid, _, ["Contract", "creator"]}, _Icode) -> prim_contract_creator; ast_body({qid, _, ["Contract", "balance"]}, _Icode) -> #prim_balance{ address = prim_contract_address }; ast_body({qid, _, ["Call", "origin"]}, _Icode) -> prim_call_origin; ast_body({qid, _, ["Call", "caller"]}, _Icode) -> prim_caller; @@ -224,6 +225,17 @@ ast_body(?qid_app(["Oracle", "get_answer"], [Oracle, Q], [_, ?query_t(_, RType)] prim_call(?PRIM_CALL_ORACLE_GET_ANSWER, #integer{value = 0}, [ast_body(Oracle, Icode), ast_body(Q, Icode)], [word, word], aeso_icode:option_typerep(ast_type(RType, Icode))); +ast_body(?qid_app(["Oracle", "check"], [Oracle], [?oracle_t(Q, R)], _), Icode) -> + prim_call(?PRIM_CALL_ORACLE_CHECK, #integer{value = 0}, + [ast_body(Oracle, Icode), ast_type_value(Q, Icode), ast_type_value(R, Icode)], + [word, typerep, typerep], word); + +ast_body(?qid_app(["Oracle", "check_query"], [Oracle, Query], [_, ?query_t(Q, R)], _), Icode) -> + prim_call(?PRIM_CALL_ORACLE_CHECK_QUERY, #integer{value = 0}, + [ast_body(Oracle, Icode), ast_body(Query, Icode), + ast_type_value(Q, Icode), ast_type_value(R, Icode)], + [word, typerep, typerep], word); + ast_body({qid, _, ["Oracle", "register"]}, _Icode) -> gen_error({underapplied_primitive, 'Oracle.register'}); ast_body({qid, _, ["Oracle", "query"]}, _Icode) -> gen_error({underapplied_primitive, 'Oracle.query'}); ast_body({qid, _, ["Oracle", "extend"]}, _Icode) -> gen_error({underapplied_primitive, 'Oracle.extend'}); @@ -410,6 +422,12 @@ ast_body(?qid_app(["Int", "to_str"], [Int], _, _), Icode) -> ast_body(?qid_app(["Address", "to_str"], [Addr], _, _), Icode) -> builtin_call(addr_to_str, [ast_body(Addr, Icode)]); +ast_body(?qid_app(["Address", "is_oracle"], [Addr], _, _), Icode) -> + prim_call(?PRIM_CALL_ADDR_IS_ORACLE, #integer{value = 0}, + [ast_body(Addr, Icode)], [word], word); +ast_body(?qid_app(["Address", "is_contract"], [Addr], _, _), Icode) -> + prim_call(?PRIM_CALL_ADDR_IS_CONTRACT, #integer{value = 0}, + [ast_body(Addr, Icode)], [word], word); %% Other terms ast_body({id, _, Name}, _Icode) -> diff --git a/src/aeso_icode_to_asm.erl b/src/aeso_icode_to_asm.erl index 7da8010..1bf18a2 100644 --- a/src/aeso_icode_to_asm.erl +++ b/src/aeso_icode_to_asm.erl @@ -343,6 +343,8 @@ assemble_expr(Funs, Stack, _Tail, #prim_put{ state = State }) -> %% Environment primitives assemble_expr(_Funs, _Stack, _Tail, prim_contract_address) -> [i(?ADDRESS)]; +assemble_expr(_Funs, _Stack, _Tail, prim_contract_creator) -> + [i(?CREATOR)]; assemble_expr(_Funs, _Stack, _Tail, prim_call_origin) -> [i(?ORIGIN)]; assemble_expr(_Funs, _Stack, _Tail, prim_caller) -> diff --git a/test/aeso_compiler_tests.erl b/test/aeso_compiler_tests.erl index 7bcda3d..fb630b7 100644 --- a/test/aeso_compiler_tests.erl +++ b/test/aeso_compiler_tests.erl @@ -107,7 +107,8 @@ compilable_contracts() -> "basic_auth", "bitcoin_auth", "address_literals", - "bytes_equality" + "bytes_equality", + "address_chain" ]. %% Contracts that should produce type errors diff --git a/test/contracts/address_chain.aes b/test/contracts/address_chain.aes new file mode 100644 index 0000000..79cd962 --- /dev/null +++ b/test/contracts/address_chain.aes @@ -0,0 +1,33 @@ +contract Remote = + function main : (int) => () + +contract AddrChain = + type o_type = oracle(string, map(string, int)) + type oq_type = oracle_query(string, map(string, int)) + + function is_o(a : address) = + Address.is_oracle(a) + + function is_c(a : address) = + Address.is_contract(a) + +// function get_o(a : address) : option(o_type) = +// Address.get_oracle(a) + +// function get_c(a : address) : option(Remote) = +// Address.get_contract(a) + + function check_o(o : o_type) = + Oracle.check(o) + + function check_oq(o : o_type, oq : oq_type) = + Oracle.check_query(o, oq) + +// function h_to_i(h : hash) : int = +// Hash.to_int(h) + +// function a_to_i(a : address) : int = +// Address.to_int(a) mod 10 ^ 16 + + function c_creator() : address = + Contract.creator