Use aeserialization for base58c encoding/decoding.
This commit is contained in:
parent
ff37438ccf
commit
429175f235
26
README.md
26
README.md
@ -58,22 +58,23 @@ Immediate values can be of 11 types:
|
||||
`0x0deadbeef0`
|
||||
|
||||
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
|
||||
`@nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
|
||||
2a. Account Address: a base58c encoded number starting with @ak_ followed by a number of base58chars
|
||||
'@ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
|
||||
|
||||
2b. Contract address: ct_{base58char}+
|
||||
`ct_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
|
||||
2b. Contract address: @ct_{base58char}+
|
||||
`@ct_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
|
||||
|
||||
2c. Oracle address: ok_{base58char}+
|
||||
`ok_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
|
||||
2c. Oracle address: @ok_{base58char}+
|
||||
`@ok_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
|
||||
|
||||
2d. Name address: nm_{base58char}+
|
||||
`nm_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
|
||||
2d. Name address: @nm_{base58char}+
|
||||
`@nm_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
|
||||
|
||||
2e. Channel address: ch_{base58char}+
|
||||
`ch_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
|
||||
2e. Channel address: @ch_{base58char}+
|
||||
`@ch_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
|
||||
|
||||
3. Boolean true or false
|
||||
`true`
|
||||
@ -106,8 +107,7 @@ Immediate values can be of 11 types:
|
||||
10. Hashes: #{base64char}+
|
||||
`#AQIDCioLFQ==`
|
||||
|
||||
11. Signatures: ${base64char}+
|
||||
`$AQIDCioLFQ==`
|
||||
11. Signatures: $sg_{base58char}+
|
||||
|
||||
|
||||
Where
|
||||
|
@ -40,12 +40,11 @@
|
||||
%%% -2374683271468723648732648736498712634876147
|
||||
%%% 1b. Integers as Hexadecimals:: 0x{Hexdigits}
|
||||
%%% 0x0deadbeef0
|
||||
%%% 2a. addresses, a base58 encoded string prefixed with @
|
||||
%%% @foo
|
||||
%%% 2b. contract address: ct_{base58char}+
|
||||
%%% 2c. oracle address: ok_{base58char}+
|
||||
%%% 2d. name address: nm_{base58char}+
|
||||
%%% 2e. channel address: ch_{base58char}+
|
||||
%%% 2a. account addresses, a base58c encoded string prefixed with @ak_
|
||||
%%% 2b. contract address: @ct_{base58char}+
|
||||
%%% 2c. oracle address: @ok_{base58char}+
|
||||
%%% 2d. name address: @nm_{base58char}+
|
||||
%%% 2e. channel address: @ch_{base58char}+
|
||||
%%% 3. Boolean true or false
|
||||
%%% true
|
||||
%%% false
|
||||
@ -69,8 +68,7 @@
|
||||
%%% (| 42 | 12 | ( "foo", 12) |)
|
||||
%%% 10. Hashes: #{base64char}+
|
||||
%%% #AQIDCioLFQ==
|
||||
%%% 11. Signatures: ${base64char}+
|
||||
%%% $AQIDCioLFQ==
|
||||
%%% 11. Signatures: $sg_{base58char}+
|
||||
%%%
|
||||
%%% Where Digits: [0123456789]
|
||||
%%% Hexdigits: [0123456789abcdef]
|
||||
@ -761,27 +759,27 @@ to_bytecode([{string,_line, String}|Rest], Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_string(String)}|Code],
|
||||
Opts);
|
||||
to_bytecode([{address,_line, {address, Value}}|Rest],
|
||||
to_bytecode([{object,_line, {address, Value}}|Rest],
|
||||
Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_address(Value)}|Code],
|
||||
Opts);
|
||||
to_bytecode([{address,_line, {contract, Value}}|Rest],
|
||||
to_bytecode([{object,_line, {contract, Value}}|Rest],
|
||||
Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_contract(Value)}|Code],
|
||||
Opts);
|
||||
to_bytecode([{address,_line, {oracle, Value}}|Rest],
|
||||
to_bytecode([{object,_line, {oracle, Value}}|Rest],
|
||||
Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_oracle(Value)}|Code],
|
||||
Opts);
|
||||
to_bytecode([{address,_line, {name, Value}}|Rest],
|
||||
to_bytecode([{object,_line, {name, Value}}|Rest],
|
||||
Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_name(Value)}|Code],
|
||||
Opts);
|
||||
to_bytecode([{address,_line, {channel, Value}}|Rest],
|
||||
to_bytecode([{object,_line, {channel, Value}}|Rest],
|
||||
Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_contract(Value)}|Code],
|
||||
@ -791,7 +789,7 @@ to_bytecode([{hash,_line, Value}|Rest],
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_hash(Value)}|Code],
|
||||
Opts);
|
||||
to_bytecode([{signature,_line, Value}|Rest],
|
||||
to_bytecode([{signature,_line, {signature, Value}}|Rest],
|
||||
Address, Env, Code, Opts) ->
|
||||
to_bytecode(Rest, Address, Env,
|
||||
[{immediate, aeb_fate_data:make_signature(Value)}|Code],
|
||||
|
@ -16,10 +16,9 @@ BASE58 = [123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]
|
||||
BASE64 = [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy0123456789+/=]
|
||||
INT = {DIGIT}+
|
||||
HEX = 0x{HEXDIGIT}+
|
||||
OBJECT = [a-z][a-z]_{BASE58}+
|
||||
ADDRESS = @{BASE58}+
|
||||
OBJECT = @[a-z][a-z]_{BASE58}+
|
||||
HASH = #{BASE64}+
|
||||
SIG = \${BASE64}+
|
||||
SIG = \$\sg_{BASE58}+
|
||||
WS = [\000-\s]
|
||||
ID = {LOWER}[a-zA-Z0-9_]*
|
||||
STRING = "[^"]*"
|
||||
@ -38,6 +37,12 @@ false : {token, {boolean, TokenLine, false}}.
|
||||
|
||||
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} :
|
||||
{token, {id, TokenLine, TokenChars}}.
|
||||
{HEX} :
|
||||
@ -46,14 +51,6 @@ FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}.
|
||||
{token, {int, TokenLine, parse_int(TokenChars)}}.
|
||||
-{INT} :
|
||||
{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} :
|
||||
{token, {string, TokenLine, list_to_binary(TokenChars)}}.
|
||||
{BITS} :
|
||||
@ -114,23 +111,15 @@ parse_acc("a" ++ N) -> list_to_integer(N).
|
||||
parse_hash("#" ++ Chars) ->
|
||||
base64:decode(Chars).
|
||||
|
||||
parse_signature("$" ++ Chars) ->
|
||||
base64:decode(Chars).
|
||||
|
||||
parse_address("@" ++ Chars) ->
|
||||
base58_to_address(Chars).
|
||||
|
||||
parse_object("ct_" ++ Chars) ->
|
||||
{contract, base58_to_address(Chars)};
|
||||
parse_object("ok_" ++ Chars) ->
|
||||
{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)}.
|
||||
|
||||
parse_object([_|Chars]) ->
|
||||
case aeser_api_encoder:decode(list_to_binary(Chars)) of
|
||||
{account_pubkey, Bin} -> {address, Bin};
|
||||
{contract_pubkey, Bin} -> {contract, Bin};
|
||||
{oracle_pubkey, Bin} -> {oracle, Bin};
|
||||
{name, Bin} -> {name, Bin};
|
||||
{channel, Bin} -> {channel, Bin};
|
||||
{signature, Bin} -> {signature, Bin}
|
||||
end.
|
||||
|
||||
scan(S) ->
|
||||
string(S).
|
||||
@ -148,23 +137,3 @@ bits([$> |_Rest], Acc) -> Acc;
|
||||
bits([$0 | Rest], Acc) -> bits(Rest, Acc bsl 1);
|
||||
bits([$1 | Rest], Acc) -> bits(Rest, (Acc bsl 1) bor 1);
|
||||
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.
|
||||
|
@ -137,23 +137,29 @@ encode({bits, Term}) when is_integer(Term) -> make_bits(Term);
|
||||
%% TODO: check that each byte is in base58
|
||||
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, 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_list(H) -> make_hash(base64:decode(H));
|
||||
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, 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, 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, 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, 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(Term) when is_integer(Term) -> make_integer(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_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_SIGNATURE(X)) -> ["$", base64:encode(X)];
|
||||
format(?FATE_CONTRACT(X)) -> ["ct_", address_to_base58(X)];
|
||||
format(?FATE_ORACLE(X)) -> ["ok_", address_to_base58(X)];
|
||||
format(?FATE_NAME(X)) -> ["nm_", address_to_base58(X)];
|
||||
format(?FATE_CHANNEL(X)) -> ["ch_", address_to_base58(X)];
|
||||
format(?FATE_ADDRESS(X)) ->
|
||||
["@", aeser_api_encoder:encode(account_pubkey, X)];
|
||||
format(?FATE_SIGNATURE(X)) ->
|
||||
["$", aeser_api_encoder:encode(signature, 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_bits(0, Acc) -> Acc;
|
||||
@ -230,42 +242,12 @@ format_list(List) ->
|
||||
format_kvs(List) ->
|
||||
lists:join(", ", [ [format(K), " => ", format(V)] || {K, V} <- List]).
|
||||
|
||||
|
||||
%% -- Local base 58 library
|
||||
|
||||
base58char(Char) ->
|
||||
binary:at(<<"123456789ABCDEFGHJKLMNPQRSTUVWXYZ"
|
||||
"abcdefghijkmnopqrstuvwxyz">>, Char).
|
||||
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.
|
||||
|
||||
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]).
|
||||
encode_address(Type, S) when is_list(S) ->
|
||||
B = list_to_binary(S),
|
||||
try aeser_api_encoder:decode(B) of
|
||||
{Type, Encoding} ->
|
||||
Encoding;
|
||||
_ -> erlang:error({bad_address_encoding, Type, S})
|
||||
catch _:_ ->
|
||||
erlang:error({bad_address_encoding, Type, S})
|
||||
end.
|
||||
|
@ -112,7 +112,7 @@ FUNCTION foo () : {tuple, []}
|
||||
|
||||
ADDR_TO_STR a arg216
|
||||
|
||||
STR_REVERSE a174 @nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
|
||||
STR_REVERSE a174 @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
|
||||
|
||||
INT_TO_ADDR arg127 var207
|
||||
|
||||
@ -180,11 +180,11 @@ FUNCTION foo () : {tuple, []}
|
||||
|
||||
LOG3 arg255 arg15 arg211 var139 arg44
|
||||
|
||||
LOG4 @nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv a247 a 9 a38 a
|
||||
LOG4 @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv a247 a 9 a38 a
|
||||
|
||||
DEACTIVATE
|
||||
|
||||
SPEND @nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv var136
|
||||
SPEND @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv var136
|
||||
|
||||
ORACLE_REGISTER arg29 48 ((| 5 | 2 | (1, "foo", ()) |)) arg65 { <> => false} <>
|
||||
|
||||
|
@ -66,7 +66,7 @@ FUNCTION tuple() : {tuple, [integer, boolean, string, {tuple, [integer, integer]
|
||||
|
||||
|
||||
FUNCTION address() : address
|
||||
RETURNR #deadbeef
|
||||
RETURNR @ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
|
||||
|
||||
;; Option(integer) = NONE | SOME(integer)
|
||||
FUNCTION variant_none() : {variant, [{tuple, []}, {tuple, [integer]}]}
|
||||
|
Loading…
x
Reference in New Issue
Block a user