From 5fdf1de4effba205625271cce8e496647385b0ab Mon Sep 17 00:00:00 2001 From: Craig Everett Date: Tue, 25 Feb 2025 10:00:14 +0900 Subject: [PATCH] Adjustments --- src/hz.erl | 112 ++++++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/src/hz.erl b/src/hz.erl index f48f4dd..9745a25 100644 --- a/src/hz.erl +++ b/src/hz.erl @@ -48,7 +48,7 @@ dry_run/1, dry_run/2, dry_run/3, dry_run_map/1, tx/1, tx_info/1, post_tx/1, - contract/1, contract_code/1, + contract/1, contract_code/1, contract_source/1, contract_poi/1, name/1, % channel/1, @@ -64,6 +64,7 @@ contract_create_built/3, contract_create/8, prepare_contract/1, + prepare_aaci/1, aaci_lookup_spec/2, contract_call/5, contract_call/6, @@ -216,7 +217,7 @@ -spec network_id() -> NetworkID when NetworkID :: string() | none. %% @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 %% 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. @@ -249,8 +250,8 @@ chain_nodes() -> when List :: [chain_node()], Reason :: {invalid, [term()]}. %% @doc -%% Sets the AE nodes that are intended to be used as your interface to the AE peer -%% network. The common situation is that your project runs a non-mining AE node as +%% 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 node as %% 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. %% The Hakuzaru manager will load balance by round-robin distribution. @@ -304,7 +305,7 @@ timeout(MS) -> -%%% AE node JSON query interface functions +%%% JSON query interface functions -spec top_height() -> {ok, Height} | {error, Reason} @@ -656,13 +657,13 @@ dry_run_map(Map) -> %% @doc %% 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 %% information provided by an AACI. decode_bytearray_fate(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 <<>> -> {ok, none}; <<"Out of gas">> -> {error, out_of_gas}; @@ -670,7 +671,7 @@ decode_bytearray_fate(EncodedStr) -> % FIXME there may be other errors that are encoded directly into % the byte array. We could try and catch to at least return % *something* for cases that we don't already detect. - Object = aeb_fate_encoding:deserialize(Binary), + Object = gmb_fate_encoding:deserialize(Binary), {ok, Object} end. @@ -758,6 +759,21 @@ contract_code(ID) -> 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} when ID :: contract_id(), Bytecode :: contract_byte_array(), @@ -952,7 +968,7 @@ contract_create(CreatorID, Path, InitArgs) -> %% %%
  • %% GasPrice: -%% 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 %% 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. @@ -995,12 +1011,12 @@ contract_create(CreatorID, Nonce, Amount, TTL, Gas, GasPrice, Path, InitArgs) -> {ok, Source} -> Dir = filename:dirname(Path), {ok, CWD} = file:get_cwd(), - SrcDir = aeso_utils:canonical_dir(Path), + SrcDir = so_utils:canonical_dir(Path), Options = [{aci, json}, {src_file, Path}, {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, Source, Options, InitArgs); Error -> @@ -1037,7 +1053,7 @@ contract_create_built(CreatorID, Compiled, 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} -> contract_create3(CreatorID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, InitArgs); @@ -1058,22 +1074,22 @@ contract_create3(CreatorID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, InitArg contract_create4(CreatorID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallData) -> PK = unicode:characters_to_binary(CreatorID), 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) catch Error:Reason -> {Error, Reason} end. contract_create5(OwnerID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallData) -> - Code = aeser_contract_code:serialize(Compiled), - Source = maps:get(contract_source, Compiled, <<>>), + Code = gmser_contract_code:serialize(Compiled), + Source = unicode:characters_to_binary(maps:get(contract_source, Compiled, <<>>)), VM = 1, ABI = 1, <> = <>, ContractCreateVersion = 1, Type = contract_create_tx, Fields = - [{owner_id, aeser_id:create(account, OwnerID)}, + [{owner_id, gmser_id:create(account, OwnerID)}, {nonce, Nonce}, {code, Code}, {source, Source}, @@ -1096,9 +1112,9 @@ contract_create5(OwnerID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallData) {gas_price, int}, {gas, int}, {call_data, binary}], - TXB = aeser_chain_objects:serialize(Type, ContractCreateVersion, Template, Fields), + TXB = gmser_chain_objects:serialize(Type, ContractCreateVersion, Template, Fields), try - {ok, aeser_api_encoder:encode(transaction, TXB)} + {ok, gmser_api_encoder:encode(transaction, TXB)} catch error:Reason -> {error, Reason} end. @@ -1110,14 +1126,11 @@ contract_create5(OwnerID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallData) ACI :: tuple(), % FIXME: Change to correct Sophia record Reason :: file:posix() | bad_aci. %% @doc -%% This function reads the contents of an .aci file produced by AEL (the Gajumaru -%% Launcher). ACI data is required for the contract call encoder to function properly. +%% This function reads the contents of an .aci file. +%% 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 %% 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 -%% 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. +%% represented internally, and here we need the actual native representation. %% %% 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 @@ -1271,7 +1284,7 @@ contract_call(CallerID, Gas, AACI, ConID, Fun, Args) -> %%
  • %%
  • %% GasPrice: -%% 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 %% 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. @@ -1329,7 +1342,7 @@ contract_call(CallerID, Nonce, Gas, GP, Amount, TTL, AACI, ConID, Fun, Args) -> contract_call2(CallerID, Nonce, Gas, GasPrice, Amount, TTL, ConID, CallData) -> CallerBin = unicode:characters_to_binary(CallerID), 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) catch Error:Reason -> {Error, Reason} @@ -1338,7 +1351,7 @@ contract_call2(CallerID, Nonce, Gas, GasPrice, Amount, TTL, ConID, CallData) -> contract_call3(PK, Nonce, Gas, GasPrice, Amount, TTL, ConID, CallData) -> ConBin = unicode:characters_to_binary(ConID), 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) catch Error:Reason -> {Error, Reason} @@ -1349,9 +1362,9 @@ contract_call4(PK, Nonce, Gas, GasPrice, Amount, TTL, CK, CallData) -> CallVersion = 1, Type = contract_call_tx, Fields = - [{caller_id, aeser_id:create(account, PK)}, + [{caller_id, gmser_id:create(account, PK)}, {nonce, Nonce}, - {contract_id, aeser_id:create(contract, CK)}, + {contract_id, gmser_id:create(contract, CK)}, {abi_version, ABI}, {ttl, TTL}, {amount, Amount}, @@ -1368,9 +1381,9 @@ contract_call4(PK, Nonce, Gas, GasPrice, Amount, TTL, CK, CallData) -> {gas_price, int}, {gas, int}, {call_data, binary}], - TXB = aeser_chain_objects:serialize(Type, CallVersion, Template, Fields), + TXB = gmser_chain_objects:serialize(Type, CallVersion, Template, Fields), try - {ok, aeser_api_encoder:encode(transaction, TXB)} + {ok, gmser_api_encoder:encode(transaction, TXB)} catch error:Reason -> {error, Reason} end. @@ -1385,7 +1398,7 @@ contract_call4(PK, Nonce, Gas, GasPrice, Amount, TTL, CK, CallData) -> %% of calldata 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)}; Error -> Error end. @@ -1453,7 +1466,7 @@ simplify_args(#{name := NameBin, type := TypeDef}, Types) -> % 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 -% 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 % "foobar" is not valid as the third field of a `bazquux`, because the third % field is supposed to be `option(integer)`, not `string`. @@ -1708,7 +1721,7 @@ coerce({O, N, integer}, S, to_fate) when is_list(S) -> end; coerce({O, N, address}, S, to_fate) -> 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}}; _ -> single_error({invalid, O, N, S}) end @@ -1716,11 +1729,11 @@ coerce({O, N, address}, S, to_fate) -> error:_ -> single_error({invalid, O, N, S}) end; 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)}; coerce({O, N, contract}, S, to_fate) -> 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}}; _ -> single_error({invalid, O, N, S}) end @@ -1728,7 +1741,7 @@ coerce({O, N, contract}, S, to_fate) -> error:_ -> single_error({invalid, O, N, S}) end; 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)}; coerce({_, _, boolean}, true, _) -> {ok, true}; @@ -1995,8 +2008,7 @@ aaci_lookup_spec({aaci, _, FunDefs, _}, Fun) -> %% @doc %% 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(), -%% (the default set in aeternity_config_schema.json). +%% This is the minimum gas price returned by aec_tx_pool:minimum_miner_gas_price() %% %% 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 @@ -2010,16 +2022,10 @@ min_gas_price() -> -spec min_gas() -> integer(). %% @doc -%% This function always returns 20,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). +%% This function always returns 200,000 in the current version. min_gas() -> - 20000. + 200000. encode_call_data({aaci, _ContractName, FunDefs, _TypeDefs}, Fun, Args) -> @@ -2030,7 +2036,7 @@ encode_call_data({aaci, _ContractName, FunDefs, _TypeDefs}, Fun, Args) -> encode_call_data2(ArgDef, Fun, Args) -> 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 end. @@ -2050,7 +2056,7 @@ encode_call_data2(ArgDef, Fun, Args) -> %% check failed before verification was able to pass or fail (bad key encoding or similar). 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); Other -> {error, {bad_key, Other}} end. @@ -2060,13 +2066,7 @@ verify_signature2(Sig, Message, PK) -> % the hash is what gets signed in order to protect % the user from accidentally signing a transaction disguised as a message. % - % Salt the message then hash with blake2b. See: - % 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 + % Salt the message then hash with blake2b. Prefix = <<"Gajumaru Signed Message:\n">>, {ok, PSize} = vencode(byte_size(Prefix)), {ok, MSize} = vencode(byte_size(Message)),