Change return type of contract_call/N

This commit is contained in:
Craig Everett
2022-10-15 00:06:05 +09:00
parent 5925b6dedb
commit 9b2aff77d3
+96 -28
View File
@@ -736,14 +736,16 @@ read_aci(Path) ->
end. end.
-spec contract_call(CallerID, Nonce, AACI, ConID, Fun, Args) -> CallTX -spec contract_call(CallerID, Nonce, AACI, ConID, Fun, Args) -> Result
when CallerID :: binary(), when CallerID :: binary(),
Nonce :: pos_integer(), Nonce :: pos_integer(),
AACI :: map(), AACI :: map(),
ConID :: binary(), ConID :: binary(),
Fun :: string(), Fun :: string(),
Args :: [string()], Args :: [string()],
CallTX :: binary(). Result :: {ok, CallTX} | {error, Reason},
CallTX :: binary(),
Reason :: term().
%% @doc %% @doc
%% Form a contract call using hardcoded default values for `Gas', `GasPrice', `Fee', %% Form a contract call using hardcoded default values for `Gas', `GasPrice', `Fee',
%% and `Amount' to simplify the call (10 args is a bit much for normal calls!). %% and `Amount' to simplify the call (10 args is a bit much for normal calls!).
@@ -753,19 +755,19 @@ read_aci(Path) ->
%% For details on the meaning of these and other argument values see the doc comment %% For details on the meaning of these and other argument values see the doc comment
%% for contract_call/10. %% for contract_call/10.
contract_call(CallerID, Nonce, ACI, ConID, Fun, Args) -> contract_call(CallerID, Nonce, AACI, ConID, Fun, Args) ->
Gas = 20000, Gas = 20000,
GasPrice = min_gas_price(), GasPrice = min_gas_price(),
Fee = 200000000000000, Fee = 200000000000000,
Amount = 0, Amount = 0,
contract_call(CallerID, Nonce, contract_call(CallerID, Nonce,
Gas, GasPrice, Fee, Amount, Gas, GasPrice, Fee, Amount,
ACI, ConID, Fun, Args). AACI, ConID, Fun, Args).
-spec contract_call(CallerID, Nonce, -spec contract_call(CallerID, Nonce,
Gas, GasPrice, Fee, Amount, Gas, GasPrice, Fee, Amount,
AACI, ConID, Fun, Args) -> CallTX AACI, ConID, Fun, Args) -> Result
when CallerID :: binary(), when CallerID :: binary(),
Nonce :: pos_integer(), Nonce :: pos_integer(),
Gas :: pos_integer(), Gas :: pos_integer(),
@@ -776,7 +778,9 @@ contract_call(CallerID, Nonce, ACI, ConID, Fun, Args) ->
ConID :: binary(), ConID :: binary(),
Fun :: string(), Fun :: string(),
Args :: [string()], Args :: [string()],
CallTX :: binary(). Result :: {ok, CallTX} | {error, Reason},
CallTX :: binary(),
Reason :: term().
%% @doc %% @doc
%% Form a contract call using the supplied values. %% Form a contract call using the supplied values.
%% %%
@@ -885,14 +889,33 @@ contract_call(CallerID, Nonce, ACI, ConID, Fun, Args) ->
%% if you do not already have a copy, and can check the spec of a function before %% if you do not already have a copy, and can check the spec of a function before
%% trying to form a contract call. %% trying to form a contract call.
contract_call(CallerID, Nonce, Gas, GasPrice, Fee, Amount, ACI, ConID, Fun, Args) -> contract_call(CallerID, Nonce, Gas, GP, Fee, Amount, AACI, ConID, Fun, Args) ->
{ok, CallData} = encode_call_data(ACI, Fun, Args), case encode_call_data(AACI, Fun, Args) of
{ok, CD} -> contract_call2(CallerID, Nonce, Gas, GP, Fee, Amount, ConID, CD);
Error -> Error
end.
contract_call2(CallerID, Nonce, Gas, GasPrice, Fee, Amount, ConID, CallData) ->
try
{account_pubkey, PK} = aeser_api_encoder:decode(CallerID),
contract_call3(PK, Nonce, Gas, GasPrice, Fee, Amount, ConID, CallData)
catch
Error:Reason -> {Error, Reason}
end.
contract_call3(PK, Nonce, Gas, GasPrice, Fee, Amount, ConID, CallData) ->
try
{contract_pubkey, CK} = aeser_api_encoder:decode(ConID),
contract_call4(PK, Nonce, Gas, GasPrice, Fee, Amount, CK, CallData)
catch
Error:Reason -> {Error, Reason}
end.
contract_call4(PK, Nonce, Gas, GasPrice, Fee, Amount, CK, CallData) ->
ABI = 3, ABI = 3,
TTL = 0, TTL = 0,
CallVersion = 1, CallVersion = 1,
Type = contract_call_tx, Type = contract_call_tx,
{account_pubkey, PK} = aeser_api_encoder:decode(CallerID),
{contract_pubkey, CK} = aeser_api_encoder:decode(ConID),
Fields = Fields =
[{caller_id, {id, account, PK}}, [{caller_id, {id, account, PK}},
{nonce, Nonce}, {nonce, Nonce},
@@ -916,7 +939,11 @@ contract_call(CallerID, Nonce, Gas, GasPrice, Fee, Amount, ACI, ConID, Fun, Args
{gas_price, int}, {gas_price, int},
{call_data, binary}], {call_data, binary}],
TXB = aeser_chain_objects:serialize(Type, CallVersion, Template, Fields), TXB = aeser_chain_objects:serialize(Type, CallVersion, Template, Fields),
aeser_api_encoder:encode(transaction, TXB). try
{ok, aeser_api_encoder:encode(transaction, TXB)}
catch
error:Reason -> {error, Reason}
end.
-spec prepare_contract(File) -> {ok, AACI} | {error, Reason} -spec prepare_contract(File) -> {ok, AACI} | {error, Reason}
@@ -929,7 +956,7 @@ contract_call(CallerID, Nonce, Gas, GasPrice, Fee, Amount, ACI, ConID, Fun, Args
prepare_contract(File) -> prepare_contract(File) ->
case aeso_compiler:file(File, [{aci, json}]) of case aeso_compiler:file(File, [{aci, json}]) of
{ok, #{aci := ACI}} -> prepare_aaci(ACI); {ok, #{aci := ACI}} -> {ok, prepare_aaci(ACI)};
Error -> Error Error -> Error
end. end.
@@ -963,17 +990,39 @@ type(Name) -> binary_to_list(Name).
%type(#{<<"map">> := {K, V}} -> {map, type(K), type(V)}; %type(#{<<"map">> := {K, V}} -> {map, type(K), type(V)};
%type(<<"string">>) -> string; %type(<<"string">>) -> string;
coerce({integer, S}) -> coerce({{ArgName, integer}, S}, {Good, Broken}) ->
list_to_integer(S); try
coerce({address, S}) -> N = list_to_integer(S),
{account_pubkey, Key} = aeser_api_encoder:decode(S), {[N | Good], Broken}
{address, Key}; catch
coerce({contract, S}) -> error:Reason -> {Good, [{ArgName, Reason} | Broken]}
aeser_api_encoder:decode(S); end;
coerce({bool, S}) -> coerce({{ArgName, address}, S}, {Good, Broken}) ->
S; try
coerce({_, S}) -> case aeser_api_encoder:decode(S) of
S. {account_pubkey, Key} -> {[{address, Key} | Good], Broken};
_ -> {Good, [{ArgName, bad_pubkey} | Broken]}
end
catch
error:Reason -> {Good, [{ArgName, Reason} | Broken]}
end;
coerce({{ArgName, contract}, S}, {Good, Broken}) ->
try
case aeser_api_encoder:decode(S) of
R = {contract_bytearray, _} -> {[R | Good], Broken};
_ -> {Good, [{ArgName, bad_contract} | Broken]}
end
catch
error:Reason -> {Good, [{ArgName, Reason} | Broken]}
end;
coerce({{_, bool}, true}, {Good, Broken}) ->
{[true | Good], Broken};
coerce({{_, bool}, false}, {Good, Broken}) ->
{[false | Good], Broken};
coerce({{ArgName, bool}, _}, {Good, Broken}) ->
{Good, [{ArgName, not_bool} | Broken]};
coerce({_, S}, {Good, Broken}) ->
{[S | Good], Broken}.
-spec min_gas_price() -> integer(). -spec min_gas_price() -> integer().
@@ -993,11 +1042,30 @@ min_gas_price() ->
1000000000. 1000000000.
encode_call_data({aaci, _Name, FunDefs}, Fun, Args) -> encode_call_data({aaci, _, FunDefs}, Fun, Args) ->
ArgDef = maps:get(Fun, FunDefs), case maps:find(Fun, FunDefs) of
Binding = lists:zip([element(2, D) || D <- ArgDef], Args), {ok, ArgDef} -> encode_call_data2(ArgDef, Fun, Args);
Coerced = lists:map(fun coerce/1, Binding), error -> {error, bad_fun_name}
aeb_fate_abi:create_calldata(Fun, Coerced). end.
encode_call_data2(ArgDef, Fun, Args) ->
DefLength = length(ArgDef),
ArgLength = length(Args),
if
DefLength =:= ArgLength -> encode_call_data3(ArgDef, Fun, Args);
DefLength > ArgLength -> {error, too_few_args};
DefLength < ArgLength -> {error, too_many_args}
end.
encode_call_data3(ArgDef, Fun, Args) ->
Binding = lists:zip(ArgDef, Args),
case lists:foldl(fun coerce/2, {[], []}, Binding) of
{Coerced, []} ->
Reversed = lists:reverse(Coerced),
aeb_fate_abi:create_calldata(Fun, Reversed);
{_, Errors} ->
{error, {args, lists:reverse(Errors)}}
end.