Use aeserialization for base58c encoding/decoding.

This commit is contained in:
Erik Stenman 2019-03-25 13:30:44 +01:00
parent ff37438ccf
commit 429175f235
6 changed files with 80 additions and 131 deletions

View File

@ -58,22 +58,23 @@ Immediate values can be of 11 types:
`0x0deadbeef0` `0x0deadbeef0`
2. Chain Objects. These are all addresses to different types of chain objects. 2. Chain Objects. These are all addresses to different types of chain objects.
Each address is a 256 bits number encoded in base64 with a prefix. Each address is a 256 bits number encoded in base58 with checksum
with a prefix of "@" plus a type prefix followed by "_".
2a. Address: a base58 encoded number starting with @ followed by a number of base58chars 2a. Account Address: a base58c encoded number starting with @ak_ followed by a number of base58chars
`@nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv` '@ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
2b. Contract address: ct_{base58char}+ 2b. Contract address: @ct_{base58char}+
`ct_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv` `@ct_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
2c. Oracle address: ok_{base58char}+ 2c. Oracle address: @ok_{base58char}+
`ok_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv` `@ok_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
2d. Name address: nm_{base58char}+ 2d. Name address: @nm_{base58char}+
`nm_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv` `@nm_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
2e. Channel address: ch_{base58char}+ 2e. Channel address: @ch_{base58char}+
`ch_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv` `@ch_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
3. Boolean true or false 3. Boolean true or false
`true` `true`
@ -106,8 +107,7 @@ Immediate values can be of 11 types:
10. Hashes: #{base64char}+ 10. Hashes: #{base64char}+
`#AQIDCioLFQ==` `#AQIDCioLFQ==`
11. Signatures: ${base64char}+ 11. Signatures: $sg_{base58char}+
`$AQIDCioLFQ==`
Where Where

View File

