From c614da15e0b7e21236533a0e2fbf5192159f97df Mon Sep 17 00:00:00 2001 From: Erik Stenman Date: Thu, 14 Mar 2019 16:45:10 +0100 Subject: [PATCH] Add hash, signature and object types. --- include/aeb_fate_data.hrl | 68 +++++++++----- src/aeb_fate_asm.erl | 135 ++++++++++++++------------- src/aeb_fate_asm_scan.template | 38 +++++++- src/aeb_fate_data.erl | 113 ++++++++++++++++++----- src/aeb_fate_encoding.erl | 161 +++++++++++++++++++++++++++++---- src/aeb_fate_generate_ops.erl | 4 +- 6 files changed, 377 insertions(+), 142 deletions(-) diff --git a/include/aeb_fate_data.hrl b/include/aeb_fate_data.hrl index 424c9b1..d82c43c 100644 --- a/include/aeb_fate_data.hrl +++ b/include/aeb_fate_data.hrl @@ -1,23 +1,35 @@ --define(FATE_INTEGER_T, integer()). --define(FATE_BYTE_T, 0..255). --define(FATE_BOOLEAN_T, true | false). --define(FATE_NIL_T, []). --define(FATE_LIST_T, list()). --define(FATE_UNIT_T, {tuple, {}}). --define(FATE_MAP_T, #{ fate_type() => fate_type() }). --define(FATE_STRING_T, binary()). --define(FATE_ADDRESS_T, {address, <<_:256>>}). --define(FATE_VARIANT_T, {variant, ?FATE_BYTE_T, ?FATE_BYTE_T, tuple()}). --define(FATE_VOID_T, void). --define(FATE_TUPLE_T, {tuple, tuple()}). --define(FATE_BITS_T, {bits, integer()}). +-define(FATE_INTEGER_T, integer()). +-define(FATE_BYTE_T, 0..255). +-define(FATE_BOOLEAN_T, true | false). +-define(FATE_NIL_T, []). +-define(FATE_LIST_T, list()). +-define(FATE_UNIT_T, {tuple, {}}). +-define(FATE_MAP_T, #{ fate_type() => fate_type() }). +-define(FATE_STRING_T, binary()). +-define(FATE_ADDRESS_T, {address, <<_:256>>}). +-define(FATE_HASH_T, {hash, binary()}). +-define(FATE_SIGNATURE_T, {signature, binary()}). +-define(FATE_CONTRACT_T, {contract, <<_:256>>}). +-define(FATE_ORACLE_T, {oracle, <<_:256>>}). +-define(FATE_NAME_T, {name, <<_:256>>}). +-define(FATE_CHANNEL_T, {channel, <<_:256>>}). +-define(FATE_VARIANT_T, {variant, ?FATE_BYTE_T, ?FATE_BYTE_T, tuple()}). +-define(FATE_VOID_T, void). +-define(FATE_TUPLE_T, {tuple, tuple()}). +-define(FATE_BITS_T, {bits, integer()}). --define(IS_FATE_INTEGER(X), is_integer(X)). --define(IS_FATE_LIST(X), (is_list(X))). --define(IS_FATE_STRING(X), (is_binary(X))). --define(IS_FATE_MAP(X), (is_map(X))). --define(IS_FATE_TUPLE(X), (is_tuple(X) andalso (tuple == element(1, X) andalso is_tuple(element(2, X))))). +-define(IS_FATE_INTEGER(X), (is_integer(X))). +-define(IS_FATE_LIST(X), (is_list(X))). +-define(IS_FATE_STRING(X), (is_binary(X))). +-define(IS_FATE_MAP(X), (is_map(X))). +-define(IS_FATE_TUPLE(X), (is_tuple(X) andalso (tuple == element(1, X) andalso is_tuple(element(2, X))))). -define(IS_FATE_ADDRESS(X), (is_tuple(X) andalso (address == element(1, X) andalso is_binary(element(2, X))))). +-define(IS_FATE_HASH(X), (is_tuple(X) andalso (hash == element(1, X) andalso is_binary(element(2, X))))). +-define(IS_FATE_SIGNATURE(X), (is_tuple(X) andalso (signature == element(1, X) andalso is_binary(element(2, X))))). +-define(IS_FATE_CONTRACT(X), (is_tuple(X) andalso (contract == element(1, X) andalso is_binary(element(2, X))))). +-define(IS_FATE_ORACLE(X), (is_tuple(X) andalso (oracle == element(1, X) andalso is_binary(element(2, X))))). +-define(IS_FATE_NAME(X), (is_tuple(X) andalso (name == element(1, X) andalso is_binary(element(2, X))))). +-define(IS_FATE_CHANNEL(X), (is_tuple(X) andalso (channel == element(1, X) andalso is_binary(element(2, X))))). -define(IS_FATE_BITS(X), (is_tuple(X) andalso (bits == element(1, X) andalso is_integer(element(2, X))))). -define(IS_FATE_VARIANT(X), (is_tuple(X) andalso @@ -28,16 +40,28 @@ ))). -define(IS_FATE_BOOLEAN(X), is_boolean(X)). --define(FATE_UNIT, {tuple, {}}). --define(FATE_TUPLE(T), {tuple, T}). --define(FATE_ADDRESS(A), {address, A}). --define(FATE_BITS(B), {bits, B}). +-define(FATE_UNIT, {tuple, {}}). +-define(FATE_TUPLE(T), {tuple, T}). +-define(FATE_ADDRESS(A), {address, A}). +-define(FATE_HASH(X), {hash, X}). +-define(FATE_SIGNATURE(S), {signature, S}). +-define(FATE_CONTRACT(X), {contract, X}). +-define(FATE_ORACLE(X), {oracle, X}). +-define(FATE_NAME(X), {name, X}). +-define(FATE_CHANNEL(X), {channel, X}). +-define(FATE_BITS(B), {bits, B}). -define(FATE_INTEGER_VALUE(X), (X)). -define(FATE_LIST_VALUE(X), (X)). -define(FATE_STRING_VALUE(X), (X)). -define(FATE_ADDRESS_VALUE(X), (element(2, X))). +-define(FATE_HASH_VALUE(X), (element(2, X))). +-define(FATE_SIGNATURE_VALUE(X), (element(2, X))). +-define(FATE_CONTRACT_VALUE(X), (element(2, X))). +-define(FATE_ORACLE_VALUE(X), (element(2, X))). +-define(FATE_NAME_VALUE(X), (element(2, X))). +-define(FATE_CHANNEL_VALUE(X), (element(2, X))). -define(FATE_MAP_VALUE(X), (X)). -define(FATE_MAP_SIZE(X), (map_size(X))). -define(FATE_STRING_SIZE(X), (byte_size(X))). diff --git a/src/aeb_fate_asm.erl b/src/aeb_fate_asm.erl index 645eb48..aed4029 100644 --- a/src/aeb_fate_asm.erl +++ b/src/aeb_fate_asm.erl @@ -40,9 +40,12 @@ %%% -2374683271468723648732648736498712634876147 %%% 1b. Integers as Hexadecimals:: 0x{Hexdigits} %%% 0x0deadbeef0 -%%% 2. addresses, a base58 encoded string starting with #{base58char} -%%% followed by up to 64 hex chars -%%% #00000deadbeef +%%% 2a. addresses, a base58 encoded string prefixed with @ +%%% @foo +%%% 2b. contract addresse: ct_{base58char}+ +%%% 2c. oracle addresse: ok_{base58char}+ +%%% 2d. name addresse: nm_{base58char}+ +%%% 2e. channel addresse: ch_{base58char}+ %%% 3. Boolean true or false %%% true %%% false @@ -708,49 +711,16 @@ serialize_data(_, Data) -> aeb_fate_encoding:serialize(Data). serialize_signature({Args, RetType}) -> - [serialize_type({tuple, Args}) | - serialize_type(RetType)]. + [aeb_fate_encoding:serialize_type({tuple, Args}) | + aeb_fate_encoding:serialize_type(RetType)]. deserialize_signature(Binary) -> - {{tuple, Args}, Rest} = deserialize_type(Binary), - {RetType, Rest2} = deserialize_type(Rest), + {{tuple, Args}, Rest} = aeb_fate_encoding:deserialize_type(Binary), + {RetType, Rest2} = aeb_fate_encoding:deserialize_type(Rest), {{Args, RetType}, Rest2}. -deserialize_type(<<0, Rest/binary>>) -> {integer, Rest}; -deserialize_type(<<1, Rest/binary>>) -> {boolean, Rest}; -deserialize_type(<<2, Rest/binary>>) -> - {T, Rest2} = deserialize_type(Rest), - {{list, T}, Rest2}; -deserialize_type(<<3, N, Rest/binary>>) -> - {Ts, Rest2} = deserialize_types(N, Rest, []), - {{tuple, Ts}, Rest2}; -deserialize_type(<<4, Rest/binary>>) -> {address, Rest}; -deserialize_type(<<5, Rest/binary>>) -> {bits, Rest}; -deserialize_type(<<6, Rest/binary>>) -> - {K, Rest2} = deserialize_type(Rest), - {V, Rest3} = deserialize_type(Rest2), - {{map, K, V}, Rest3}; -deserialize_type(<<7, Rest/binary>>) -> - {string, Rest}; -deserialize_type(<<8, Size, Rest/binary>>) -> - {Variants, Rest2} = deserialize_variants(Size, Rest, []), - {{variant, Variants}, Rest2}. - -deserialize_variants(0, Rest, Variants) -> - {lists:reverse(Variants), Rest}; -deserialize_variants(N, Rest, Variants) -> - {T, Rest2} = deserialize_type(Rest), - deserialize_variants(N-1, Rest2, [T|Variants]). - - - -deserialize_types(0, Binary, Acc) -> - {lists:reverse(Acc), Binary}; -deserialize_types(N, Binary, Acc) -> - {T, Rest} = deserialize_type(Binary), - deserialize_types(N-1, Rest, [T | Acc]). to_hexstring(ByteList) -> @@ -786,10 +756,41 @@ 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, Value}|Rest], Address, Env, Code, Opts) -> +to_bytecode([{address,_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], + 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], + 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], + 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], + Address, Env, Code, Opts) -> + to_bytecode(Rest, Address, Env, + [{immediate, aeb_fate_data:make_contract(Value)}|Code], + Opts); +to_bytecode([{hash,_line, Value}|Rest], + Address, Env, Code, Opts) -> + to_bytecode(Rest, Address, Env, + [{immediate, aeb_fate_data:make_hash(Value)}|Code], + Opts); +to_bytecode([{signature,_line, Value}|Rest], + Address, Env, Code, Opts) -> + to_bytecode(Rest, Address, Env, + [{immediate, aeb_fate_data:make_signature(Value)}|Code], + Opts); to_bytecode([{id,_line, ID}|Rest], Address, Env, Code, Opts) -> {Hash, Env2} = insert_symbol(ID, Env), to_bytecode(Rest, Address, Env2, [{immediate, Hash}|Code], Opts); @@ -878,7 +879,6 @@ parse_variant([{start_variant,_line} parse_value([{int,_line, Int} | Rest]) -> {Int, Rest}; parse_value([{boolean,_line, Bool} | Rest]) -> {Bool, Rest}; -parse_value([{hash,_line, Hash} | Rest]) -> {Hash, Rest}; parse_value([{'{',_line} | Rest]) -> parse_map(Rest); parse_value([{'[',_line} | Rest]) -> parse_list(Rest); parse_value([{'(',_line} | Rest]) -> @@ -892,8 +892,20 @@ parse_value([{start_variant,_line}|_] = Tokens) -> {Variant, Rest}; parse_value([{string,_line, String} | Rest]) -> {aeb_fate_data:make_string(String), Rest}; -parse_value([{address,_line, Address} | Rest]) -> - {aeb_fate_data:make_address(Address), Rest}. +parse_value([{address,_line, {address, Address}} | Rest]) -> + {aeb_fate_data:make_address(Address), Rest}; +parse_value([{address,_line, {contract, Address}} | Rest]) -> + {aeb_fate_data:make_contract(Address), Rest}; +parse_value([{address,_line, {oracle, Address}} | Rest]) -> + {aeb_fate_data:make_oracle(Address), Rest}; +parse_value([{address,_line, {name, Address}} | Rest]) -> + {aeb_fate_data:make_name(Address), Rest}; +parse_value([{address,_line, {channel, Address}} | Rest]) -> + {aeb_fate_data:make_channel(Address), Rest}; +parse_value([{hash,_line, Hash} | Rest]) -> + {aeb_fate_data:make_hash(Hash), Rest}; +parse_value([{signature,_line, Hash} | Rest]) -> + {aeb_fate_data:make_signature(Hash), Rest}. to_fun_def([{id, _, Name}, {'(', _} | Rest]) -> {ArgsType, [{'to', _} | Rest2]} = to_arg_types(Rest), @@ -913,11 +925,17 @@ to_arg_types(Tokens) -> %% Type handling -to_type([{id, _, "integer"} | Rest]) -> {integer, Rest}; -to_type([{id, _, "boolean"} | Rest]) -> {boolean, Rest}; -to_type([{id, _, "string"} | Rest]) -> {string, Rest}; -to_type([{id, _, "address"} | Rest]) -> {address, Rest}; -to_type([{id, _, "bits"} | Rest]) -> {bits, Rest}; +to_type([{id, _, "integer"} | Rest]) -> {integer, Rest}; +to_type([{id, _, "boolean"} | Rest]) -> {boolean, Rest}; +to_type([{id, _, "string"} | Rest]) -> {string, Rest}; +to_type([{id, _, "address"} | Rest]) -> {address, Rest}; +to_type([{id, _, "contract"} | Rest]) -> {contract, Rest}; +to_type([{id, _, "oracle"} | Rest]) -> {oracle, Rest}; +to_type([{id, _, "name"} | Rest]) -> {name, Rest}; +to_type([{id, _, "channel"} | Rest]) -> {channel, Rest}; +to_type([{id, _, "hash"} | Rest]) -> {hash, Rest}; +to_type([{id, _, "signature"} | Rest]) -> {signature, Rest}; +to_type([{id, _, "bits"} | Rest]) -> {bits, Rest}; to_type([{'{', _}, {id, _, "list"}, {',', _} | Rest]) -> %% TODO: Error handling {ListType, [{'}', _}| Rest2]} = to_type(Rest), @@ -951,25 +969,6 @@ to_list_of_types(Tokens) -> {[Type], Rest} end. --spec serialize_type(aeb_fate_data:fate_type_type()) -> [byte()]. -serialize_type(integer) -> [0]; -serialize_type(boolean) -> [1]; -serialize_type({list, T}) -> [2 | serialize_type(T)]; -serialize_type({tuple, Ts}) -> - case length(Ts) of - N when N =< 255 -> - [3, N | [serialize_type(T) || T <- Ts]] - end; -serialize_type(address) -> [4]; -serialize_type(bits) -> [5]; -serialize_type({map, K, V}) -> [6 | serialize_type(K) ++ serialize_type(V)]; -serialize_type(string) -> [7]; -serialize_type({variant, ListOfVariants}) -> - Size = length(ListOfVariants), - if Size < 256 -> - [8, Size | [serialize_type(T) || T <- ListOfVariants]] - end. - %% ------------------------------------------------------------------- %% Helper functions diff --git a/src/aeb_fate_asm_scan.template b/src/aeb_fate_asm_scan.template index 1fa686a..c9013dc 100644 --- a/src/aeb_fate_asm_scan.template +++ b/src/aeb_fate_asm_scan.template @@ -4,7 +4,7 @@ %%% @doc %%% Handling FATE code. %%% @end -###REPLACEWITHNOTE### +%%% ###REPLACEWITHNOTE### %%%------------------------------------------------------------------- Definitions. @@ -13,9 +13,13 @@ HEXDIGIT = [0-9a-fA-F] LOWER = [a-z_] UPPER = [A-Z] BASE58 = [123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz] +BASE64 = [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy0123456789+/=] INT = {DIGIT}+ HEX = 0x{HEXDIGIT}+ -HASH = #{BASE58}+ +OBJECT = [a-z][a-z]_{BASE58}+ +ADDRESS = @{BASE58}+ +HASH = #{BASE64}+ +SIG = \${BASE64}+ WS = [\000-\s] ID = {LOWER}[a-zA-Z0-9_]* STRING = "[^"]*" @@ -30,7 +34,7 @@ a{INT} : {token, {stack, TokenLine, parse_acc(TokenChars)}}. true : {token, {boolean, TokenLine, true}}. false : {token, {boolean, TokenLine, false}}. -###REPLACEWITHOPTOKENS### +%% ###REPLACEWITHOPTOKENS### FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}. @@ -43,7 +47,13 @@ FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}. -{INT} : {token, {int, TokenLine, parse_int(TokenChars)}}. {HASH} : - {token, {address, TokenLine, parse_hash(TokenChars)}}. + {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} : @@ -102,8 +112,26 @@ 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)}. + + scan(S) -> string(S). @@ -139,4 +167,4 @@ base58_to_integer([Char | Str]) -> base58_to_address(Base58) -> I = base58_to_integer(Base58), Bin = <>, - Bin. \ No newline at end of file + Bin. diff --git a/src/aeb_fate_data.erl b/src/aeb_fate_data.erl index e2308ea..0568193 100644 --- a/src/aeb_fate_data.erl +++ b/src/aeb_fate_data.erl @@ -4,18 +4,22 @@ -module(aeb_fate_data). --type fate_integer() :: ?FATE_INTEGER_T. --type fate_boolean() :: ?FATE_BOOLEAN_T. --type fate_nil() :: ?FATE_NIL_T. --type fate_list() :: ?FATE_LIST_T. --type fate_unit() :: ?FATE_UNIT_T. --type fate_map() :: ?FATE_MAP_T. --type fate_string() :: ?FATE_STRING_T. --type fate_address() :: ?FATE_ADDRESS_T. - --type fate_variant() :: ?FATE_VARIANT_T. - --type fate_tuple() :: ?FATE_TUPLE_T. +-type fate_integer() :: ?FATE_INTEGER_T. +-type fate_boolean() :: ?FATE_BOOLEAN_T. +-type fate_nil() :: ?FATE_NIL_T. +-type fate_list() :: ?FATE_LIST_T. +-type fate_unit() :: ?FATE_UNIT_T. +-type fate_map() :: ?FATE_MAP_T. +-type fate_string() :: ?FATE_STRING_T. +-type fate_address() :: ?FATE_ADDRESS_T. +-type fate_hash() :: ?FATE_HASH_T. +-type fate_contract() :: ?FATE_CONTRACT_T. +-type fate_oracle() :: ?FATE_ORACLE_T. +-type fate_name() :: ?FATE_NAME_T. +-type fate_channel() :: ?FATE_CHANNEL_T. +-type fate_signature() :: ?FATE_SIGNATURE_T. +-type fate_variant() :: ?FATE_VARIANT_T. +-type fate_tuple() :: ?FATE_TUPLE_T. -type fate_type_type() :: integer | boolean @@ -23,6 +27,12 @@ | {map, fate_type(), fate_type()} | {tuple, [fate_type()]} | address + | hash + | signature + | contract + | oracle + | name + | channel | bits | {variant, integer()}. @@ -36,6 +46,12 @@ | fate_tuple() | fate_string() | fate_address() + | fate_hash() + | fate_signature() + | fate_contract() + | fate_oracle() + | fate_name() + | fate_channel() | fate_variant() | fate_map() | fate_type_type(). @@ -49,6 +65,12 @@ , fate_tuple/0 , fate_string/0 , fate_address/0 + , fate_hash/0 + , fate_signature/0 + , fate_contract/0 + , fate_oracle/0 + , fate_name/0 + , fate_channel/0 , fate_variant/0 , fate_map/0 , fate_type_type/0 @@ -62,6 +84,12 @@ , make_string/1 , make_map/1 , make_address/1 + , make_hash/1 + , make_signature/1 + , make_contract/1 + , make_oracle/1 + , make_name/1 + , make_channel/1 , make_bits/1 , make_unit/0 , tuple_to_list/1 @@ -71,19 +99,26 @@ -export([format/1]). -make_integer(I) when is_integer(I) -> ?MAKE_FATE_INTEGER(I). + make_boolean(true) -> ?FATE_TRUE; make_boolean(false) -> ?FATE_FALSE. -make_list([]) -> ?FATE_NIL; -make_list(L) -> ?MAKE_FATE_LIST(L). -make_string(S) when is_list(S) -> +make_list([]) -> ?FATE_NIL; +make_list(L) -> ?MAKE_FATE_LIST(L). +make_unit() -> ?FATE_UNIT. +make_tuple(T) -> ?FATE_TUPLE(T). +make_map(M) -> ?MAKE_FATE_MAP(M). +make_address(X) -> ?FATE_ADDRESS(X). +make_hash(X) -> ?FATE_HASH(X). +make_signature(X) -> ?FATE_SIGNATURE(X). +make_contract(X) -> ?FATE_CONTRACT(X). +make_oracle(X) -> ?FATE_ORACLE(X). +make_name(X) -> ?FATE_NAME(X). +make_channel(X) -> ?FATE_CHANNEL(X). +make_integer(I) when is_integer(I) -> ?MAKE_FATE_INTEGER(I). +make_bits(I) when is_integer(I) -> ?FATE_BITS(I). +make_string(S) when is_list(S) -> ?FATE_STRING(list_to_binary(lists:flatten(S))); -make_string(S) when is_binary(S) -> ?FATE_STRING(S). -make_unit() -> ?FATE_UNIT. -make_tuple(T) -> ?FATE_TUPLE(T). -make_map(M) -> ?MAKE_FATE_MAP(M). -make_address(A) -> ?FATE_ADDRESS(A). -make_bits(I) when is_integer(I) -> ?FATE_BITS(I). +make_string(S) when is_binary(S) -> ?FATE_STRING(S). make_variant(Size, Tag, Values) when is_integer(Size), is_integer(Tag) , 0 =< Size @@ -103,6 +138,22 @@ encode({bits, Term}) when is_integer(Term) -> make_bits(Term); encode({address, B}) when is_binary(B) -> make_address(B); encode({address, I}) when is_integer(I) -> B = <>, make_address(B); encode({address, S}) when is_list(S) -> make_address(base58_to_address(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({contract, B}) when is_binary(B) -> make_contract(B); +encode({contract, I}) when is_integer(I) -> B = <>, make_contract(B); +encode({contract, S}) when is_list(S) -> make_contract(base58_to_address(S)); +encode({oracle, B}) when is_binary(B) -> make_oracle(B); +encode({oracle, I}) when is_integer(I) -> B = <>, make_oracle(B); +encode({oracle, S}) when is_list(S) -> make_oracle(base58_to_address(S)); +encode({name, B}) when is_binary(B) -> make_name(B); +encode({name, I}) when is_integer(I) -> B = <>, make_name(B); +encode({name, S}) when is_list(S) -> make_name(base58_to_address(S)); +encode({channel, B}) when is_binary(B) -> make_channel(B); +encode({channel, I}) when is_integer(I) -> B = <>, make_channel(B); +encode({channel, S}) when is_list(S) -> make_channel(base58_to_address(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); @@ -120,8 +171,14 @@ decode(?FATE_TRUE) -> true; decode(?FATE_FALSE) -> false; decode(L) when ?IS_FATE_LIST(L) -> [decode(E) || E <- L]; decode(?FATE_ADDRESS(<>)) -> {address, Address}; -decode(?FATE_BITS(Bits)) -> {bits, Bits}; -decode(?FATE_TUPLE(T)) -> erlang:list_to_tuple([decode(E) || E <- T]); +decode(?FATE_HASH(H)) -> {hash, H}; +decode(?FATE_SIGNATURE(S)) -> {signature, S}; +decode(?FATE_CONTRACT(X)) -> {contract, X}; +decode(?FATE_ORACLE(X)) -> {oracle, X}; +decode(?FATE_NAME(X)) -> {name, X}; +decode(?FATE_CHANNEL(X)) -> {channel, X}; +decode(?FATE_BITS(Bits)) -> {bits, Bits}; +decode(?FATE_TUPLE(T)) -> erlang:list_to_tuple([decode(E) || E <- T]); decode(?FATE_VARIANT(Size, Tag, Values)) -> {variant, Size, Tag, Values}; decode(S) when ?IS_FATE_STRING(S) -> binary_to_list(S); decode(M) when ?IS_FATE_MAP(M) -> @@ -148,7 +205,13 @@ 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_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(V) -> exit({not_a_fate_type, V}). format_bits(0, Acc) -> Acc; diff --git a/src/aeb_fate_encoding.erl b/src/aeb_fate_encoding.erl index d0e5c12..8a3656a 100644 --- a/src/aeb_fate_encoding.erl +++ b/src/aeb_fate_encoding.erl @@ -37,7 +37,9 @@ -export([ deserialize/1 , deserialize_one/1 + , deserialize_type/1 , serialize/1 + , serialize_type/1 ]). -include("aeb_fate_data.hrl"). @@ -47,38 +49,62 @@ -define(SMALL_INT , 2#0). %% sxxxxxx 0 - 6 bit integer with sign bit %% 1 Set below --define(LONG_STRING , 2#00000001). %% 000000 01 - RLP encoded array, size >= 64 --define(SHORT_STRING , 2#01). %% xxxxxx 01 - [bytes], 0 < xxxxxx:size < 64 +-define(LONG_STRING , 2#00000001). %% 000000 01 | RLP encoded array - when size >= 64 +-define(SHORT_STRING , 2#01). %% xxxxxx 01 | [bytes] - when 0 < xxxxxx:size < 64 %% 11 Set below --define(SHORT_LIST , 2#0011). %% xxxx 0011 - [encoded elements], 0 < length < 16 -%% xxxx 0111 - FREE (For typedefs in future) --define(LONG_TUPLE , 2#00001011). %% 0000 1011 - RLP encoded (size - 16) + [encoded elements], --define(SHORT_TUPLE , 2#1011). %% xxxx 1011 - [encoded elements], 0 < size < 16 +-define(SHORT_LIST , 2#0011). %% xxxx 0011 | [encoded elements] when 0 < length < 16 +%% xxxx 0111 +-define(TYPE_INTEGER , 2#00000111). %% 0000 0111 - Integer typedef +-define(TYPE_BOOLEAN , 2#00010111). %% 0001 0111 - Boolean typedef +-define(TYPE_LIST , 2#00100111). %% 0010 0111 | Type +-define(TYPE_TUPLE , 2#00110111). %% 0011 0111 | Size | [Element Types] +-define(TYPE_OBJECT , 2#01000111). %% 0100 0111 | ObjectType +-define(TYPE_BITS , 2#01010111). %% 0101 0111 - Bits typedef +-define(TYPE_MAP , 2#01100111). %% 0110 0111 | Type | Type +-define(TYPE_STRING , 2#01110111). %% 0111 0111 - string typedef +-define(TYPE_VARIANT , 2#10000111). %% 1000 0111 | Size | [Type] + %% 1001 0111 + %% 1010 0111 + %% 1011 0111 + %% 1100 0111 + %% 1101 0111 + %% 1110 0111 + %% 1111 0111 +-define(LONG_TUPLE , 2#00001011). %% 0000 1011 | RLP encoded (size - 16) | [encoded elements], +-define(SHORT_TUPLE , 2#1011). %% xxxx 1011 | [encoded elements] when 0 < size < 16 %% 1111 Set below --define(LONG_LIST , 2#00011111). %% 0001 1111 - RLP encoded (length - 16) + [Elements] --define(MAP , 2#00101111). %% 0010 1111 - RLP encoded size + [encoded key, encoded value] +-define(LONG_LIST , 2#00011111). %% 0001 1111 | RLP encoded (length - 16) | [encoded lements] +-define(MAP , 2#00101111). %% 0010 1111 | RLP encoded size | [encoded key, encoded value] -define(EMPTY_TUPLE , 2#00111111). %% 0011 1111 --define(POS_BITS , 2#01001111). %% 0100 1111 - RLP encoded integer (to be interpreted as bitfield) +-define(POS_BITS , 2#01001111). %% 0100 1111 | RLP encoded integer (to be interpreted as bitfield) -define(EMPTY_STRING , 2#01011111). %% 0101 1111 --define(POS_BIG_INT , 2#01101111). %% 0110 1111 - RLP encoded (integer - 64) +-define(POS_BIG_INT , 2#01101111). %% 0110 1111 | RLP encoded (integer - 64) -define(FALSE , 2#01111111). %% 0111 1111 %% %% 1000 1111 - FREE (Possibly for bytecode in the future.) --define(ADDRESS , 2#10011111). %% 1001 1111 - [32 bytes] --define(VARIANT , 2#10101111). %% 1010 1111 - encoded size + encoded tag + encoded values +-define(OBJECT , 2#10011111). %% 1001 1111 | ObjectType | RLP encoded Array +-define(VARIANT , 2#10101111). %% 1010 1111 | encoded size | encoded tag | [encoded values] -define(NIL , 2#10111111). %% 1011 1111 - Empty list --define(NEG_BITS , 2#11001111). %% 1100 1111 - RLP encoded integer (infinite 1:s bitfield) +-define(NEG_BITS , 2#11001111). %% 1100 1111 | RLP encoded integer (infinite 1:s bitfield) -define(EMPTY_MAP , 2#11011111). %% 1101 1111 --define(NEG_BIG_INT , 2#11101111). %% 1110 1111 - RLP encoded (integer - 64) +-define(NEG_BIG_INT , 2#11101111). %% 1110 1111 | RLP encoded (integer - 64) -define(TRUE , 2#11111111). %% 1111 1111 --define(SHORT_TUPLE_SIZE, 16). --define(SHORT_LIST_SIZE , 16). --define(SMALL_INT_SIZE , 64). +-define(SHORT_TUPLE_SIZE, 16). +-define(SHORT_LIST_SIZE, 16). +-define(SMALL_INT_SIZE, 64). -define(SHORT_STRING_SIZE, 64). -define(POS_SIGN, 0). -define(NEG_SIGN, 1). +%% Object types +-define(OTYPE_ADDRESS, 0). +-define(OTYPE_HASH, 1). +-define(OTYPE_SIGNATURE, 2). +-define(OTYPE_CONTRACT, 3). +-define(OTYPE_ORACLE, 4). +-define(OTYPE_NAME, 5). +-define(OTYPE_CHANNEL, 6). %% -------------------------------------------------- %% Serialize @@ -106,7 +132,19 @@ serialize(String) when ?IS_FATE_STRING(String), Bytes = ?FATE_STRING_VALUE(String), <>; serialize(?FATE_ADDRESS(Address)) when is_binary(Address) -> - <>; + <>; +serialize(?FATE_HASH(Address)) when is_binary(Address) -> + <>; +serialize(?FATE_SIGNATURE(Address)) when is_binary(Address) -> + <>; +serialize(?FATE_CONTRACT(Address)) when is_binary(Address) -> + <>; +serialize(?FATE_ORACLE(Address)) when is_binary(Address) -> + <>; +serialize(?FATE_NAME(Address)) when is_binary(Address) -> + <>; +serialize(?FATE_CHANNEL(Address)) when is_binary(Address) -> + <>; serialize(?FATE_TUPLE(T)) when size(T) > 0 -> S = size(T), L = tuple_to_list(T), @@ -142,6 +180,79 @@ serialize(?FATE_VARIANT(Size, Tag, Values)) when 0 < Size, Size < 256, (serialize(?FATE_TUPLE(Values)))/binary >>. +%% ----------------------------------------------------- + +-spec serialize_type(aeb_fate_data:fate_type_type()) -> [byte()]. +serialize_type(integer) -> [?TYPE_INTEGER]; +serialize_type(boolean) -> [?TYPE_BOOLEAN]; +serialize_type({list, T}) -> [?TYPE_LIST | serialize_type(T)]; +serialize_type({tuple, Ts}) -> + case length(Ts) of + N when N =< 255 -> + [?TYPE_TUPLE, N | [serialize_type(T) || T <- Ts]] + end; +serialize_type(address) -> [?TYPE_OBJECT, ?OTYPE_ADDRESS]; +serialize_type(hash) -> [?TYPE_OBJECT, ?OTYPE_HASH]; +serialize_type(signature) -> [?TYPE_OBJECT, ?OTYPE_SIGNATURE]; +serialize_type(contract) -> [?TYPE_OBJECT, ?OTYPE_CONTRACT]; +serialize_type(oracle) -> [?TYPE_OBJECT, ?OTYPE_ORACLE]; +serialize_type(name) -> [?TYPE_OBJECT, ?OTYPE_NAME]; +serialize_type(channel) -> [?TYPE_OBJECT, ?OTYPE_CHANNEL]; +serialize_type(bits) -> [?TYPE_BITS]; +serialize_type({map, K, V}) -> [?TYPE_MAP + | serialize_type(K) ++ serialize_type(V)]; +serialize_type(string) -> [?TYPE_STRING]; +serialize_type({variant, ListOfVariants}) -> + Size = length(ListOfVariants), + if Size < 256 -> + [?TYPE_VARIANT, Size | [serialize_type(T) || T <- ListOfVariants]] + end. + + +-spec deserialize_type(binary()) -> {aeb_fate_data:fate_type_type(), binary()}. +deserialize_type(<>) -> {integer, Rest}; +deserialize_type(<>) -> {boolean, Rest}; +deserialize_type(<>) -> + {T, Rest2} = deserialize_type(Rest), + {{list, T}, Rest2}; +deserialize_type(<>) -> + {Ts, Rest2} = deserialize_types(N, Rest, []), + {{tuple, Ts}, Rest2}; +deserialize_type(<>) -> + case ObjectType of + ?OTYPE_ADDRESS -> {address, Rest}; + ?OTYPE_HASH -> {hash, Rest}; + ?OTYPE_SIGNATURE -> {signature, Rest}; + ?OTYPE_CONTRACT -> {contract, Rest}; + ?OTYPE_ORACLE -> {oracle, Rest}; + ?OTYPE_NAME -> {name, Rest}; + ?OTYPE_CHANNEL -> {channel, Rest} + end; +deserialize_type(<>) -> {bits, Rest}; +deserialize_type(<>) -> + {K, Rest2} = deserialize_type(Rest), + {V, Rest3} = deserialize_type(Rest2), + {{map, K, V}, Rest3}; +deserialize_type(<>) -> + {string, Rest}; +deserialize_type(<>) -> + {Variants, Rest2} = deserialize_variants(Size, Rest, []), + {{variant, Variants}, Rest2}. + +deserialize_variants(0, Rest, Variants) -> + {lists:reverse(Variants), Rest}; +deserialize_variants(N, Rest, Variants) -> + {T, Rest2} = deserialize_type(Rest), + deserialize_variants(N-1, Rest2, [T|Variants]). + + + +deserialize_types(0, Binary, Acc) -> + {lists:reverse(Acc), Binary}; +deserialize_types(N, Binary, Acc) -> + {T, Rest} = deserialize_type(Binary), + deserialize_types(N-1, Rest, [T | Acc]). + %% ----------------------------------------------------- @@ -205,9 +316,19 @@ deserialize2(<>) -> String = binary:part(Rest, 0, S), Rest2 = binary:part(Rest, byte_size(Rest), - (byte_size(Rest) - S)), {?MAKE_FATE_STRING(String), Rest2}; -deserialize2(<>) -> +deserialize2(<>) -> {A, Rest2} = aeser_rlp:decode_one(Rest), - {?FATE_ADDRESS(A), Rest2}; + Val = + case ObjectType of + ?OTYPE_ADDRESS -> ?FATE_ADDRESS(A); + ?OTYPE_HASH -> ?FATE_HASH(A); + ?OTYPE_SIGNATURE -> ?FATE_SIGNATURE(A); + ?OTYPE_CONTRACT -> ?FATE_CONTRACT(A); + ?OTYPE_ORACLE -> ?FATE_ORACLE(A); + ?OTYPE_NAME -> ?FATE_NAME(A); + ?OTYPE_CHANNEL -> ?FATE_CHANNEL(A) + end, + {Val, Rest2}; deserialize2(<>) -> {?FATE_TRUE, Rest}; deserialize2(<>) -> diff --git a/src/aeb_fate_generate_ops.erl b/src/aeb_fate_generate_ops.erl index 524b795..2988191 100644 --- a/src/aeb_fate_generate_ops.erl +++ b/src/aeb_fate_generate_ops.erl @@ -393,9 +393,9 @@ gen_token(#{opname := OpName}) -> io_lib:format("~-28s: {token, {mnemonic, TokenLine, ~w}}.\n", [Name, OpName]). -insert_tokens_in_template(<<"###REPLACEWITHOPTOKENS###", Rest/binary >>, Tokens) -> +insert_tokens_in_template(<<"%% ###REPLACEWITHOPTOKENS###", Rest/binary >>, Tokens) -> [Tokens, Rest]; -insert_tokens_in_template(<<"###REPLACEWITHNOTE###", Rest/binary >>, Tokens) -> +insert_tokens_in_template(<<"%%% ###REPLACEWITHNOTE###", Rest/binary >>, Tokens) -> [ "%%%\n" "%%% === === N O T E : This file is generated do not edit. === ===\n"