Compare commits

..

9 Commits

Author SHA1 Message Date
SpiveeWorks
4e71d3215b Factor handling of different ACI typedef cases
A lot of this complexity was a consequence of trying to avoid redundant
extraction of the namespace's/contract's name, so on the other hand
letting it be redundant made all of the complexity kind of evaporate.
Add to that that we're now building a little deep list and then
flattening it, and this logic was able to get really neat in a way that
I couldn't work out a year ago.
2025-02-26 12:00:12 +11:00
SpiveeWorks
c27005c424 Rename 'flatten' and so on to 'annotate' 2025-02-26 12:00:06 +11:00
SpiveeWorks
ad7be7c8db Break up prepare_aaci logic
Now we convert the ACI into trees of opaque types, then flatten the tree
into a map and a list of function specs, and only then dereference the
types in the function specs down to our accelerated annotated types.
2025-02-26 11:59:58 +11:00
SpiveeWorks
7eb29827a6 Fix type substitution into variants and records
Variants were working by accident, since
{variant, [{"VariantName", [Element]}]} had a similar enough form to
the opaque types that would come from something like
`type1(type2(int))`, but records were not working, since they have a
different form. Now both are handled explicitly so that only the
intended forms of each are handled.
2025-02-26 11:59:52 +11:00
SpiveeWorks
4441f6ff37 Also prepare AACI for namespace types 2025-02-26 11:59:45 +11:00
SpiveeWorks
04311f9c99 Even more unit tests
Trying to test all the basic types that coerce covers, and a couple more
type parameter and nested cases.
2025-02-26 11:59:34 +11:00
SpiveeWorks
cf8970dad2 Add unit tests for some simple coercions 2025-02-26 11:59:33 +11:00
e53da36f2e Update deps and verup 2025-02-25 10:06:12 +09:00
5fdf1de4ef Adjustments 2025-02-25 10:00:14 +09:00
7 changed files with 68 additions and 68 deletions

View File

@ -3,6 +3,6 @@
{included_applications,[]}, {included_applications,[]},
{applications,[stdlib,kernel]}, {applications,[stdlib,kernel]},
{description,"Gajumaru interoperation library"}, {description,"Gajumaru interoperation library"},
{vsn,"0.2.0"}, {vsn,"0.3.0"},
{modules,[hakuzaru,hz,hz_fetcher,hz_man,hz_sup]}, {modules,[hakuzaru,hz,hz_fetcher,hz_man,hz_sup]},
{mod,{hakuzaru,[]}}]}. {mod,{hakuzaru,[]}}]}.

View File

@ -6,7 +6,7 @@
%%% @end %%% @end
-module(hakuzaru). -module(hakuzaru).
-vsn("0.2.0"). -vsn("0.3.0").
-author("Craig Everett <ceverett@tsuriai.jp>"). -author("Craig Everett <ceverett@tsuriai.jp>").
-copyright("Craig Everett <ceverett@tsuriai.jp>"). -copyright("Craig Everett <ceverett@tsuriai.jp>").
-license("GPL-3.0-or-later"). -license("GPL-3.0-or-later").

View File