@ -40,12 +40,11 @@
%%% -2374683271468723648732648736498712634876147 %%% -2374683271468723648732648736498712634876147
%%% 1b. Integers as Hexadecimals:: 0x{Hexdigits} %%% 1b. Integers as Hexadecimals:: 0x{Hexdigits}
%%% 0x0deadbeef0 %%% 0x0deadbeef0
%%% 2a. addresses, a base58 encoded string prefixed with @ %%% 2a. account addresses, a base58c encoded string prefixed with @ak_
%%% @foo %%% 2b. contract address: @ct_{base58char}+
%%% 2b. contract address: ct_{base58char}+ %%% 2c. oracle address: @ok_{base58char}+
%%% 2c. oracle address: ok_{base58char}+ %%% 2d. name address: @nm_{base58char}+
%%% 2d. name address: nm_{base58char}+ %%% 2e. channel address: @ch_{base58char}+
%%% 2e. channel address: ch_{base58char}+
%%% 3. Boolean true or false %%% 3. Boolean true or false
%%% true %%% true
%%% false %%% false
@ -69,8 +68,7 @@
%%% (| 42 | 12 | ( "foo", 12) |) %%% (| 42 | 12 | ( "foo", 12) |)
%%% 10. Hashes: #{base64char}+ %%% 10. Hashes: #{base64char}+
%%% #AQIDCioLFQ== %%% #AQIDCioLFQ==
%%% 11. Signatures: ${base64char}+ %%% 11. Signatures: $sg_{base58char}+
%%% $AQIDCioLFQ==
%%% %%%
%%% Where Digits: [0123456789] %%% Where Digits: [0123456789]
%%% Hexdigits: [0123456789abcdef] %%% Hexdigits: [0123456789abcdef]
@ -761,27 +759,27 @@ to_bytecode([{string,_line, String}|Rest], Address, Env, Code, Opts) ->
to_bytecode(Rest, Address, Env, to_bytecode(Rest, Address, Env,
[{immediate, aeb_fate_data:make_string(String)}|Code], [{immediate, aeb_fate_data:make_string(String)}|Code],
Opts); Opts);
to_bytecode([{address,_line, {address, Value}}|Rest], to_bytecode([{object,_line, {address, Value}}|Rest],
Address, Env, Code, Opts) -> Address, Env, Code, Opts) ->
to_bytecode(Rest, Address, Env, to_bytecode(Rest, Address, Env,
[{immediate, aeb_fate_data:make_address(Value)}|Code], [{immediate, aeb_fate_data:make_address(Value)}|Code],
Opts); Opts);
to_bytecode([{address,_line, {contract, Value}}|Rest], to_bytecode([{object,_line, {contract, Value}}|Rest],
Address, Env, Code, Opts) -> Address, Env, Code, Opts) ->
to_bytecode(Rest, Address, Env, to_bytecode(Rest, Address, Env,
[{immediate, aeb_fate_data:make_contract(Value)}|Code], [{immediate, aeb_fate_data:make_contract(Value)}|Code],
Opts); Opts);
to_bytecode([{address,_line, {oracle, Value}}|Rest], to_bytecode([{object,_line, {oracle, Value}}|Rest],
Address, Env, Code, Opts) -> Address, Env, Code, Opts) ->
to_bytecode(Rest, Address, Env, to_bytecode(Rest, Address, Env,
[{immediate, aeb_fate_data:make_oracle(Value)}|Code], [{immediate, aeb_fate_data:make_oracle(Value)}|Code],
Opts); Opts);
to_bytecode([{address,_line, {name, Value}}|Rest], to_bytecode([{object,_line, {name, Value}}|Rest],
Address, Env, Code, Opts) -> Address, Env, Code, Opts) ->
to_bytecode(Rest, Address, Env, to_bytecode(Rest, Address, Env,
[{immediate, aeb_fate_data:make_name(Value)}|Code], [{immediate, aeb_fate_data:make_name(Value)}|Code],
Opts); Opts);
to_bytecode([{address,_line, {channel, Value}}|Rest], to_bytecode([{object,_line, {channel, Value}}|Rest],
Address, Env, Code, Opts) -> Address, Env, Code, Opts) ->
to_bytecode(Rest, Address, Env, to_bytecode(Rest, Address, Env,
[{immediate, aeb_fate_data:make_contract(Value)}|Code], [{immediate, aeb_fate_data:make_contract(Value)}|Code],
@ -791,7 +789,7 @@ to_bytecode([{hash,_line, Value}|Rest],
to_bytecode(Rest, Address, Env, to_bytecode(Rest, Address, Env,
[{immediate, aeb_fate_data:make_hash(Value)}|Code], [{immediate, aeb_fate_data:make_hash(Value)}|Code],
Opts); Opts);
to_bytecode([{signature,_line, Value}|Rest], to_bytecode([{signature,_line, {signature, Value}}|Rest],
Address, Env, Code, Opts) -> Address, Env, Code, Opts) ->
to_bytecode(Rest, Address, Env, to_bytecode(Rest, Address, Env,
[{immediate, aeb_fate_data:make_signature(Value)}|Code], [{immediate, aeb_fate_data:make_signature(Value)}|Code],

View File

@ -16,10 +16,9 @@ BASE58 = [123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]
BASE64 = [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy0123456789+/=] BASE64 = [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy0123456789+/=]
INT = {DIGIT}+ INT = {DIGIT}+
HEX = 0x{HEXDIGIT}+ HEX = 0x{HEXDIGIT}+
OBJECT = [a-z][a-z]_{BASE58}+ OBJECT = @[a-z][a-z]_{BASE58}+
ADDRESS = @{BASE58}+
HASH = #{BASE64}+ HASH = #{BASE64}+
SIG = \${BASE64}+ SIG = \$\sg_{BASE58}+
WS = [\000-\s] WS = [\000-\s]
ID = {LOWER}[a-zA-Z0-9_]* ID = {LOWER}[a-zA-Z0-9_]*
STRING = "[^"]*" STRING = "[^"]*"
@ -38,6 +37,12 @@ false : {token, {boolean, TokenLine, false}}.
FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}. FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}.
{HASH} :
{token, {hash, TokenLine, parse_hash(TokenChars)}}.
{SIG} :
{token, {signature, TokenLine, parse_object(TokenChars)}}.
{OBJECT} :
{token, {object, TokenLine, parse_object(TokenChars)}}.
{ID} : {ID} :
{token, {id, TokenLine, TokenChars}}. {token, {id, TokenLine, TokenChars}}.
{HEX} : {HEX} :
@ -46,14 +51,6 @@ FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}.
{token, {int, TokenLine, parse_int(TokenChars)}}. {token, {int, TokenLine, parse_int(TokenChars)}}.
-{INT} : -{INT} :
{token, {int, TokenLine, parse_int(TokenChars)}}. {token, {int, TokenLine, parse_int(TokenChars)}}.
{HASH} :
{token, {hash, TokenLine, parse_hash(TokenChars)}}.
{SIG} :
{token, {signature, TokenLine, parse_signature(TokenChars)}}.
{ADDRESS} :
{token, {address, TokenLine, {address, parse_address(TokenChars)}}}.
{OBJECT} :
{token, {object, TokenLine, parse_object(TokenChars)}}.
{STRING} : {STRING} :
{token, {string, TokenLine, list_to_binary(TokenChars)}}. {token, {string, TokenLine, list_to_binary(TokenChars)}}.
{BITS} : {BITS} :
@ -114,23 +111,15 @@ parse_acc("a" ++ N) -> list_to_integer(N).
parse_hash("#" ++ Chars) -> parse_hash("#" ++ Chars) ->
base64:decode(Chars). base64:decode(Chars).
parse_signature("$" ++ Chars) -> parse_object([_|Chars]) ->
base64:decode(Chars). case aeser_api_encoder:decode(list_to_binary(Chars)) of
{account_pubkey, Bin} -> {address, Bin};
parse_address("@" ++ Chars) -> {contract_pubkey, Bin} -> {contract, Bin};
base58_to_address(Chars). {oracle_pubkey, Bin} -> {oracle, Bin};
{name, Bin} -> {name, Bin};
parse_object("ct_" ++ Chars) -> {channel, Bin} -> {channel, Bin};
{contract, base58_to_address(Chars)}; {signature, Bin} -> {signature, Bin}
parse_object("ok_" ++ Chars) -> end.
{oracle, base58_to_address(Chars)};
parse_object("nm_" ++ Chars) ->
{name, base58_to_address(Chars)};
parse_object("ch_" ++ Chars) ->
{channel, base58_to_address(Chars)};
parse_object("ak_" ++ Chars) ->
{address, base58_to_address(Chars)}.
scan(S) -> scan(S) ->
string(S). string(S).
@ -148,23 +137,3 @@ bits([$> |_Rest], Acc) -> Acc;
bits([$0 | Rest], Acc) -> bits(Rest, Acc bsl 1); bits([$0 | Rest], Acc) -> bits(Rest, Acc bsl 1);
bits([$1 | Rest], Acc) -> bits(Rest, (Acc bsl 1) bor 1); bits([$1 | Rest], Acc) -> bits(Rest, (Acc bsl 1) bor 1);
bits([$ | Rest], Acc) -> bits(Rest, Acc). bits([$ | Rest], Acc) -> bits(Rest, Acc).
char_to_base58(C) ->
binary:at(<<0,1,2,3,4,5,6,7,8,0,0,0,0,0,0,0,9,10,11,12,13,14,15,16,0,17,
18,19,20,21,0,22,23,24,25,26,27,28,29,30,31,32,0,0,0,0,0,0,
33,34,35,36,37,38,39,40,41,42,43,0,44,45,46,47,48,49,50,51,
52,53,54,55,56,57>>, C-$1).
base58_to_integer(C, []) -> C;
base58_to_integer(C, [X | Xs]) ->
base58_to_integer(C * 58 + char_to_base58(X), Xs).
base58_to_integer([]) -> error;
base58_to_integer([Char]) -> char_to_base58(Char);
base58_to_integer([Char | Str]) ->
base58_to_integer(char_to_base58(Char), Str).
base58_to_address(Base58) ->
I = base58_to_integer(Base58),
Bin = <<I:256>>,
Bin.

View File

@ -137,23 +137,29 @@ encode({bits, Term}) when is_integer(Term) -> make_bits(Term);
%% TODO: check that each byte is in base58 %% TODO: check that each byte is in base58
encode({address, B}) when is_binary(B) -> make_address(B); encode({address, B}) when is_binary(B) -> make_address(B);
encode({address, I}) when is_integer(I) -> B = <<I:256>>, make_address(B); encode({address, I}) when is_integer(I) -> B = <<I:256>>, make_address(B);
encode({address, S}) when is_list(S) -> make_address(base58_to_address(S)); encode({address, S}) when is_list(S) ->
make_address(encode_address(account_pubkey, S));
encode({hash, H}) when is_binary(H) -> make_hash(H); encode({hash, H}) when is_binary(H) -> make_hash(H);
encode({hash, H}) when is_list(H) -> make_hash(base64:decode(H)); encode({hash, H}) when is_list(H) -> make_hash(base64:decode(H));
encode({signature, S}) when is_binary(S) -> make_signature(S); encode({signature, S}) when is_binary(S) -> make_signature(S);
encode({signature, S}) when is_list(S) -> make_signature(base64:decode(S)); encode({signature, S}) when is_list(S) ->
make_signature(encode_address(signature, S));
encode({contract, B}) when is_binary(B) -> make_contract(B); encode({contract, B}) when is_binary(B) -> make_contract(B);
encode({contract, I}) when is_integer(I) -> B = <<I:256>>, make_contract(B); encode({contract, I}) when is_integer(I) -> B = <<I:256>>, make_contract(B);
encode({contract, S}) when is_list(S) -> make_contract(base58_to_address(S)); encode({contract, S}) when is_list(S) ->
make_contract(encode_address(contract_pubkey, S));
encode({oracle, B}) when is_binary(B) -> make_oracle(B); encode({oracle, B}) when is_binary(B) -> make_oracle(B);
encode({oracle, I}) when is_integer(I) -> B = <<I:256>>, make_oracle(B); encode({oracle, I}) when is_integer(I) -> B = <<I:256>>, make_oracle(B);
encode({oracle, S}) when is_list(S) -> make_oracle(base58_to_address(S)); encode({oracle, S}) when is_list(S) ->
make_oracle(encode_address(oracle_pubkey, S));
encode({name, B}) when is_binary(B) -> make_name(B); encode({name, B}) when is_binary(B) -> make_name(B);
encode({name, I}) when is_integer(I) -> B = <<I:256>>, make_name(B); encode({name, I}) when is_integer(I) -> B = <<I:256>>, make_name(B);
encode({name, S}) when is_list(S) -> make_name(base58_to_address(S)); encode({name, S}) when is_list(S) ->
make_name(encode_address(name, S));
encode({channel, B}) when is_binary(B) -> make_channel(B); encode({channel, B}) when is_binary(B) -> make_channel(B);
encode({channel, I}) when is_integer(I) -> B = <<I:256>>, make_channel(B); encode({channel, I}) when is_integer(I) -> B = <<I:256>>, make_channel(B);
encode({channel, S}) when is_list(S) -> make_channel(base58_to_address(S)); encode({channel, S}) when is_list(S) ->
make_channel(encode_address(channel, S));
encode({variant, Size, Tag, Values}) -> make_variant(Size, Tag, Values); encode({variant, Size, Tag, Values}) -> make_variant(Size, Tag, Values);
encode(Term) when is_integer(Term) -> make_integer(Term); encode(Term) when is_integer(Term) -> make_integer(Term);
encode(Term) when is_boolean(Term) -> make_boolean(Term); encode(Term) when is_boolean(Term) -> make_boolean(Term);
@ -205,13 +211,19 @@ format(?FATE_VARIANT(Size, Tag, T)) ->
" |)"]; " |)"];
format(M) when ?IS_FATE_MAP(M) -> format(M) when ?IS_FATE_MAP(M) ->
["{ ", format_kvs(maps:to_list(?FATE_MAP_VALUE(M))), " }"]; ["{ ", format_kvs(maps:to_list(?FATE_MAP_VALUE(M))), " }"];
format(?FATE_ADDRESS(Address)) -> ["@", address_to_base58(Address)];
format(?FATE_HASH(X)) -> ["#", base64:encode(X)]; format(?FATE_HASH(X)) -> ["#", base64:encode(X)];
format(?FATE_SIGNATURE(X)) -> ["$", base64:encode(X)]; format(?FATE_ADDRESS(X)) ->
format(?FATE_CONTRACT(X)) -> ["ct_", address_to_base58(X)]; ["@", aeser_api_encoder:encode(account_pubkey, X)];
format(?FATE_ORACLE(X)) -> ["ok_", address_to_base58(X)]; format(?FATE_SIGNATURE(X)) ->
format(?FATE_NAME(X)) -> ["nm_", address_to_base58(X)]; ["$", aeser_api_encoder:encode(signature, X)];
format(?FATE_CHANNEL(X)) -> ["ch_", address_to_base58(X)]; format(?FATE_CONTRACT(X)) ->
["@", aeser_api_encoder:encode(contract_pubkey, X)];
format(?FATE_ORACLE(X)) ->
["@", eser_api_encoder:encode(oracle_pubkey, X)];
format(?FATE_NAME(X)) ->
["@", aeser_api_encoder:encode(name, X)];
format(?FATE_CHANNEL(X)) ->
["@", aeser_api_encoder:encode(channel, X)];
format(V) -> exit({not_a_fate_type, V}). format(V) -> exit({not_a_fate_type, V}).
format_bits(0, Acc) -> Acc; format_bits(0, Acc) -> Acc;
@ -230,42 +242,12 @@ format_list(List) ->
format_kvs(List) -> format_kvs(List) ->
lists:join(", ", [ [format(K), " => ", format(V)] || {K, V} <- List]). lists:join(", ", [ [format(K), " => ", format(V)] || {K, V} <- List]).
encode_address(Type, S) when is_list(S) ->
%% -- Local base 58 library B = list_to_binary(S),
try aeser_api_encoder:decode(B) of
base58char(Char) -> {Type, Encoding} ->
binary:at(<<"123456789ABCDEFGHJKLMNPQRSTUVWXYZ" Encoding;
"abcdefghijkmnopqrstuvwxyz">>, Char). _ -> erlang:error({bad_address_encoding, Type, S})
char_to_base58(C) -> catch _:_ ->
binary:at(<<0,1,2,3,4,5,6,7,8,0,0,0,0,0,0,0,9,10,11,12,13,14,15,16,0,17, erlang:error({bad_address_encoding, Type, S})
18,19,20,21,0,22,23,24,25,26,27,28,29,30,31,32,0,0,0,0,0,0, end.
33,34,35,36,37,38,39,40,41,42,43,0,44,45,46,47,48,49,50,51,
52,53,54,55,56,57>>, C-$1).
base58_to_integer(C, []) -> C;
base58_to_integer(C, [X | Xs]) ->
base58_to_integer(C * 58 + char_to_base58(X), Xs).
base58_to_integer([]) -> error;
base58_to_integer([Char]) -> char_to_base58(Char);
base58_to_integer([Char | Str]) ->
base58_to_integer(char_to_base58(Char), Str).
base58_to_address(Base58) ->
I = base58_to_integer(Base58),
Bin = <<I:256>>,
Bin.
address_to_base58(<<A:256>>) ->
integer_to_base58(A).
integer_to_base58(0) -> <<"1">>;
integer_to_base58(Integer) ->
Base58String = integer_to_base58(Integer, []),
list_to_binary(Base58String).
integer_to_base58(0, Acc) -> Acc;
integer_to_base58(Integer, Acc) ->
Quot = Integer div 58,
Rem = Integer rem 58,
integer_to_base58(Quot, [base58char(Rem)|Acc]).

