Move sign, spend, account decode, etc to lib

This commit is contained in:
Craig Everett 2025-03-05 22:29:30 +09:00
parent b6cb79d81e
commit 10e3a0b1c3
2 changed files with 177 additions and 35 deletions

View File

@ -29,13 +29,13 @@
-license("GPL-3.0-or-later").
% Get/Set admin functions.
-export([network_id/0, network_id/1,
chain_nodes/0, chain_nodes/1,
-export([chain_nodes/0, chain_nodes/1,
tls/0, tls/1,
timeout/0, timeout/1]).
% Node JSON query interface functions
-export([top_height/0, top_block/0,
-export([network_id/0,
top_height/0, top_block/0,
kb_current/0, kb_current_hash/0, kb_current_height/0,
kb_pending/0,
kb_by_hash/1, kb_by_height/1,
@ -71,6 +71,8 @@
contract_call/6,
contract_call/10,
decode_bytearray_fate/1, decode_bytearray/2,
spend/5, spend/10,
sign_tx/2, sign_tx/3,
verify_signature/3]).
@ -225,17 +227,10 @@
%% call data or perform other actions on chain that require a signature.
network_id() ->
hz_man:network_id().
-spec network_id(Identifier) -> ok | {error, Reason}
when Identifier :: string() | none,
Reason :: not_started.
%% @doc
%% Sets the network ID, or returns `not_started' if the service is not yet started.
network_id(Identifier) ->
hz_man:network_id(Identifier).
case status() of
{ok, #{"network_id" := NetworkID}} -> {ok, NetworkID};
Error -> Error
end.
-spec chain_nodes() -> [chain_node()].
@ -2110,6 +2105,172 @@ encode_call_data2(ArgDef, Fun, Args) ->
end.
sign_tx(Unsigned, SecKey) ->
case network_id() of
{ok, NetworkID} -> sign_tx(Unsigned, SecKey, NetworkID);
Error -> Error
end.
sign_tx(Unsigned, SecKey, MNetworkID) ->
UnsignedBin = unicode:characters_to_binary(Unsigned),
NetworkID = unicode:characters_to_binary(MNetworkID),
{ok, TX_Data} = gmser_api_encoder:safe_decode(transaction, UnsignedBin),
{ok, Hash} = eblake2:blake2b(32, TX_Data),
NetworkHash = <<NetworkID/binary, Hash/binary>>,
Signature = ecu_eddsa:sign_detached(NetworkHash, SecKey),
SigTxType = signed_tx,
SigTxVsn = 1,
SigTemplate =
[{signatures, [binary]},
{transaction, binary}],
TX =
[{signatures, [Signature]},
{transaction, TX_Data}],
SignedTX = gmser_chain_objects:serialize(SigTxType, SigTxVsn, SigTemplate, TX),
gmser_api_encoder:encode(transaction, SignedTX).
spend(SenderID, SecKey, ReceipientID, Amount, Payload) ->
case status() of
{ok, #{"top_block_height" := Height, "network_id" := NetworkID}} ->
spend(SenderID, SecKey, ReceipientID, Amount, Payload, Height, NetworkID);
Error ->
Error
end.
spend(SenderID, SecKey, RecipientID, Amount, Payload, Height, NetworkID) ->
case next_nonce(SenderID) of
{ok, Nonce} ->
{ok, Height} = top_height(),
TTL = Height + 262980,
Gas = 20000,
GasPrice = min_gas_price(),
spend(SenderID,
SecKey,
RecipientID,
Amount,
GasPrice,
Gas,
TTL,
Nonce,
Payload,
NetworkID);
Error ->
Error
end.
spend(SenderID,
SecKey,
RecipientID,
Amount,
GasPrice,
Gas,
TTL,
Nonce,
Payload,
NetworkID) ->
case decode_account_id(unicode:characters_to_binary(SenderID)) of
{ok, DSenderID} ->
spend2(gmser_id:create(account, DSenderID),
SecKey,
RecipientID,
Amount,
GasPrice,
Gas,
TTL,
Nonce,
Payload,
NetworkID);
Error ->
Error
end.
spend2(DSenderID,
SecKey,
RecipientID,
Amount,
GasPrice,
Gas,
TTL,
Nonce,
Payload,
NetworkID) ->
case decode_account_id(unicode:characters_to_binary(RecipientID)) of
{ok, DRecipientID} ->
spend3(DSenderID,
SecKey,
gmser_id:create(account, DRecipientID),
Amount,
GasPrice,
Gas,
TTL,
Nonce,
Payload,
NetworkID);
Error ->
Error
end.
decode_account_id(S) when is_list(S) ->
decode_account_id(list_to_binary(S));
decode_account_id(B) ->
try
{account_pubkey, PK} = gmser_api_encoder:decode(B),
{ok, PK}
catch
E:R -> {E, R}
end.
spend3(DSenderID,
SecKey,
DRecipientID,
Amount,
GasPrice,
Gas,
TTL,
Nonce,
Payload,
MNetworkID) ->
NetworkID = unicode:characters_to_binary(MNetworkID),
Type = spend_tx,
Vsn = 1,
Fields =
[{sender_id, DSenderID},
{recipient_id, DRecipientID},
{amount, Amount},
{gas_price, GasPrice},
{gas, Gas},
{ttl, TTL},
{nonce, Nonce},
{payload, Payload}],
Template =
[{sender_id, id},
{recipient_id, id},
{amount, int},
{gas_price, int},
{gas, int},
{ttl, int},
{nonce, int},
{payload, binary}],
BinaryTX = gmser_chain_objects:serialize(Type, Vsn, Template, Fields),
NetworkTX = <<NetworkID/binary, BinaryTX/binary>>,
Signature = ecu_eddsa:sign_detached(NetworkTX, SecKey),
SigTxType = signed_tx,
SigTxVsn = 1,
SigTemplate =
[{signatures, [binary]},
{transaction, binary}],
TX_Data =
[{signatures, [Signature]},
{transaction, BinaryTX}],
SignedTX = gmser_chain_objects:serialize(SigTxType, SigTxVsn, SigTemplate, TX_Data),
Encoded = gmser_api_encoder:encode(transaction, SignedTX),
hz:post_tx(Encoded).
-spec verify_signature(Sig, Message, PubKey) -> Result
when Sig :: binary(),
Message :: iodata(),

View File

@ -16,8 +16,7 @@
-license("MIT").
%% Admin functions
-export([network_id/0, network_id/1,
tls/0, tls/1,
-export([tls/0, tls/1,
chain_nodes/0, chain_nodes/1,
timeout/0, timeout/1]).
@ -44,8 +43,7 @@
req = none :: none | binary()}).
-record(s,
{network_id = "gm_mainnet" :: string(),
tls = false :: boolean(),
{tls = false :: boolean(),
chain_nodes = {[], []} :: {[hz:chain_node()], [hz:chain_node()]},
sticky = none :: none | hz:chain_node(),
fetchers = [] :: [#fetcher{}],
@ -58,19 +56,6 @@
%%% Service Interface
-spec network_id() -> Name
when Name :: hz:network_id().
network_id() ->
gen_server:call(?MODULE, network_id).
-spec network_id(Name) -> ok
when Name :: hz:network_id().
network_id(Name) ->
gen_server:cast(?MODULE, {network_id, Name}).
-spec tls() -> boolean().
@ -163,8 +148,6 @@ init(none) ->
handle_call({request, Request}, From, State) ->
NewState = do_request(Request, From, State),
{noreply, NewState};
handle_call(network_id, _, State = #s{network_id = Name}) ->
{reply, Name, State};
handle_call(tls, _, State = #s{tls = TLS}) ->
{reply, TLS, State};
handle_call(chain_nodes, _, State = #s{chain_nodes = {Wait, Used}}) ->
@ -177,8 +160,6 @@ handle_call(Unexpected, From, State) ->
{noreply, State}.
handle_cast({network_id, Name}, State) ->
{noreply, State#s{network_id = Name}};
handle_cast({tls, Boolean}, State) ->
NewState = do_tls(Boolean, State),
{noreply, NewState};