Merge pull request #69 from aeternity/PT-162578406-payable_modifier
PT-162578406 Add payable modifier
This commit is contained in:
commit
befa1e3ff9
@ -201,3 +201,4 @@
|
|||||||
-define(PRIM_CALL_IN_ADDRESS_RANGE(__TTYPE__), (((__TTYPE__) > 599) andalso ((__TTYPE__) < 700))).
|
-define(PRIM_CALL_IN_ADDRESS_RANGE(__TTYPE__), (((__TTYPE__) > 599) andalso ((__TTYPE__) < 700))).
|
||||||
-define(PRIM_CALL_ADDR_IS_ORACLE, 600).
|
-define(PRIM_CALL_ADDR_IS_ORACLE, 600).
|
||||||
-define(PRIM_CALL_ADDR_IS_CONTRACT, 601).
|
-define(PRIM_CALL_ADDR_IS_CONTRACT, 601).
|
||||||
|
-define(PRIM_CALL_ADDR_IS_PAYABLE, 610).
|
||||||
|
@ -11,14 +11,15 @@
|
|||||||
-define(HASH_SIZE, 32).
|
-define(HASH_SIZE, 32).
|
||||||
|
|
||||||
-export([ create_calldata/4
|
-export([ create_calldata/4
|
||||||
, check_calldata/2
|
, check_calldata/3
|
||||||
, function_type_info/3
|
, function_type_info/4
|
||||||
, function_type_hash/3
|
, function_type_hash/3
|
||||||
, arg_typerep_from_function/2
|
, arg_typerep_from_function/2
|
||||||
, type_hash_from_function_name/2
|
, type_hash_from_function_name/2
|
||||||
, typereps_from_type_hash/2
|
, typereps_from_type_hash/2
|
||||||
, function_name_from_type_hash/2
|
, function_name_from_type_hash/2
|
||||||
, get_function_hash_from_calldata/1
|
, get_function_hash_from_calldata/1
|
||||||
|
, is_payable/2
|
||||||
, abi_version/0
|
, abi_version/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
@ -27,6 +28,7 @@
|
|||||||
-type typerep() :: aeb_aevm_data:type().
|
-type typerep() :: aeb_aevm_data:type().
|
||||||
-type function_type_info() :: { FunctionHash :: hash()
|
-type function_type_info() :: { FunctionHash :: hash()
|
||||||
, FunctionName :: function_name()
|
, FunctionName :: function_name()
|
||||||
|
, Payable :: boolean()
|
||||||
, ArgType :: binary() %% binary typerep
|
, ArgType :: binary() %% binary typerep
|
||||||
, OutType :: binary() %% binary typerep
|
, OutType :: binary() %% binary typerep
|
||||||
}.
|
}.
|
||||||
@ -51,12 +53,24 @@ create_calldata(FunName, Args, ArgTypes0, RetType) ->
|
|||||||
Data = aeb_heap:to_binary({TypeHashInt, list_to_tuple(Args)}),
|
Data = aeb_heap:to_binary({TypeHashInt, list_to_tuple(Args)}),
|
||||||
{ok, Data}.
|
{ok, Data}.
|
||||||
|
|
||||||
-spec check_calldata(binary(), type_info()) ->
|
-spec check_calldata(binary(), type_info(), boolean()) ->
|
||||||
{'ok', typerep(), typerep()} | {'error', atom()}.
|
{'ok', typerep(), typerep()} | {'error', atom()}.
|
||||||
check_calldata(CallData, TypeInfo) ->
|
check_calldata(CallData, TypeInfo, CheckPayable) ->
|
||||||
%% The first element of the CallData should be the function name
|
%% The first element of the CallData should be the function name
|
||||||
case get_function_hash_from_calldata(CallData) of
|
case get_function_hash_from_calldata(CallData) of
|
||||||
{ok, Hash} ->
|
{ok, Hash} ->
|
||||||
|
check_calldata(Hash, CallData, TypeInfo, CheckPayable);
|
||||||
|
{error, _What} ->
|
||||||
|
{error, bad_call_data}
|
||||||
|
end.
|
||||||
|
|
||||||
|
check_calldata(Hash, CallData, TypeInfo, true) ->
|
||||||
|
case is_payable(Hash, TypeInfo) of
|
||||||
|
{ok, true} -> check_calldata(Hash, CallData, TypeInfo, false);
|
||||||
|
{ok, false} -> {error, function_is_not_payable};
|
||||||
|
Err = {error, _} -> Err
|
||||||
|
end;
|
||||||
|
check_calldata(Hash, CallData, TypeInfo, false) ->
|
||||||
case typereps_from_type_hash(Hash, TypeInfo) of
|
case typereps_from_type_hash(Hash, TypeInfo) of
|
||||||
{ok, ArgType, OutType} ->
|
{ok, ArgType, OutType} ->
|
||||||
try aeb_heap:from_binary({tuple, [word, ArgType]}, CallData) of
|
try aeb_heap:from_binary({tuple, [word, ArgType]}, CallData) of
|
||||||
@ -70,11 +84,9 @@ check_calldata(CallData, TypeInfo) ->
|
|||||||
end;
|
end;
|
||||||
{error, _} ->
|
{error, _} ->
|
||||||
{error, unknown_function}
|
{error, unknown_function}
|
||||||
end;
|
|
||||||
{error, _What} ->
|
|
||||||
{error, bad_call_data}
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
-spec get_function_hash_from_calldata(CallData::binary()) ->
|
-spec get_function_hash_from_calldata(CallData::binary()) ->
|
||||||
{ok, binary()} | {error, term()}.
|
{ok, binary()} | {error, term()}.
|
||||||
get_function_hash_from_calldata(CallData) ->
|
get_function_hash_from_calldata(CallData) ->
|
||||||
@ -86,12 +98,13 @@ get_function_hash_from_calldata(CallData) ->
|
|||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% Handle type info from contract meta data
|
%%% Handle type info from contract meta data
|
||||||
|
|
||||||
-spec function_type_info(function_name(), [typerep()], typerep()) ->
|
-spec function_type_info(function_name(), boolean(), [typerep()], typerep()) ->
|
||||||
function_type_info().
|
function_type_info().
|
||||||
function_type_info(Name, ArgTypes, OutType) ->
|
function_type_info(Name, Payable, ArgTypes, OutType) ->
|
||||||
ArgType = {tuple, ArgTypes},
|
ArgType = {tuple, ArgTypes},
|
||||||
{ function_type_hash(Name, ArgType, OutType)
|
{ function_type_hash(Name, ArgType, OutType)
|
||||||
, Name
|
, Name
|
||||||
|
, Payable
|
||||||
, aeb_heap:to_binary(ArgType)
|
, aeb_heap:to_binary(ArgType)
|
||||||
, aeb_heap:to_binary(OutType)
|
, aeb_heap:to_binary(OutType)
|
||||||
}.
|
}.
|
||||||
@ -110,35 +123,46 @@ function_type_hash(Name, ArgType, OutType) when is_binary(Name) ->
|
|||||||
{'ok', typerep()} | {'error', 'bad_type_data' | 'unknown_function'}.
|
{'ok', typerep()} | {'error', 'bad_type_data' | 'unknown_function'}.
|
||||||
arg_typerep_from_function(Function, TypeInfo) ->
|
arg_typerep_from_function(Function, TypeInfo) ->
|
||||||
case lists:keyfind(Function, 2, TypeInfo) of
|
case lists:keyfind(Function, 2, TypeInfo) of
|
||||||
{_TypeHash, Function, ArgTypeBin,_OutTypeBin} ->
|
{_TypeHash, Function, ArgTypeBin, _OutTypeBin} ->
|
||||||
case aeb_heap:from_binary(typerep, ArgTypeBin) of
|
arg_typerep_from_type_binary(ArgTypeBin);
|
||||||
{ok, ArgType} -> {ok, ArgType};
|
{_TypeHash, Function, _Payable, ArgTypeBin, _OutTypeBin} ->
|
||||||
{error,_} -> {error, bad_type_data}
|
arg_typerep_from_type_binary(ArgTypeBin);
|
||||||
end;
|
|
||||||
false ->
|
false ->
|
||||||
{error, unknown_function}
|
{error, unknown_function}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
arg_typerep_from_type_binary(ArgTBin) ->
|
||||||
|
case aeb_heap:from_binary(typerep, ArgTBin) of
|
||||||
|
{ok, ArgT} -> {ok, ArgT};
|
||||||
|
{error,_} -> {error, bad_type_data}
|
||||||
|
end.
|
||||||
|
|
||||||
-spec typereps_from_type_hash(hash(), type_info()) ->
|
-spec typereps_from_type_hash(hash(), type_info()) ->
|
||||||
{'ok', typerep(), typerep()} | {'error', 'bad_type_data' | 'unknown_function'}.
|
{'ok', typerep(), typerep()} | {'error', 'bad_type_data' | 'unknown_function'}.
|
||||||
typereps_from_type_hash(TypeHash, TypeInfo) ->
|
typereps_from_type_hash(TypeHash, TypeInfo) ->
|
||||||
case lists:keyfind(TypeHash, 1, TypeInfo) of
|
case lists:keyfind(TypeHash, 1, TypeInfo) of
|
||||||
{TypeHash,_Function, ArgTypeBin, OutTypeBin} ->
|
{TypeHash, _Function, ArgTypeBin, OutTypeBin} ->
|
||||||
case {aeb_heap:from_binary(typerep, ArgTypeBin),
|
typereps_from_type_binaries(ArgTypeBin, OutTypeBin);
|
||||||
aeb_heap:from_binary(typerep, OutTypeBin)} of
|
{TypeHash, _Function, _Payable, ArgTypeBin, OutTypeBin} ->
|
||||||
{{ok, ArgType}, {ok, OutType}} -> {ok, ArgType, OutType};
|
typereps_from_type_binaries(ArgTypeBin, OutTypeBin);
|
||||||
{_, _} -> {error, bad_type_data}
|
|
||||||
end;
|
|
||||||
false ->
|
false ->
|
||||||
{error, unknown_function}
|
{error, unknown_function}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
typereps_from_type_binaries(ArgTBin, OutTBin) ->
|
||||||
|
case {aeb_heap:from_binary(typerep, ArgTBin), aeb_heap:from_binary(typerep, OutTBin)} of
|
||||||
|
{{ok, ArgT}, {ok, OutT}} -> {ok, ArgT, OutT};
|
||||||
|
{_, _} -> {error, bad_type_data}
|
||||||
|
end.
|
||||||
|
|
||||||
-spec function_name_from_type_hash(hash(), type_info()) ->
|
-spec function_name_from_type_hash(hash(), type_info()) ->
|
||||||
{'ok', function_name()}
|
{'ok', function_name()}
|
||||||
| {'error', 'unknown_function'}.
|
| {'error', 'unknown_function'}.
|
||||||
function_name_from_type_hash(TypeHash, TypeInfo) ->
|
function_name_from_type_hash(TypeHash, TypeInfo) ->
|
||||||
case lists:keyfind(TypeHash, 1, TypeInfo) of
|
case lists:keyfind(TypeHash, 1, TypeInfo) of
|
||||||
{TypeHash, Function,_ArgTypeBin,_OutTypeBin} ->
|
{TypeHash, Function, _ArgTypeBin, _OutTypeBin} ->
|
||||||
|
{ok, Function};
|
||||||
|
{TypeHash, Function, _Payable, _ArgTypeBin, _OutTypeBin} ->
|
||||||
{ok, Function};
|
{ok, Function};
|
||||||
false ->
|
false ->
|
||||||
{error, unknown_function}
|
{error, unknown_function}
|
||||||
@ -149,8 +173,22 @@ function_name_from_type_hash(TypeHash, TypeInfo) ->
|
|||||||
| {'error', 'unknown_function'}.
|
| {'error', 'unknown_function'}.
|
||||||
type_hash_from_function_name(Name, TypeInfo) ->
|
type_hash_from_function_name(Name, TypeInfo) ->
|
||||||
case lists:keyfind(Name, 2, TypeInfo) of
|
case lists:keyfind(Name, 2, TypeInfo) of
|
||||||
{TypeHash, Name,_ArgTypeBin,_OutTypeBin} ->
|
{TypeHash, Name, _ArgTypeBin, _OutTypeBin} ->
|
||||||
|
{ok, TypeHash};
|
||||||
|
{TypeHash, Name, _Payable, _ArgTypeBin, _OutTypeBin} ->
|
||||||
{ok, TypeHash};
|
{ok, TypeHash};
|
||||||
false ->
|
false ->
|
||||||
{error, unknown_function}
|
{error, unknown_function}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
-spec is_payable(hash(), type_info()) -> {ok, boolean()} | {error, 'unknown_function'}.
|
||||||
|
is_payable(TypeHash, TypeInfo) ->
|
||||||
|
case lists:keyfind(TypeHash, 1, TypeInfo) of
|
||||||
|
{TypeHash, _Function, _ArgTypeBin, _OutTypeBin} ->
|
||||||
|
{ok, true};
|
||||||
|
{TypeHash, _Function, Payable, _ArgTypeBin, _OutTypeBin} ->
|
||||||
|
{ok, Payable};
|
||||||
|
false ->
|
||||||
|
{error, unknown_function}
|
||||||
|
end.
|
||||||
|
|
||||||
|
@ -72,6 +72,6 @@ get_function_type_from_function_hash(SymbolHash, FateCode) ->
|
|||||||
case maps:get(SymbolHash, Functions, undefined) of
|
case maps:get(SymbolHash, Functions, undefined) of
|
||||||
undefined ->
|
undefined ->
|
||||||
{error, no_function_matching_function_hash};
|
{error, no_function_matching_function_hash};
|
||||||
{{ArgTypes, RetType}, _Code} ->
|
{_Attrs, {ArgTypes, RetType}, _Code} ->
|
||||||
{ok, ArgTypes, RetType}
|
{ok, ArgTypes, RetType}
|
||||||
end.
|
end.
|
||||||
|
@ -153,7 +153,7 @@ format_functions(Functions, Symbols) ->
|
|||||||
lists:sort(maps:to_list(CodeMap)),
|
lists:sort(maps:to_list(CodeMap)),
|
||||||
Symbols)
|
Symbols)
|
||||||
||
|
||
|
||||||
{Name, {Sig, CodeMap}} <- maps:to_list(Functions)].
|
{Name, {_Attrs, Sig, CodeMap}} <- maps:to_list(Functions)].
|
||||||
|
|
||||||
|
|
||||||
format(Name, Sig, BBs, Symbols) ->
|
format(Name, Sig, BBs, Symbols) ->
|
||||||
@ -484,7 +484,7 @@ insert_fun({NameString, ArgType, RetType}, Code, #{ fate_code := FateCode
|
|||||||
{FateCode1, Id} = aeb_fate_code:insert_symbol(Name, FateCode),
|
{FateCode1, Id} = aeb_fate_code:insert_symbol(Name, FateCode),
|
||||||
BodyByteCode = aeb_fate_code:serialize_code(lists:reverse(Code)),
|
BodyByteCode = aeb_fate_code:serialize_code(lists:reverse(Code)),
|
||||||
SigByteCode = aeb_fate_code:serialize_signature({ArgType, RetType}),
|
SigByteCode = aeb_fate_code:serialize_signature({ArgType, RetType}),
|
||||||
FunByteCode = [?FUNCTION, Id, SigByteCode, BodyByteCode],
|
FunByteCode = [?FUNCTION, Id, aeb_fate_encoding:serialize(0), SigByteCode, BodyByteCode],
|
||||||
Env#{ functions => Funs#{ Id => FunByteCode }
|
Env#{ functions => Funs#{ Id => FunByteCode }
|
||||||
, fate_code => FateCode1}.
|
, fate_code => FateCode1}.
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
, deserialize/1
|
, deserialize/1
|
||||||
, functions/1
|
, functions/1
|
||||||
, insert_annotation/4
|
, insert_annotation/4
|
||||||
, insert_fun/4
|
, insert_fun/5
|
||||||
, insert_symbol/2
|
, insert_symbol/2
|
||||||
, new/0
|
, new/0
|
||||||
, serialize/1
|
, serialize/1
|
||||||
@ -72,9 +72,9 @@ symbol_identifier(Bin) ->
|
|||||||
{ok, <<X:4/binary,_/binary>> } = eblake2:blake2b(?HASH_BYTES, Bin),
|
{ok, <<X:4/binary,_/binary>> } = eblake2:blake2b(?HASH_BYTES, Bin),
|
||||||
X.
|
X.
|
||||||
|
|
||||||
insert_fun(Name, {ArgType, RetType}, #{} = BBs, FCode) ->
|
insert_fun(Name, Attrs, {ArgType, RetType}, #{} = BBs, FCode) ->
|
||||||
{F1, ID} = insert_symbol(Name, FCode),
|
{F1, ID} = insert_symbol(Name, FCode),
|
||||||
update_functions(F1, #{ID => {{ArgType, RetType}, BBs}}).
|
update_functions(F1, #{ID => {Attrs, {ArgType, RetType}, BBs}}).
|
||||||
|
|
||||||
insert_symbol(Name, #fcode{ symbols = Syms } = F) ->
|
insert_symbol(Name, #fcode{ symbols = Syms } = F) ->
|
||||||
ID = symbol_identifier(Name),
|
ID = symbol_identifier(Name),
|
||||||
@ -128,10 +128,17 @@ to_hexstring(ByteList) ->
|
|||||||
serialize_functions(#fcode{ functions = Functions }) ->
|
serialize_functions(#fcode{ functions = Functions }) ->
|
||||||
%% Sort the functions on name to get a canonical serialisation.
|
%% Sort the functions on name to get a canonical serialisation.
|
||||||
iolist_to_binary(
|
iolist_to_binary(
|
||||||
lists:foldr(fun({Id, {Sig, C}}, Acc) ->
|
lists:foldr(fun({Id, {Attrs, Sig, C}}, Acc) ->
|
||||||
[[?FUNCTION, Id, serialize_signature(Sig), serialize_bbs(C)] | Acc]
|
[[?FUNCTION, Id, serialize_attributes(Attrs), serialize_signature(Sig), serialize_bbs(C)] | Acc]
|
||||||
end, [], lists:sort(maps:to_list(Functions)))).
|
end, [], lists:sort(maps:to_list(Functions)))).
|
||||||
|
|
||||||
|
serialize_attributes(Attrs) ->
|
||||||
|
AttrVal = lists:sum([ attr_value(Attr) || Attr <- Attrs ]),
|
||||||
|
aeb_fate_encoding:serialize(?MAKE_FATE_INTEGER(AttrVal)).
|
||||||
|
|
||||||
|
attr_value(private) -> 1;
|
||||||
|
attr_value(payable) -> 2.
|
||||||
|
|
||||||
serialize_signature({Args, RetType}) ->
|
serialize_signature({Args, RetType}) ->
|
||||||
[aeb_fate_encoding:serialize_type({tuple, Args}) |
|
[aeb_fate_encoding:serialize_type({tuple, Args}) |
|
||||||
aeb_fate_encoding:serialize_type(RetType)].
|
aeb_fate_encoding:serialize_type(RetType)].
|
||||||
@ -139,7 +146,7 @@ serialize_signature({Args, RetType}) ->
|
|||||||
serialize_symbol_table(#fcode{ symbols = Symbols }) ->
|
serialize_symbol_table(#fcode{ symbols = Symbols }) ->
|
||||||
aeb_fate_encoding:serialize(aeb_fate_data:make_map(Symbols)).
|
aeb_fate_encoding:serialize(aeb_fate_data:make_map(Symbols)).
|
||||||
|
|
||||||
serialize_annotations(#fcode{ annotations = Annotations}) ->
|
serialize_annotations(#fcode{ annotations = Annotations }) ->
|
||||||
aeb_fate_encoding:serialize(aeb_fate_data:make_map(Annotations)).
|
aeb_fate_encoding:serialize(aeb_fate_data:make_map(Annotations)).
|
||||||
|
|
||||||
serialize_bbs(#{} = BBs) ->
|
serialize_bbs(#{} = BBs) ->
|
||||||
@ -166,7 +173,7 @@ serialize_op(Op) ->
|
|||||||
|
|
||||||
sanity_check(#fcode{ functions = Funs }) ->
|
sanity_check(#fcode{ functions = Funs }) ->
|
||||||
_ = [ case Def of
|
_ = [ case Def of
|
||||||
{_, BBs} when byte_size(Id) == 4 -> sanity_check_bbs(BBs);
|
{_, _, BBs} when byte_size(Id) == 4 -> sanity_check_bbs(BBs);
|
||||||
_ -> error({illegal_function_id, Id})
|
_ -> error({illegal_function_id, Id})
|
||||||
end || {Id, Def} <- maps:to_list(Funs) ],
|
end || {Id, Def} <- maps:to_list(Funs) ],
|
||||||
ok.
|
ok.
|
||||||
@ -303,33 +310,35 @@ deserialize_functions(<<?FUNCTION:8, A, B, C, D, Rest/binary>>,
|
|||||||
, bb := 0
|
, bb := 0
|
||||||
, current_bb_code := []
|
, current_bb_code := []
|
||||||
} = Env) ->
|
} = Env) ->
|
||||||
{Sig, Rest2} = deserialize_signature(Rest),
|
{Attrs, Rest2} = deserialize_attributes(Rest),
|
||||||
Env2 = Env#{function => {<<A,B,C,D>>, Sig}},
|
{Sig, Rest3} = deserialize_signature(Rest2),
|
||||||
deserialize_functions(Rest2, Env2);
|
Env2 = Env#{function => {<<A,B,C,D>>, Attrs, Sig}},
|
||||||
|
deserialize_functions(Rest3, Env2);
|
||||||
deserialize_functions(<<?FUNCTION:8, A, B, C, D, Rest/binary>>,
|
deserialize_functions(<<?FUNCTION:8, A, B, C, D, Rest/binary>>,
|
||||||
#{ function := {F, Sig}
|
#{ function := {F, Attrs, Sig}
|
||||||
, bb := BB
|
, bb := BB
|
||||||
, current_bb_code := Code
|
, current_bb_code := Code
|
||||||
, code := Program
|
, code := Program
|
||||||
, functions := Funs} = Env) ->
|
, functions := Funs} = Env) ->
|
||||||
{NewSig, Rest2} = deserialize_signature(Rest),
|
{NewAttrs, Rest2} = deserialize_attributes(Rest),
|
||||||
|
{NewSig, Rest3} = deserialize_signature(Rest2),
|
||||||
case Code of
|
case Code of
|
||||||
[] ->
|
[] ->
|
||||||
Env2 = Env#{ bb => 0
|
Env2 = Env#{ bb => 0
|
||||||
, current_bb_code => []
|
, current_bb_code => []
|
||||||
, function => {<<A,B,C,D>>, NewSig}
|
, function => {<<A,B,C,D>>, NewAttrs, NewSig}
|
||||||
, code => #{}
|
, code => #{}
|
||||||
, functions => Funs#{F => {Sig, Program}}},
|
, functions => Funs#{F => {Attrs, Sig, Program}}},
|
||||||
deserialize_functions(Rest2, Env2);
|
deserialize_functions(Rest3, Env2);
|
||||||
_ ->
|
_ ->
|
||||||
Env2 = Env#{ bb => 0
|
Env2 = Env#{ bb => 0
|
||||||
, current_bb_code => []
|
, current_bb_code => []
|
||||||
, function => {<<A,B,C,D>>, NewSig}
|
, function => {<<A,B,C,D>>, NewAttrs, NewSig}
|
||||||
, code => #{}
|
, code => #{}
|
||||||
, functions =>
|
, functions =>
|
||||||
Funs#{F => {Sig,
|
Funs#{F => {Attrs, Sig,
|
||||||
Program#{ BB => lists:reverse(Code)}}}},
|
Program#{ BB => lists:reverse(Code)}}}},
|
||||||
deserialize_functions(Rest2, Env2)
|
deserialize_functions(Rest3, Env2)
|
||||||
end;
|
end;
|
||||||
deserialize_functions(<<_Op:8, _Rest/binary>>,
|
deserialize_functions(<<_Op:8, _Rest/binary>>,
|
||||||
#{ function := none }) ->
|
#{ function := none }) ->
|
||||||
@ -351,7 +360,7 @@ deserialize_functions(<<Op:8, Rest/binary>>,
|
|||||||
deserialize_functions(<<>>, #{ function := none
|
deserialize_functions(<<>>, #{ function := none
|
||||||
, functions := Funs}) ->
|
, functions := Funs}) ->
|
||||||
Funs;
|
Funs;
|
||||||
deserialize_functions(<<>>, #{ function := {F, Sig}
|
deserialize_functions(<<>>, #{ function := {F, Attrs, Sig}
|
||||||
, bb := BB
|
, bb := BB
|
||||||
, current_bb_code := Code
|
, current_bb_code := Code
|
||||||
, code := Program
|
, code := Program
|
||||||
@ -361,7 +370,7 @@ deserialize_functions(<<>>, #{ function := {F, Sig}
|
|||||||
[] -> Program;
|
[] -> Program;
|
||||||
_ -> Program#{ BB => lists:reverse(Code)}
|
_ -> Program#{ BB => lists:reverse(Code)}
|
||||||
end,
|
end,
|
||||||
Funs#{F => {Sig, FunctionCode}}.
|
Funs#{F => {Attrs, Sig, FunctionCode}}.
|
||||||
|
|
||||||
deserialize_op(Op, Rest, Code) ->
|
deserialize_op(Op, Rest, Code) ->
|
||||||
OpName = aeb_fate_opcodes:mnemonic(Op),
|
OpName = aeb_fate_opcodes:mnemonic(Op),
|
||||||
@ -399,6 +408,18 @@ deserialize_n_args(N, <<M7:2, M6:2, M5:2, M4:2, M3:2, M2:2, M1:2, M0:2,
|
|||||||
end
|
end
|
||||||
end, Rest, ArgMods).
|
end, Rest, ArgMods).
|
||||||
|
|
||||||
|
deserialize_attributes(Binary) ->
|
||||||
|
{AttrVal, Rest} = aeb_fate_encoding:deserialize_one(Binary),
|
||||||
|
Attrs = [ attr(AVal) || AVal <- attr_vals(1, AttrVal) ],
|
||||||
|
{lists:sort(Attrs), Rest}.
|
||||||
|
|
||||||
|
attr_vals(_, 0) -> [];
|
||||||
|
attr_vals(X, N) when N rem 2 == 0 -> attr_vals(X + 1, N div 2);
|
||||||
|
attr_vals(X, N) -> [X | attr_vals(X + 1, N div 2)].
|
||||||
|
|
||||||
|
attr(1) -> private;
|
||||||
|
attr(2) -> payable.
|
||||||
|
|
||||||
deserialize_signature(Binary) ->
|
deserialize_signature(Binary) ->
|
||||||
{{tuple, Args}, Rest} = aeb_fate_encoding:deserialize_type(Binary),
|
{{tuple, Args}, Rest} = aeb_fate_encoding:deserialize_type(Binary),
|
||||||
{RetType, Rest2} = aeb_fate_encoding:deserialize_type(Rest),
|
{RetType, Rest2} = aeb_fate_encoding:deserialize_type(Rest),
|
||||||
|
@ -176,6 +176,7 @@ ops_defs() ->
|
|||||||
, { 'IS_CONTRACT', 16#7b, false, false, true, 3, [a,a], is_contract, {address}, bool, "Arg0 := is Arg1 a contract"}
|
, { 'IS_CONTRACT', 16#7b, false, false, true, 3, [a,a], is_contract, {address}, bool, "Arg0 := is Arg1 a contract"}
|
||||||
, { 'CREATOR', 16#7c, false, true, true, 3, [a], contract_creator, {}, address, "Arg0 := contract creator"}
|
, { 'CREATOR', 16#7c, false, true, true, 3, [a], contract_creator, {}, address, "Arg0 := contract creator"}
|
||||||
, { 'ECRECOVER_SECP256K1', 16#7d, false, true, true, 1300, [a,a,a], ecrecover_secp256k1, {bytes, bytes}, bytes, "Arg0 := ecrecover_secp256k1(Hash, Signature)"}
|
, { 'ECRECOVER_SECP256K1', 16#7d, false, true, true, 1300, [a,a,a], ecrecover_secp256k1, {bytes, bytes}, bytes, "Arg0 := ecrecover_secp256k1(Hash, Signature)"}
|
||||||
|
, { 'IS_PAYABLE', 16#7e, false, false, true, 3, [a,a], is_payable, {address}, bool, "Arg0 := is Arg1 a payable address"}
|
||||||
|
|
||||||
, { 'DEACTIVATE', 16#fa, false, true, true, 3, [], deactivate, {}, none, "Mark the current contract for deactivation."}
|
, { 'DEACTIVATE', 16#fa, false, true, true, 3, [], deactivate, {}, none, "Mark the current contract for deactivation."}
|
||||||
, { 'ABORT', 16#fb, true, true, true, 3, [a], abort, {string}, none, "Abort execution (dont use all gas) with error message in Arg0."}
|
, { 'ABORT', 16#fb, true, true, true, 3, [a], abort, {string}, none, "Abort execution (dont use all gas) with error message in Arg0."}
|
||||||
|
@ -251,3 +251,9 @@ FUNCTION foo () : {tuple, []}
|
|||||||
AUTH_TX_HASH
|
AUTH_TX_HASH
|
||||||
|
|
||||||
CONTRACT_TO_ADDRESS @ct_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
|
CONTRACT_TO_ADDRESS @ct_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
|
||||||
|
|
||||||
|
IS_ORACLE @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
|
||||||
|
|
||||||
|
IS_CONTRACT @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
|
||||||
|
|
||||||
|
IS_PAYABLE @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
|
||||||
|
Loading…
x
Reference in New Issue
Block a user