View File

@ -112,7 +112,7 @@ FUNCTION foo () : {tuple, []}
ADDR_TO_STR a arg216 ADDR_TO_STR a arg216
STR_REVERSE a174 @nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv STR_REVERSE a174 @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
INT_TO_ADDR arg127 var207 INT_TO_ADDR arg127 var207
@ -180,11 +180,11 @@ FUNCTION foo () : {tuple, []}
LOG3 arg255 arg15 arg211 var139 arg44 LOG3 arg255 arg15 arg211 var139 arg44
LOG4 @nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv a247 a 9 a38 a LOG4 @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv a247 a 9 a38 a
DEACTIVATE DEACTIVATE
SPEND @nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv var136 SPEND @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv var136
ORACLE_REGISTER arg29 48 ((| 5 | 2 | (1, "foo", ()) |)) arg65 { <> => false} <> ORACLE_REGISTER arg29 48 ((| 5 | 2 | (1, "foo", ()) |)) arg65 { <> => false} <>

View File

@ -66,7 +66,7 @@ FUNCTION tuple() : {tuple, [integer, boolean, string, {tuple, [integer, integer]
FUNCTION address() : address FUNCTION address() : address
RETURNR #deadbeef RETURNR @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
;; Option(integer) = NONE | SOME(integer) ;; Option(integer) = NONE | SOME(integer)
FUNCTION variant_none() : {variant, [{tuple, []}, {tuple, [integer]}]} FUNCTION variant_none() : {variant, [{tuple, []}, {tuple, [integer]}]}