Add support for extended-auth account types #60

Open
uwiger wants to merge 1 commits from uw-ext-account-types into master
4 changed files with 81 additions and 15 deletions
+24 -4
View File
@@ -36,6 +36,7 @@
| transaction | transaction
| tx_hash | tx_hash
| account_pubkey | account_pubkey
| {account_pubkey, 0..6}
| account_seckey | account_seckey
| associate_chain | associate_chain
| entry | entry
@@ -107,8 +108,12 @@ safe_decode_keypair(#{<<"pub">> := EncPub, <<"priv">> := EncPriv}) ->
-spec encode(known_type(), payload() | gmser_id:id()) -> encoded(). -spec encode(known_type(), payload() | gmser_id:id()) -> encoded().
encode(id_hash, Payload) -> encode(id_hash, Payload) ->
{IdType, Val} = gmser_id:specialize(Payload), case gmser_id:to_map(Payload) of
encode(id2type(IdType), Val); #{type := account, subtype := SubT, value := Val} ->
encode({account_pubkey, SubT}, Val);
#{type := IdType, value := Val} ->
encode(id2type(IdType), Val)
end;
encode(Type, Payload) -> encode(Type, Payload) ->
case type_size_check(Type, Payload) of case type_size_check(Type, Payload) of
ok -> ok ->
@@ -237,17 +242,16 @@ id2type(associate_chain) -> associate_chain;
id2type(channel) -> channel; id2type(channel) -> channel;
id2type(commitment) -> commitment; id2type(commitment) -> commitment;
id2type(contract) -> contract_pubkey; id2type(contract) -> contract_pubkey;
id2type(contract_source) -> contract_source;
id2type(name) -> name; id2type(name) -> name;
id2type(native_token) -> native_token; id2type(native_token) -> native_token;
id2type(entry) -> entry. id2type(entry) -> entry.
type2id({account_pubkey, SubT}) -> {account, SubT};
type2id(account_pubkey) -> account; type2id(account_pubkey) -> account;
type2id(associate_chain) -> associate_chain; type2id(associate_chain) -> associate_chain;
type2id(channel) -> channel; type2id(channel) -> channel;
type2id(commitment) -> commitment; type2id(commitment) -> commitment;
type2id(contract_pubkey) -> contract; type2id(contract_pubkey) -> contract;
type2id(contract_source) -> contract_source;
type2id(name) -> name; type2id(name) -> name;
type2id(native_token) -> native_token; type2id(native_token) -> native_token;
type2id(entry) -> entry. type2id(entry) -> entry.
@@ -266,6 +270,7 @@ type2enc(contract_store_value) -> ?BASE64;
type2enc(contract_source) -> ?BASE64; type2enc(contract_source) -> ?BASE64;
type2enc(transaction) -> ?BASE64; type2enc(transaction) -> ?BASE64;
type2enc(tx_hash) -> ?BASE58; type2enc(tx_hash) -> ?BASE58;
type2enc({account_pubkey, _}) -> ?BASE58;
type2enc(account_pubkey) -> ?BASE58; type2enc(account_pubkey) -> ?BASE58;
type2enc(account_seckey) -> ?BASE58; type2enc(account_seckey) -> ?BASE58;
type2enc(associate_chain) -> ?BASE58; type2enc(associate_chain) -> ?BASE58;
@@ -298,6 +303,13 @@ type2pfx(contract_store_value) -> <<"cv">>;
type2pfx(contract_source) -> <<"cx">>; type2pfx(contract_source) -> <<"cx">>;
type2pfx(transaction) -> <<"tx">>; type2pfx(transaction) -> <<"tx">>;
type2pfx(tx_hash) -> <<"th">>; type2pfx(tx_hash) -> <<"th">>;
type2pfx({account_pubkey,0}) -> <<"a0">>;
type2pfx({account_pubkey,1}) -> <<"a1">>;
type2pfx({account_pubkey,2}) -> <<"a2">>;
type2pfx({account_pubkey,3}) -> <<"a3">>;
type2pfx({account_pubkey,4}) -> <<"a4">>;
type2pfx({account_pubkey,5}) -> <<"a5">>;
type2pfx({account_pubkey,6}) -> <<"a6">>;
type2pfx(account_pubkey) -> <<"ak">>; type2pfx(account_pubkey) -> <<"ak">>;
type2pfx(account_seckey) -> <<"sk">>; type2pfx(account_seckey) -> <<"sk">>;
type2pfx(associate_chain) -> <<"ac">>; type2pfx(associate_chain) -> <<"ac">>;
@@ -329,6 +341,13 @@ pfx2type(<<"ct">>) -> contract_pubkey;
pfx2type(<<"cx">>) -> contract_source; pfx2type(<<"cx">>) -> contract_source;
pfx2type(<<"tx">>) -> transaction; pfx2type(<<"tx">>) -> transaction;
pfx2type(<<"th">>) -> tx_hash; pfx2type(<<"th">>) -> tx_hash;
pfx2type(<<"a0">>) -> {account_pubkey, 0};
pfx2type(<<"a1">>) -> {account_pubkey, 1};
pfx2type(<<"a2">>) -> {account_pubkey, 2};
pfx2type(<<"a3">>) -> {account_pubkey, 3};
pfx2type(<<"a4">>) -> {account_pubkey, 4};
pfx2type(<<"a5">>) -> {account_pubkey, 5};
pfx2type(<<"a6">>) -> {account_pubkey, 6};
pfx2type(<<"ak">>) -> account_pubkey; pfx2type(<<"ak">>) -> account_pubkey;
pfx2type(<<"sk">>) -> account_seckey; pfx2type(<<"sk">>) -> account_seckey;
pfx2type(<<"ac">>) -> associate_chain; pfx2type(<<"ac">>) -> associate_chain;
@@ -363,6 +382,7 @@ byte_size_for_type(contract_source) -> not_applicable;
byte_size_for_type(transaction) -> not_applicable; byte_size_for_type(transaction) -> not_applicable;
byte_size_for_type(tx_hash) -> 32; byte_size_for_type(tx_hash) -> 32;
byte_size_for_type(account_pubkey) -> 32; byte_size_for_type(account_pubkey) -> 32;
byte_size_for_type({account_pubkey, _}) -> 32;
byte_size_for_type(account_seckey) -> 32; byte_size_for_type(account_seckey) -> 32;
byte_size_for_type(associate_chain) -> 32; byte_size_for_type(associate_chain) -> 32;
byte_size_for_type(signature) -> 64; byte_size_for_type(signature) -> 64;
+4
View File
@@ -115,6 +115,8 @@ tag(entry) -> 140;
tag(entry_create_tx) -> 141; tag(entry_create_tx) -> 141;
tag(entry_transfer_tx) -> 142; tag(entry_transfer_tx) -> 142;
tag(entry_destroy_tx) -> 143; tag(entry_destroy_tx) -> 143;
tag(account_key_store) -> 144;
tag(account_create_tx) -> 145;
tag(pof) -> 200. tag(pof) -> 200.
rev_tag(10) -> account; rev_tag(10) -> account;
@@ -194,4 +196,6 @@ rev_tag(140) -> entry;
rev_tag(141) -> entry_create_tx; rev_tag(141) -> entry_create_tx;
rev_tag(142) -> entry_transfer_tx; rev_tag(142) -> entry_transfer_tx;
rev_tag(143) -> entry_destroy_tx; rev_tag(143) -> entry_destroy_tx;
rev_tag(144) -> account_key_store;
rev_tag(145) -> account_create_tx;
rev_tag(200) -> pof. rev_tag(200) -> pof.
+36 -3
View File
@@ -14,6 +14,7 @@
, specialize/1 , specialize/1
, specialize/2 , specialize/2
, specialize_type/1 , specialize_type/1
, to_map/1
, is_id/1 , is_id/1
]). ]).
@@ -29,12 +30,17 @@
, val , val
}). }).
-type tag() :: 'account' -type subtype() :: 0..6.
-type id_map() :: #{ type := simple_tag()
, subtype => subtype()
, value := binary() }.
-type tag() :: {'account', subtype()} | simple_tag().
-type simple_tag() :: 'account'
| 'associate_chain' | 'associate_chain'
| 'channel' | 'channel'
| 'commitment' | 'commitment'
| 'contract' | 'contract'
| 'contract_source'
| 'name' | 'name'
| 'native_token' | 'native_token'
| 'entry'. | 'entry'.
@@ -57,7 +63,8 @@
___TAG___ =:= contract; ___TAG___ =:= contract;
___TAG___ =:= channel; ___TAG___ =:= channel;
___TAG___ =:= associate_chain; ___TAG___ =:= associate_chain;
___TAG___ =:= entry ___TAG___ =:= entry;
___TAG___ =:= native_token
). ).
-define(IS_VAL(___VAL___), byte_size(___VAL___) =:= 32). -define(IS_VAL(___VAL___), byte_size(___VAL___) =:= 32).
@@ -69,6 +76,8 @@
create(Tag, Val) when ?IS_TAG(Tag), ?IS_VAL(Val) -> create(Tag, Val) when ?IS_TAG(Tag), ?IS_VAL(Val) ->
#id{ tag = Tag #id{ tag = Tag
, val = Val}; , val = Val};
create({account,I}, Val) when is_binary(Val), I >= 0, I =< 6 ->
#id{ tag = {account, I}, val = Val};
create(Tag, Val) when ?IS_VAL(Val) -> create(Tag, Val) when ?IS_VAL(Val) ->
error({illegal_tag, Tag}); error({illegal_tag, Tag});
create(Tag, Val) when ?IS_TAG(Tag)-> create(Tag, Val) when ?IS_TAG(Tag)->
@@ -78,28 +87,52 @@ create(Tag, Val) ->
-spec specialize(id()) -> {tag(), val()}. -spec specialize(id()) -> {tag(), val()}.
specialize(#id{tag = {Tag,_}, val = Val}) ->
{Tag, Val};
specialize(#id{tag = Tag, val = Val}) -> specialize(#id{tag = Tag, val = Val}) ->
{Tag, Val}. {Tag, Val}.
-spec specialize(id(), tag()) -> val(). -spec specialize(id(), tag()) -> val().
specialize(#id{tag = {Tag, _}, val = Val}, Tag) when is_binary(Val) ->
Val;
specialize(#id{tag = Tag, val = Val}, Tag) when ?IS_TAG(Tag), ?IS_VAL(Val) -> specialize(#id{tag = Tag, val = Val}, Tag) when ?IS_TAG(Tag), ?IS_VAL(Val) ->
Val. Val.
-spec specialize_type(id()) -> tag(). -spec specialize_type(id()) -> tag().
specialize_type(#id{tag = {Tag, _}}) when ?IS_TAG(Tag) ->
Tag;
specialize_type(#id{tag = Tag}) when ?IS_TAG(Tag) -> specialize_type(#id{tag = Tag}) when ?IS_TAG(Tag) ->
Tag. Tag.
-spec to_map(id()) -> id_map().
to_map(#id{tag = {Tag, SubType}, val = Val}) when ?IS_TAG(Tag) ->
#{ type => Tag
, subtype => SubType
, value => Val };
to_map(#id{tag = Tag, val = Val}) when ?IS_TAG(Tag) ->
#{ type => Tag
, value => Val }.
-spec is_id(term()) -> boolean(). -spec is_id(term()) -> boolean().
is_id(#id{}) -> true; is_id(#id{}) -> true;
is_id(_) -> false. is_id(_) -> false.
-spec encode(id()) -> binary(). -spec encode(id()) -> binary().
encode(#id{tag = {account, N}, val = Val}) when N =< 2#111_1111 ->
Ext = 2#1000_0000 bor N,
<<Ext:8, Val/binary>>;
encode(#id{tag = Tag, val = Val}) -> encode(#id{tag = Tag, val = Val}) ->
Res = <<(encode_tag(Tag)):?TAG_SIZE/unit:8, Val/binary>>, Res = <<(encode_tag(Tag)):?TAG_SIZE/unit:8, Val/binary>>,
true = ?SERIALIZED_SIZE =:= byte_size(Res), true = ?SERIALIZED_SIZE =:= byte_size(Res),
Res. Res.
-spec decode(binary()) -> id(). -spec decode(binary()) -> id().
decode(<<Ext:8, Rest/binary>>) when Ext >= 2#1000_0000 ->
%% Extended account id type
Type = Ext band 2#0111_1111,
#id{ tag = {account, Type}
, val = Rest };
decode(<<Tag:?TAG_SIZE/unit:8, Val:?PUB_SIZE/binary>>) -> decode(<<Tag:?TAG_SIZE/unit:8, Val:?PUB_SIZE/binary>>) ->
#id{ tag = decode_tag(Tag) #id{ tag = decode_tag(Tag)
, val = Val}. , val = Val}.
+10 -1
View File
@@ -194,7 +194,16 @@ known_types() ->
Forms = get_forms(), Forms = get_forms(),
[{type, _, union, Types}] = [{type, _, union, Types}] =
[Def || {attribute, _, type, {known_type, Def, []}} <- Forms], [Def || {attribute, _, type, {known_type, Def, []}} <- Forms],
[Name || {atom,_, Name} <- Types]. lists:flatmap(fun known_type_entry/1, Types).
known_type_entry({atom, _, Name}) ->
[Name];
known_type_entry({type, _, tuple,
[{atom, _, account_pubkey},
{type, _, range, [{integer, _, Lo}, {integer, _, Hi}]}]}) ->
[{account_pubkey, N} || N <- lists:seq(Lo, Hi)];
known_type_entry(Other) ->
error({unsupported_known_type, Other}).
mapped_prefixes() -> mapped_prefixes() ->
Forms = get_forms(), Forms = get_forms(),