From efe6f0ed06660a7e249aebebb84c73ebb2617b6d Mon Sep 17 00:00:00 2001 From: Ulf Norell Date: Fri, 6 Sep 2019 16:01:21 +0200 Subject: [PATCH] [AEVM] Compile Crypto.(hash_fun) to String.(hash_fun) for byte arrays --- src/aeso_ast_to_icode.erl | 44 ++++++++++++++++++++++----------------- src/aeso_builtins.erl | 8 +++++++ 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/aeso_ast_to_icode.erl b/src/aeso_ast_to_icode.erl index 129443c..3f5ce4c 100644 --- a/src/aeso_ast_to_icode.erl +++ b/src/aeso_ast_to_icode.erl @@ -659,16 +659,12 @@ builtin_code(_, {qid, _, ["Crypto", "ecrecover_secp256k1"]}, [Msg, Sig], _, _, I [ast_body(Msg, Icode), ast_body(Sig, Icode)], [word, bytes_t(65)], aeso_icode:option_typerep(bytes_t(20))); -builtin_code(_, {qid, _, ["Crypto", "sha3"]}, [Term], [Type], _, Icode) -> - generic_hash_primop(?PRIM_CALL_CRYPTO_SHA3, Term, Type, Icode); -builtin_code(_, {qid, _, ["Crypto", "sha256"]}, [Term], [Type], _, Icode) -> - generic_hash_primop(?PRIM_CALL_CRYPTO_SHA256, Term, Type, Icode); -builtin_code(_, {qid, _, ["Crypto", "blake2b"]}, [Term], [Type], _, Icode) -> - generic_hash_primop(?PRIM_CALL_CRYPTO_BLAKE2B, Term, Type, Icode); -builtin_code(_, {qid, _, ["String", "sha256"]}, [String], _, _, Icode) -> - string_hash_primop(?PRIM_CALL_CRYPTO_SHA256_STRING, String, Icode); -builtin_code(_, {qid, _, ["String", "blake2b"]}, [String], _, _, Icode) -> - string_hash_primop(?PRIM_CALL_CRYPTO_BLAKE2B_STRING, String, Icode); +builtin_code(_, {qid, _, ["Crypto", Op]}, [Term], [Type], _, Icode) + when Op == "sha3"; Op == "sha256"; Op == "blake2b" -> + generic_hash_primop(list_to_atom(Op), ast_body(Term, Icode), Type, Icode); +builtin_code(_, {qid, _, ["String", Op]}, [String], _, _, Icode) + when Op == "sha3"; Op == "sha256"; Op == "blake2b" -> + string_hash_primop(list_to_atom(Op), ast_body(String, Icode)); %% Strings %% -- String length @@ -679,10 +675,6 @@ builtin_code(_, {qid, _, ["String", "length"]}, [String], _, _, Icode) -> builtin_code(_, {qid, _, ["String", "concat"]}, [String1, String2], _, _, Icode) -> builtin_call(string_concat, [ast_body(String1, Icode), ast_body(String2, Icode)]); -%% -- String hash (sha3) -builtin_code(_, {qid, _, ["String", "sha3"]}, [String], _, _, Icode) -> - #unop{ op = 'sha3', rand = ast_body(String, Icode) }; - builtin_code(_, {qid, _, ["Bits", Fun]}, Args, _, _, Icode) when Fun == "test"; Fun == "set"; Fun == "clear"; Fun == "union"; Fun == "intersection"; Fun == "difference" -> @@ -846,15 +838,29 @@ prim_call(Prim, Amount, Args, ArgTypes, OutType) -> type_hash= #integer{value = TypeHash} }. -generic_hash_primop(PrimOp, Term, Type, Icode) -> +generic_hash_primop(Op, Arg, {bytes_t, _, N}, _Icode) -> + %% Compile hashing bytes to String.hash. Makes it easier for the user to + %% predict the result. + string_hash_primop(Op, aeso_builtins:bytes_to_raw_string(N, Arg)); +generic_hash_primop(Op, Arg, Type, Icode) -> + PrimOp = case Op of + sha3 -> ?PRIM_CALL_CRYPTO_SHA3; + sha256 -> ?PRIM_CALL_CRYPTO_SHA256; + blake2b -> ?PRIM_CALL_CRYPTO_BLAKE2B + end, ArgType = ast_type(Type, Icode), TypeValue = type_value(ArgType), prim_call(PrimOp, #integer{value = 0}, - [TypeValue, ast_body(Term, Icode)], - [typerep, ArgType], word). + [TypeValue, Arg], [typerep, ArgType], word). -string_hash_primop(PrimOp, String, Icode) -> - prim_call(PrimOp, #integer{value = 0}, [ast_body(String, Icode)], [string], word). +string_hash_primop(sha3, String) -> + #unop{ op = 'sha3', rand = String }; +string_hash_primop(Op, String) -> + PrimOp = case Op of + sha256 -> ?PRIM_CALL_CRYPTO_SHA256_STRING; + blake2b -> ?PRIM_CALL_CRYPTO_BLAKE2B_STRING + end, + prim_call(PrimOp, #integer{value = 0}, [String], [string], word). make_type_def(Args, Def, Icode = #{ type_vars := TypeEnv }) -> TVars = [ X || {tvar, _, X} <- Args ], diff --git a/src/aeso_builtins.erl b/src/aeso_builtins.erl index b913db9..79677c3 100644 --- a/src/aeso_builtins.erl +++ b/src/aeso_builtins.erl @@ -10,6 +10,7 @@ -module(aeso_builtins). -export([ builtin_function/1 + , bytes_to_raw_string/2 , check_event_type/1 , used_builtins/1 ]). @@ -575,3 +576,10 @@ builtin_string_reverse_() -> builtin_addr_to_str() -> {[{"a", word}], ?call({baseX_int, 58}, [?V(a)]), word}. +bytes_to_raw_string(N, Term) when N =< 32 -> + {tuple, [?I(N), Term]}; +bytes_to_raw_string(N, Term) when N > 32 -> + Elem = fun(I) -> #binop{op = '!', left = ?I(32 * I), right = ?V(bin)} + end, + Words = (N + 31) div 32, + ?LET(bin, Term, {tuple, [?I(N) | [Elem(I) || I <- lists:seq(0, Words - 1)]]}).