serialize signatures
This took a surprising number of goose chases to work out... I had to find out - what is the gmser prefix for a signature (sg_) - what is the gmb wrapper for a signature (none) - what errors gmser can report when a signature is invalid - what an example of a valid signature is - what that example signature serializes to
This commit is contained in:
parent
a6f58a95e2
commit
7704d82c6f
55
src/hz.erl
55
src/hz.erl
@ -1806,29 +1806,20 @@ coerce({O, N, integer}, S, to_fate) when is_list(S) ->
|
|||||||
error:badarg -> single_error({invalid, O, N, S})
|
error:badarg -> single_error({invalid, O, N, S})
|
||||||
end;
|
end;
|
||||||
coerce({O, N, address}, S, to_fate) ->
|
coerce({O, N, address}, S, to_fate) ->
|
||||||
try
|
coerce_chain_object(O, N, address, account_pubkey, S);
|
||||||
case gmser_api_encoder:decode(unicode:characters_to_binary(S)) of
|
|
||||||
{account_pubkey, Key} -> {ok, {address, Key}};
|
|
||||||
_ -> single_error({invalid, O, N, S})
|
|
||||||
end
|
|
||||||
catch
|
|
||||||
error:_ -> single_error({invalid, O, N, S})
|
|
||||||
end;
|
|
||||||
coerce({_, _, address}, {address, Bin}, from_fate) ->
|
coerce({_, _, address}, {address, Bin}, from_fate) ->
|
||||||
Address = gmser_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
|
coerce_chain_object(O, N, contract, contract_pubkey, S);
|
||||||
case gmser_api_encoder:decode(unicode:characters_to_binary(S)) of
|
|
||||||
{contract_pubkey, Key} -> {ok, {contract, Key}};
|
|
||||||
_ -> single_error({invalid, O, N, S})
|
|
||||||
end
|
|
||||||
catch
|
|
||||||
error:_ -> single_error({invalid, O, N, S})
|
|
||||||
end;
|
|
||||||
coerce({_, _, contract}, {contract, Bin}, from_fate) ->
|
coerce({_, _, contract}, {contract, Bin}, from_fate) ->
|
||||||
Address = gmser_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({O, N, signature}, S, to_fate) ->
|
||||||
|
coerce_chain_object(O, N, signature, signature, S);
|
||||||
|
coerce({_, _, signature}, Bin, from_fate) ->
|
||||||
|
Address = gmser_api_encoder:encode(signature, Bin),
|
||||||
|
{ok, unicode:characters_to_list(Address)};
|
||||||
coerce({_, _, boolean}, true, _) ->
|
coerce({_, _, boolean}, true, _) ->
|
||||||
{ok, true};
|
{ok, true};
|
||||||
coerce({_, _, boolean}, false, _) ->
|
coerce({_, _, boolean}, false, _) ->
|
||||||
@ -1897,6 +1888,27 @@ coerce({O, N, _}, Data, from_fate) ->
|
|||||||
{ok, Data};
|
{ok, Data};
|
||||||
coerce({O, N, _}, Data, _) -> single_error({invalid, O, N, Data}).
|
coerce({O, N, _}, Data, _) -> single_error({invalid, O, N, Data}).
|
||||||
|
|
||||||
|
coerce_chain_object(O, N, T, Tag, S) ->
|
||||||
|
case decode_chain_object(Tag, S) of
|
||||||
|
{ok, Data} -> {ok, coerce_chain_object2(T, Data)};
|
||||||
|
{error, Reason} -> single_error({Reason, O, N, S})
|
||||||
|
end.
|
||||||
|
|
||||||
|
coerce_chain_object2(address, Data) -> {address, Data};
|
||||||
|
coerce_chain_object2(contract, Data) -> {contract, Data};
|
||||||
|
coerce_chain_object2(signature, Data) -> Data.
|
||||||
|
|
||||||
|
decode_chain_object(Tag, S) ->
|
||||||
|
try
|
||||||
|
case gmser_api_encoder:decode(unicode:characters_to_binary(S)) of
|
||||||
|
{Tag, Data} -> {ok, Data};
|
||||||
|
{_, _} -> {error, wrong_prefix}
|
||||||
|
end
|
||||||
|
catch
|
||||||
|
error:missing_prefix -> {error, missing_prefix};
|
||||||
|
error:incorrect_size -> {error, incorrect_size}
|
||||||
|
end.
|
||||||
|
|
||||||
coerce_list(Type, Elements, Direction) ->
|
coerce_list(Type, Elements, Direction) ->
|
||||||
% 0 index since it represents a sophia list
|
% 0 index since it represents a sophia list
|
||||||
coerce_list(Type, Elements, Direction, 0, [], []).
|
coerce_list(Type, Elements, Direction, 0, [], []).
|
||||||
@ -2427,6 +2439,8 @@ try_coerce(Type, Sophia, Fate) ->
|
|||||||
_ ->
|
_ ->
|
||||||
erlang:error({from_fate_failed, Sophia, SophiaActual})
|
erlang:error({from_fate_failed, Sophia, SophiaActual})
|
||||||
end,
|
end,
|
||||||
|
% Finally, check that the FATE result is something that gmb understands.
|
||||||
|
gmb_fate_encoding:serialize(Fate),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
coerce_int_test() ->
|
coerce_int_test() ->
|
||||||
@ -2449,6 +2463,15 @@ coerce_contract_test() ->
|
|||||||
167,208,53,78,40,235,2,163,132,36,47,183,228,151,9,
|
167,208,53,78,40,235,2,163,132,36,47,183,228,151,9,
|
||||||
210,39,214>>}).
|
210,39,214>>}).
|
||||||
|
|
||||||
|
coerce_signature_test() ->
|
||||||
|
{ok, Type} = annotate_type(signature, #{}),
|
||||||
|
try_coerce(Type,
|
||||||
|
"sg_XDyF8LJC4tpMyAySvpaG1f5V9F2XxAbRx9iuVjvvdNMwVracLhzAuXhRM5kXAFtpwW1DCHuz5jGehUayCah4jub32Ti2n",
|
||||||
|
<<231,4,97,129,16,173,37,42,194,249,28,94,134,163,208,84,22,135,
|
||||||
|
169,85,212,142,14,12,233,252,97,50,193,158,229,51,123,206,222,
|
||||||
|
249,2,3,85,173,106,150,243,253,89,128,248,52,195,140,95,114,
|
||||||
|
233,110,119,143,206,137,124,36,63,154,85,7>>).
|
||||||
|
|
||||||
coerce_bool_test() ->
|
coerce_bool_test() ->
|
||||||
{ok, Type} = annotate_type(boolean, #{}),
|
{ok, Type} = annotate_type(boolean, #{}),
|
||||||
try_coerce(Type, true, true),
|
try_coerce(Type, true, true),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user