@ -23,7 +23,7 @@
%%% @end %%% @end
-module(hz). -module(hz).
-vsn("0.2.0"). -vsn("0.3.0").
-author("Craig Everett <ceverett@tsuriai.jp>"). -author("Craig Everett <ceverett@tsuriai.jp>").
-copyright("Craig Everett <ceverett@tsuriai.jp>"). -copyright("Craig Everett <ceverett@tsuriai.jp>").
-license("GPL-3.0-or-later"). -license("GPL-3.0-or-later").
@ -48,7 +48,7 @@
dry_run/1, dry_run/2, dry_run/3, dry_run_map/1, dry_run/1, dry_run/2, dry_run/3, dry_run_map/1,
tx/1, tx_info/1, tx/1, tx_info/1,
post_tx/1, post_tx/1,
contract/1, contract_code/1, contract/1, contract_code/1, contract_source/1,
contract_poi/1, contract_poi/1,
name/1, name/1,
% channel/1, % channel/1,
@ -64,6 +64,7 @@
contract_create_built/3, contract_create_built/3,
contract_create/8, contract_create/8,
prepare_contract/1, prepare_contract/1,
prepare_aaci/1,
aaci_lookup_spec/2, aaci_lookup_spec/2,
contract_call/5, contract_call/5,
contract_call/6, contract_call/6,
@ -217,7 +218,7 @@
-spec network_id() -> NetworkID -spec network_id() -> NetworkID
when NetworkID :: string() | none. when NetworkID :: string() | none.
%% @doc %% @doc
%% Returns the AE network ID or the atom `none' if it is unset. %% Returns the network ID or the atom `none' if it is unset.
%% Checking this is not normally necessary, but if network ID assignment is dynamic %% Checking this is not normally necessary, but if network ID assignment is dynamic
%% in your system it may be necessary to call this before attempting to form %% in your system it may be necessary to call this before attempting to form
%% call data or perform other actions on chain that require a signature. %% call data or perform other actions on chain that require a signature.
@ -250,8 +251,8 @@ chain_nodes() ->
when List :: [chain_node()], when List :: [chain_node()],
Reason :: {invalid, [term()]}. Reason :: {invalid, [term()]}.
%% @doc %% @doc
%% Sets the AE nodes that are intended to be used as your interface to the AE peer %% Sets the nodes that are intended to be used as your interface to the peer
%% network. The common situation is that your project runs a non-mining AE node as %% network. The common situation is that your project runs a non-mining node as
%% part of your backend infrastructure. Typically one or two nodes is plenty, but %% part of your backend infrastructure. Typically one or two nodes is plenty, but
%% this may need to expand depending on how much query load your application generates. %% this may need to expand depending on how much query load your application generates.
%% The Hakuzaru manager will load balance by round-robin distribution. %% The Hakuzaru manager will load balance by round-robin distribution.
@ -305,7 +306,7 @@ timeout(MS) ->
%%% AE node JSON query interface functions %%% JSON query interface functions
-spec top_height() -> {ok, Height} | {error, Reason} -spec top_height() -> {ok, Height} | {error, Reason}
@ -657,13 +658,13 @@ dry_run_map(Map) ->
%% @doc %% @doc
%% Decode the "cb_XXXX" string that came out of a tx_info or dry_run, to %% Decode the "cb_XXXX" string that came out of a tx_info or dry_run, to
%% the Erlang representation of FATE objects used by aeb_fate_encoding. See %% the Erlang representation of FATE objects used by gmb_fate_encoding. See
%% decode_bytearray/2 for an alternative that provides simpler outputs based on %% decode_bytearray/2 for an alternative that provides simpler outputs based on
%% information provided by an AACI. %% information provided by an AACI.
decode_bytearray_fate(EncodedStr) -> decode_bytearray_fate(EncodedStr) ->
Encoded = unicode:characters_to_binary(EncodedStr), Encoded = unicode:characters_to_binary(EncodedStr),
{contract_bytearray, Binary} = aeser_api_encoder:decode(Encoded), {contract_bytearray, Binary} = gmser_api_encoder:decode(Encoded),
case Binary of case Binary of
<<>> -> {ok, none}; <<>> -> {ok, none};
<<"Out of gas">> -> {error, out_of_gas}; <<"Out of gas">> -> {error, out_of_gas};
@ -671,7 +672,7 @@ decode_bytearray_fate(EncodedStr) ->
% FIXME there may be other errors that are encoded directly into % FIXME there may be other errors that are encoded directly into
% the byte array. We could try and catch to at least return % the byte array. We could try and catch to at least return
% *something* for cases that we don't already detect. % *something* for cases that we don't already detect.
Object = aeb_fate_encoding:deserialize(Binary), Object = gmb_fate_encoding:deserialize(Binary),
{ok, Object} {ok, Object}
end. end.
@ -759,6 +760,21 @@ contract_code(ID) ->
end. end.
-spec contract_source(ID) -> {ok, Bytecode} | {error, Reason}
when ID :: contract_id(),
Bytecode :: contract_byte_array(),
Reason :: chain_error() | string().
%% @doc
%% Retrieve the code of a contract as represented on chain.
contract_source(ID) ->
case request(["/v3/contracts/", ID, "/source"]) of
{ok, #{"source" := Source}} -> {ok, Source};
{ok, #{"reason" := Reason}} -> {error, Reason};
Error -> Error
end.
-spec contract_poi(ID) -> {ok, Bytecode} | {error, Reason} -spec contract_poi(ID) -> {ok, Bytecode} | {error, Reason}
when ID :: contract_id(), when ID :: contract_id(),
Bytecode :: contract_byte_array(), Bytecode :: contract_byte_array(),
@ -953,7 +969,7 @@ contract_create(CreatorID, Path, InitArgs) ->
%% </li> %% </li>
%% <li> %% <li>
%% <b>GasPrice:</b> %% <b>GasPrice:</b>
%% This is a factor that is used calculate a value in aettos (the smallest unit of %% This is a factor that is used calculate a value in pucks (the smallest unit of
%% Gajumaru's currency value) for the gas consumed. In times of high contention %% Gajumaru's currency value) for the gas consumed. In times of high contention
%% in the mempool increasing the gas price increases the value of mining a given %% in the mempool increasing the gas price increases the value of mining a given
%% transaction, thus making miners more likely to prioritize the high value ones. %% transaction, thus making miners more likely to prioritize the high value ones.
@ -996,12 +1012,12 @@ contract_create(CreatorID, Nonce, Amount, TTL, Gas, GasPrice, Path, InitArgs) ->
{ok, Source} -> {ok, Source} ->
Dir = filename:dirname(Path), Dir = filename:dirname(Path),
{ok, CWD} = file:get_cwd(), {ok, CWD} = file:get_cwd(),
SrcDir = aeso_utils:canonical_dir(Path), SrcDir = so_utils:canonical_dir(Path),
Options = Options =
[{aci, json}, [{aci, json},
{src_file, Path}, {src_file, Path},
{src_dir, SrcDir}, {src_dir, SrcDir},
{include, {file_system, [CWD, aeso_utils:canonical_dir(Dir)]}}], {include, {file_system, [CWD, so_utils:canonical_dir(Dir)]}}],
contract_create2(CreatorID, Nonce, Amount, TTL, Gas, GasPrice, contract_create2(CreatorID, Nonce, Amount, TTL, Gas, GasPrice,
Source, Options, InitArgs); Source, Options, InitArgs);
Error -> Error ->
@ -1038,7 +1054,7 @@ contract_create_built(CreatorID, Compiled, InitArgs) ->
contract_create2(CreatorID, Nonce, Amount, TTL, Gas, GasPrice, Source, Options, InitArgs) -> contract_create2(CreatorID, Nonce, Amount, TTL, Gas, GasPrice, Source, Options, InitArgs) ->
case aeso_compiler:from_string(Source, Options) of case so_compiler:from_string(Source, Options) of
{ok, Compiled} -> {ok, Compiled} ->
contract_create3(CreatorID, Nonce, Amount, TTL, Gas, GasPrice, contract_create3(CreatorID, Nonce, Amount, TTL, Gas, GasPrice,
Compiled, InitArgs); Compiled, InitArgs);
@ -1059,22 +1075,22 @@ contract_create3(CreatorID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, InitArg
contract_create4(CreatorID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallData) -> contract_create4(CreatorID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallData) ->
PK = unicode:characters_to_binary(CreatorID), PK = unicode:characters_to_binary(CreatorID),
try try
{account_pubkey, OwnerID} = aeser_api_encoder:decode(PK), {account_pubkey, OwnerID} = gmser_api_encoder:decode(PK),
contract_create5(OwnerID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallData) contract_create5(OwnerID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallData)
catch catch
Error:Reason -> {Error, Reason} Error:Reason -> {Error, Reason}
end. end.
contract_create5(OwnerID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallData) -> contract_create5(OwnerID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallData) ->
Code = aeser_contract_code:serialize(Compiled), Code = gmser_contract_code:serialize(Compiled),
Source = maps:get(contract_source, Compiled, <<>>), Source = unicode:characters_to_binary(maps:get(contract_source, Compiled, <<>>)),
VM = 1, VM = 1,
ABI = 1, ABI = 1,
<<CTVersion:32>> = <<VM:16, ABI:16>>, <<CTVersion:32>> = <<VM:16, ABI:16>>,
ContractCreateVersion = 1, ContractCreateVersion = 1,
Type = contract_create_tx, Type = contract_create_tx,
Fields = Fields =
[{owner_id, aeser_id:create(account, OwnerID)}, [{owner_id, gmser_id:create(account, OwnerID)},
{nonce, Nonce}, {nonce, Nonce},
{code, Code}, {code, Code},
{source, Source}, {source, Source},
@ -1097,9 +1113,9 @@ contract_create5(OwnerID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallData)
{gas_price, int}, {gas_price, int},
{gas, int}, {gas, int},
{call_data, binary}], {call_data, binary}],
TXB = aeser_chain_objects:serialize(Type, ContractCreateVersion, Template, Fields), TXB = gmser_chain_objects:serialize(Type, ContractCreateVersion, Template, Fields),
try try
{ok, aeser_api_encoder:encode(transaction, TXB)} {ok, gmser_api_encoder:encode(transaction, TXB)}
catch catch
error:Reason -> {error, Reason} error:Reason -> {error, Reason}
end. end.
@ -1111,14 +1127,11 @@ contract_create5(OwnerID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallData)
ACI :: tuple(), % FIXME: Change to correct Sophia record ACI :: tuple(), % FIXME: Change to correct Sophia record
Reason :: file:posix() | bad_aci. Reason :: file:posix() | bad_aci.
%% @doc %% @doc
%% This function reads the contents of an .aci file produced by AEL (the Gajumaru %% This function reads the contents of an .aci file.
%% Launcher). ACI data is required for the contract call encoder to function properly. %% ACI data is required for the contract call encoder to function properly.
%% ACI data is can be generated and stored in JSON data, and the Sophia CLI tool %% ACI data is can be generated and stored in JSON data, and the Sophia CLI tool
%% can perform this action. Unfortunately, JSON is not the way that ACI data is %% can perform this action. Unfortunately, JSON is not the way that ACI data is
%% represented internally, and here we need the actual native representation. For %% represented internally, and here we need the actual native representation.
%% that reason Gajumaru's GUI launcher (AEL) has a "Developer's Workbench" tool
%% that can produce an .aci file from a contract's source code and store it in the
%% native Erlang format.
%% %%
%% ACI encding/decoding and contract call encoding is significantly complex enough that %% ACI encding/decoding and contract call encoding is significantly complex enough that
%% this provides for a pretty large savings in complexity for this library, dramatically %% this provides for a pretty large savings in complexity for this library, dramatically
@ -1272,7 +1285,7 @@ contract_call(CallerID, Gas, AACI, ConID, Fun, Args) ->
%% </li> %% </li>
%% <li> %% <li>
%% <b>GasPrice:</b> %% <b>GasPrice:</b>
%% This is a factor that is used calculate a value in aettos (the smallest unit of %% This is a factor that is used calculate a value in pucks (the smallest unit of
%% Gajumaru's currency value) for the gas consumed. In times of high contention %% Gajumaru's currency value) for the gas consumed. In times of high contention
%% in the mempool increasing the gas price increases the value of mining a given %% in the mempool increasing the gas price increases the value of mining a given
%% transaction, thus making miners more likely to prioritize the high value ones. %% transaction, thus making miners more likely to prioritize the high value ones.
@ -1330,7 +1343,7 @@ contract_call(CallerID, Nonce, Gas, GP, Amount, TTL, AACI, ConID, Fun, Args) ->
contract_call2(CallerID, Nonce, Gas, GasPrice, Amount, TTL, ConID, CallData) -> contract_call2(CallerID, Nonce, Gas, GasPrice, Amount, TTL, ConID, CallData) ->
CallerBin = unicode:characters_to_binary(CallerID), CallerBin = unicode:characters_to_binary(CallerID),
try try
{account_pubkey, PK} = aeser_api_encoder:decode(CallerBin), {account_pubkey, PK} = gmser_api_encoder:decode(CallerBin),
contract_call3(PK, Nonce, Gas, GasPrice, Amount, TTL, ConID, CallData) contract_call3(PK, Nonce, Gas, GasPrice, Amount, TTL, ConID, CallData)
catch catch
Error:Reason -> {Error, Reason} Error:Reason -> {Error, Reason}
@ -1339,7 +1352,7 @@ contract_call2(CallerID, Nonce, Gas, GasPrice, Amount, TTL, ConID, CallData) ->
contract_call3(PK, Nonce, Gas, GasPrice, Amount, TTL, ConID, CallData) -> contract_call3(PK, Nonce, Gas, GasPrice, Amount, TTL, ConID, CallData) ->
ConBin = unicode:characters_to_binary(ConID), ConBin = unicode:characters_to_binary(ConID),
try try
{contract_pubkey, CK} = aeser_api_encoder:decode(ConBin), {contract_pubkey, CK} = gmser_api_encoder:decode(ConBin),
contract_call4(PK, Nonce, Gas, GasPrice, Amount, TTL, CK, CallData) contract_call4(PK, Nonce, Gas, GasPrice, Amount, TTL, CK, CallData)
catch catch
Error:Reason -> {Error, Reason} Error:Reason -> {Error, Reason}
@ -1350,9 +1363,9 @@ contract_call4(PK, Nonce, Gas, GasPrice, Amount, TTL, CK, CallData) ->
CallVersion = 1, CallVersion = 1,
Type = contract_call_tx, Type = contract_call_tx,
Fields = Fields =
[{caller_id, aeser_id:create(account, PK)}, [{caller_id, gmser_id:create(account, PK)},
{nonce, Nonce}, {nonce, Nonce},
{contract_id, aeser_id:create(contract, CK)}, {contract_id, gmser_id:create(contract, CK)},
{abi_version, ABI}, {abi_version, ABI},
{ttl, TTL}, {ttl, TTL},
{amount, Amount}, {amount, Amount},
@ -1369,9 +1382,9 @@ contract_call4(PK, Nonce, Gas, GasPrice, Amount, TTL, CK, CallData) ->
{gas_price, int}, {gas_price, int},
{gas, int}, {gas, int},
{call_data, binary}], {call_data, binary}],
TXB = aeser_chain_objects:serialize(Type, CallVersion, Template, Fields), TXB = gmser_chain_objects:serialize(Type, CallVersion, Template, Fields),
try try
{ok, aeser_api_encoder:encode(transaction, TXB)} {ok, gmser_api_encoder:encode(transaction, TXB)}
catch catch
error:Reason -> {error, Reason} error:Reason -> {error, Reason}
end. end.
@ -1386,7 +1399,7 @@ contract_call4(PK, Nonce, Gas, GasPrice, Amount, TTL, CK, CallData) ->
%% of calldata %% of calldata
prepare_contract(File) -> prepare_contract(File) ->
case aeso_compiler:file(File, [{aci, json}]) of case so_compiler:file(File, [{aci, json}]) of
{ok, #{aci := ACI}} -> {ok, prepare_aaci(ACI)}; {ok, #{aci := ACI}} -> {ok, prepare_aaci(ACI)};
Error -> Error Error -> Error
end. end.
@ -1522,7 +1535,7 @@ opaque_type_name(Name) -> binary_to_list(Name).
% Type preparation has two goals. First, we need a data structure that can be % Type preparation has two goals. First, we need a data structure that can be
% traversed quickly, to take sophia-esque erlang expressions and turn them into % traversed quickly, to take sophia-esque erlang expressions and turn them into
% fate-esque erlang expressions that aebytecode can serialize. Second, we need % fate-esque erlang expressions that gmbytecode can serialize. Second, we need
% partially substituted names, so that error messages can be generated for why % partially substituted names, so that error messages can be generated for why
% "foobar" is not valid as the third field of a `bazquux`, because the third % "foobar" is not valid as the third field of a `bazquux`, because the third
% field is supposed to be `option(integer)`, not `string`. % field is supposed to be `option(integer)`, not `string`.
@ -1536,7 +1549,7 @@ opaque_type_name(Name) -> binary_to_list(Name).
% {record, [{Name, Type}]} expression that can be used in actual Sophia->FATE % {record, [{Name, Type}]} expression that can be used in actual Sophia->FATE
% coercion. The type sub-expressions in these dereferenced types will each be % coercion. The type sub-expressions in these dereferenced types will each be
% fully annotated as well, i.e. they will each contain *all three* of the above % fully annotated as well, i.e. they will each contain *all three* of the above
% representations, so that coercion of subexpressions remains fast and % representations, so that coercion of subexpressions remains fast AND
% informative. % informative.
% %
% In a lot of cases the opaque type given will already be normalized, in which % In a lot of cases the opaque type given will already be normalized, in which
@ -1774,7 +1787,7 @@ coerce({O, N, integer}, S, to_fate) when is_list(S) ->
end; end;
coerce({O, N, address}, S, to_fate) -> coerce({O, N, address}, S, to_fate) ->
try try
case aeser_api_encoder:decode(unicode:characters_to_binary(S)) of case gmser_api_encoder:decode(unicode:characters_to_binary(S)) of
{account_pubkey, Key} -> {ok, {address, Key}}; {account_pubkey, Key} -> {ok, {address, Key}};
_ -> single_error({invalid, O, N, S}) _ -> single_error({invalid, O, N, S})
end end
@ -1782,11 +1795,11 @@ coerce({O, N, address}, S, to_fate) ->
error:_ -> single_error({invalid, O, N, S}) error:_ -> single_error({invalid, O, N, S})
end; end;
coerce({_, _, address}, {address, Bin}, from_fate) -> coerce({_, _, address}, {address, Bin}, from_fate) ->
Address = aeser_api_encoder:encode(account_pubkey, Bin), Address = gmser_api_encoder:encode(account_pubkey, Bin),
{ok, unicode:characters_to_list(Address)}; {ok, unicode:characters_to_list(Address)};
coerce({O, N, contract}, S, to_fate) -> coerce({O, N, contract}, S, to_fate) ->
try try
case aeser_api_encoder:decode(unicode:characters_to_binary(S)) of case gmser_api_encoder:decode(unicode:characters_to_binary(S)) of
{contract_pubkey, Key} -> {ok, {contract, Key}}; {contract_pubkey, Key} -> {ok, {contract, Key}};
_ -> single_error({invalid, O, N, S}) _ -> single_error({invalid, O, N, S})
end end
@ -1794,7 +1807,7 @@ coerce({O, N, contract}, S, to_fate) ->
error:_ -> single_error({invalid, O, N, S}) error:_ -> single_error({invalid, O, N, S})
end; end;
coerce({_, _, contract}, {contract, Bin}, from_fate) -> coerce({_, _, contract}, {contract, Bin}, from_fate) ->
Address = aeser_api_encoder:encode(contract_pubkey, Bin), Address = gmser_api_encoder:encode(contract_pubkey, Bin),
{ok, unicode:characters_to_list(Address)}; {ok, unicode:characters_to_list(Address)};
coerce({_, _, boolean}, true, _) -> coerce({_, _, boolean}, true, _) ->
{ok, true}; {ok, true};
@ -2061,8 +2074,7 @@ aaci_lookup_spec({aaci, _, FunDefs, _}, Fun) ->
%% @doc %% @doc
%% This function always returns 1,000,000,000 in the current version. %% This function always returns 1,000,000,000 in the current version.
%% %%
%% This is the minimum gas price returned by aec_tx_pool:minimum_miner_gas_price(), %% This is the minimum gas price returned by aec_tx_pool:minimum_miner_gas_price()
%% (the default set in aeternity_config_schema.json).
%% %%
%% Surely there can be some more nuance to this, but until a "gas station" type %% Surely there can be some more nuance to this, but until a "gas station" type
%% market/chain survey service exists we will use this naive value as a default %% market/chain survey service exists we will use this naive value as a default
@ -2076,16 +2088,10 @@ min_gas_price() ->
-spec min_gas() -> integer(). -spec min_gas() -> integer().
%% @doc %% @doc
%% This function always returns 20,000 in the current version. %% This function always returns 200,000 in the current version.
%%
%% There is no actual minimum gas price, but this figure provides a lower limit toward
%% successful completion of general contract calls while not too severely limiting the
%% number of TXs that may appear in a single microblock based on the per-block gas
%% maximum (6,000,000 / 20,000 = 300 TXs in a microblock -- which at the moment seems
%% like plenty).
min_gas() -> min_gas() ->
20000. 200000.
encode_call_data({aaci, _ContractName, FunDefs, _TypeDefs}, Fun, Args) -> encode_call_data({aaci, _ContractName, FunDefs, _TypeDefs}, Fun, Args) ->
@ -2096,7 +2102,7 @@ encode_call_data({aaci, _ContractName, FunDefs, _TypeDefs}, Fun, Args) ->
encode_call_data2(ArgDef, Fun, Args) -> encode_call_data2(ArgDef, Fun, Args) ->
case coerce_bindings(ArgDef, Args, to_fate) of case coerce_bindings(ArgDef, Args, to_fate) of
{ok, Coerced} -> aeb_fate_abi:create_calldata(Fun, Coerced); {ok, Coerced} -> gmb_fate_abi:create_calldata(Fun, Coerced);
Errors -> Errors Errors -> Errors
end. end.
@ -2116,7 +2122,7 @@ encode_call_data2(ArgDef, Fun, Args) ->
%% check failed before verification was able to pass or fail (bad key encoding or similar). %% check failed before verification was able to pass or fail (bad key encoding or similar).
verify_signature(Sig, Message, PubKey) -> verify_signature(Sig, Message, PubKey) ->
case aeser_api_encoder:decode(PubKey) of case gmser_api_encoder:decode(PubKey) of
{account_pubkey, PK} -> verify_signature2(Sig, Message, PK); {account_pubkey, PK} -> verify_signature2(Sig, Message, PK);
Other -> {error, {bad_key, Other}} Other -> {error, {bad_key, Other}}
end. end.
@ -2126,13 +2132,7 @@ verify_signature2(Sig, Message, PK) ->
% the hash is what gets signed in order to protect % the hash is what gets signed in order to protect
% the user from accidentally signing a transaction disguised as a message. % the user from accidentally signing a transaction disguised as a message.
% %
% Salt the message then hash with blake2b. See: % Salt the message then hash with blake2b.
% 1. Erlang Blake2 blake2b/2 function:
% https://gitlab.com/ioecs/eblake2/blob/60a079f00d72d1bfcc25de8e6996d28f912db3fd/src/eblake2.erl#L23-L25
% 2. SDK salting step:
% https://gitlab.com/ioecs/aepp-sdk-js/blob/370f1e30064ad0239ba59931908d9aba0a2e86b6/src/utils/crypto.ts#L171-L175
% 3. SDK hashing:
% https://gitlab.com/ioecs/aepp-sdk-js/blob/370f1e30064ad0239ba59931908d9aba0a2e86b6/src/utils/crypto.ts#L83-L85
Prefix = <<"Gajumaru Signed Message:\n">>, Prefix = <<"Gajumaru Signed Message:\n">>,
{ok, PSize} = vencode(byte_size(Prefix)), {ok, PSize} = vencode(byte_size(Prefix)),
{ok, MSize} = vencode(byte_size(Message)), {ok, MSize} = vencode(byte_size(Message)),
@ -2283,7 +2283,7 @@ coerce_record_test() ->
%%% Complex AACI paramter and namespace tests %%% Complex AACI paramter and namespace tests
aaci_from_string(String) -> aaci_from_string(String) ->
case aeso_compiler:from_string(String, [{aci, json}]) of case so_compiler:from_string(String, [{aci, json}]) of
{ok, #{aci := ACI}} -> {ok, prepare_aaci(ACI)}; {ok, #{aci := ACI}} -> {ok, prepare_aaci(ACI)};
Error -> Error Error -> Error
end. end.

View File

@ -1,5 +1,5 @@
-module(hz_fetcher). -module(hz_fetcher).
-vsn("0.2.0"). -vsn("0.3.0").
-author("Craig Everett <ceverett@tsuriai.jp>"). -author("Craig Everett <ceverett@tsuriai.jp>").
-copyright("Craig Everett <ceverett@tsuriai.jp>"). -copyright("Craig Everett <ceverett@tsuriai.jp>").
-license("MIT"). -license("MIT").

View File

@ -9,7 +9,7 @@
%%% @end %%% @end
-module(hz_man). -module(hz_man).
-vsn("0.2.0"). -vsn("0.3.0").
-behavior(gen_server). -behavior(gen_server).
-author("Craig Everett <ceverett@tsuriai.jp>"). -author("Craig Everett <ceverett@tsuriai.jp>").
-copyright("Craig Everett <ceverett@tsuriai.jp>"). -copyright("Craig Everett <ceverett@tsuriai.jp>").

View File

@ -9,7 +9,7 @@
%%% @end %%% @end
-module(hz_sup). -module(hz_sup).
-vsn("0.2.0"). -vsn("0.3.0").
-behaviour(supervisor). -behaviour(supervisor).
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").

View File

@ -2,15 +2,15 @@
{type,app}. {type,app}.
{modules,[]}. {modules,[]}.
{prefix,"hz"}. {prefix,"hz"}.
{author,"Craig Everett"}.
{desc,"Gajumaru interoperation library"}. {desc,"Gajumaru interoperation library"}.
{package_id,{"otpr","hakuzaru",{0,2,0}}}. {author,"Craig Everett"}.
{deps,[{"otpr","gmbytecode",{3,4,1}}, {package_id,{"otpr","hakuzaru",{0,3,0}}}.
{deps,[{"otpr","sophia",{8,0,1}},
{"otpr","gmbytecode",{3,4,1}},
{"otpr","gmserialization",{0,1,2}}, {"otpr","gmserialization",{0,1,2}},
{"otpr","base58",{0,1,1}}, {"otpr","base58",{0,1,1}},
{"otpr","eblake2",{1,0,1}}, {"otpr","eblake2",{1,0,1}},
{"otpr","ec_utils",{1,0,0}}, {"otpr","ec_utils",{1,0,0}},
{"otpr","aesophia",{7,1,2}},
{"otpr","zj",{1,1,0}}, {"otpr","zj",{1,1,0}},
{"otpr","getopt",{1,0,2}}]}. {"otpr","getopt",{1,0,2}}]}.
{key_name,none}. {key_name,none}.