Merge pull request #10 from aeternity/PT-168026424-prepare_sophia_4_0_RC1
Add aeser_contract_code
This commit is contained in:
commit
ede7c14422
3
include/aeser_contract_code.hrl
Normal file
3
include/aeser_contract_code.hrl
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
-define(SOPHIA_CONTRACT_VSN_1, 1).
|
||||||
|
-define(SOPHIA_CONTRACT_VSN_2, 2).
|
||||||
|
-define(SOPHIA_CONTRACT_VSN_3, 3).
|
@ -1,3 +1,4 @@
|
|||||||
{erl_opts, [debug_info]}.
|
{erl_opts, [debug_info]}.
|
||||||
{deps, [ {base58, {git, "https://github.com/aeternity/erl-base58.git", {ref, "60a3356"}}}
|
{deps, [ {base58, {git, "https://github.com/aeternity/erl-base58.git", {ref, "60a3356"}}}
|
||||||
|
, {enacl, {git, "https://github.com/aeternity/enacl.git", {ref, "26180f4"}}}
|
||||||
]}.
|
]}.
|
||||||
|
114
src/aeser_contract_code.erl
Normal file
114
src/aeser_contract_code.erl
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||||
|
%%% @doc
|
||||||
|
%%% Serialization of contract code
|
||||||
|
%%% @end
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
-module(aeser_contract_code).
|
||||||
|
|
||||||
|
-include("aeser_contract_code.hrl").
|
||||||
|
|
||||||
|
-export([ deserialize/1
|
||||||
|
, serialize/1
|
||||||
|
, serialize/2 ]).
|
||||||
|
|
||||||
|
-spec serialize(map()) -> binary().
|
||||||
|
serialize(CodeMap) ->
|
||||||
|
serialize(CodeMap, ?SOPHIA_CONTRACT_VSN_3).
|
||||||
|
|
||||||
|
-spec serialize(map(), non_neg_integer()) -> binary().
|
||||||
|
serialize(CodeMap = #{ byte_code := ByteCode
|
||||||
|
, type_info := TypeInfo }, SophiaContractVersion) ->
|
||||||
|
%% Source hash
|
||||||
|
SourceHash = case CodeMap of
|
||||||
|
#{ source_hash := SHash } -> SHash;
|
||||||
|
#{ contract_source := SrcStr } ->
|
||||||
|
{ok, SHash} = enacl:generichash(32, list_to_binary(SrcStr)),
|
||||||
|
SHash
|
||||||
|
end,
|
||||||
|
|
||||||
|
%% Compiler version
|
||||||
|
Version = maps:get(compiler_version, CodeMap, <<"unknown">>),
|
||||||
|
BinVersion = if is_integer(Version) -> integer_to_binary(Version);
|
||||||
|
is_binary(Version) -> Version
|
||||||
|
end,
|
||||||
|
|
||||||
|
%% Payable
|
||||||
|
Payable = maps:get(payable, CodeMap, true),
|
||||||
|
|
||||||
|
Fields = [ {source_hash, SourceHash}
|
||||||
|
, {type_info, TypeInfo}
|
||||||
|
, {byte_code, ByteCode} ] ++
|
||||||
|
[ {compiler_version, BinVersion}
|
||||||
|
|| SophiaContractVersion > ?SOPHIA_CONTRACT_VSN_1 ] ++
|
||||||
|
[ {payable, Payable}
|
||||||
|
|| SophiaContractVersion > ?SOPHIA_CONTRACT_VSN_2 ],
|
||||||
|
aeser_chain_objects:serialize(compiler_sophia,
|
||||||
|
SophiaContractVersion,
|
||||||
|
serialization_template(SophiaContractVersion),
|
||||||
|
Fields).
|
||||||
|
|
||||||
|
-spec deserialize(binary()) -> map().
|
||||||
|
deserialize(Binary) ->
|
||||||
|
case aeser_chain_objects:deserialize_type_and_vsn(Binary) of
|
||||||
|
{compiler_sophia = Type, ?SOPHIA_CONTRACT_VSN_1 = Vsn, _Rest} ->
|
||||||
|
Template = serialization_template(Vsn),
|
||||||
|
[ {source_hash, Hash}
|
||||||
|
, {type_info, TypeInfo}
|
||||||
|
, {byte_code, ByteCode}
|
||||||
|
] = aeser_chain_objects:deserialize(Type, Vsn, Template, Binary),
|
||||||
|
#{ source_hash => Hash
|
||||||
|
, type_info => TypeInfo
|
||||||
|
, byte_code => ByteCode
|
||||||
|
, contract_vsn => Vsn
|
||||||
|
, payable => true
|
||||||
|
};
|
||||||
|
{compiler_sophia = Type, ?SOPHIA_CONTRACT_VSN_2 = Vsn, _Rest} ->
|
||||||
|
Template = serialization_template(Vsn),
|
||||||
|
[ {source_hash, Hash}
|
||||||
|
, {type_info, TypeInfo}
|
||||||
|
, {byte_code, ByteCode}
|
||||||
|
, {compiler_version, CompilerVersion}
|
||||||
|
] = aeser_chain_objects:deserialize(Type, Vsn, Template, Binary),
|
||||||
|
#{ source_hash => Hash
|
||||||
|
, type_info => TypeInfo
|
||||||
|
, byte_code => ByteCode
|
||||||
|
, compiler_version => CompilerVersion
|
||||||
|
, contract_vsn => Vsn
|
||||||
|
, payable => true
|
||||||
|
};
|
||||||
|
{compiler_sophia = Type, ?SOPHIA_CONTRACT_VSN_3 = Vsn, _Rest} ->
|
||||||
|
Template = serialization_template(Vsn),
|
||||||
|
[ {source_hash, Hash}
|
||||||
|
, {type_info, TypeInfo}
|
||||||
|
, {byte_code, ByteCode}
|
||||||
|
, {compiler_version, CompilerVersion}
|
||||||
|
, {payable, Payable}
|
||||||
|
] = aeser_chain_objects:deserialize(Type, Vsn, Template, Binary),
|
||||||
|
#{ source_hash => Hash
|
||||||
|
, type_info => TypeInfo
|
||||||
|
, byte_code => ByteCode
|
||||||
|
, compiler_version => CompilerVersion
|
||||||
|
, contract_vsn => Vsn
|
||||||
|
, payable => Payable
|
||||||
|
};
|
||||||
|
Other ->
|
||||||
|
error({illegal_code_object, Other})
|
||||||
|
end.
|
||||||
|
|
||||||
|
serialization_template(?SOPHIA_CONTRACT_VSN_1) ->
|
||||||
|
[ {source_hash, binary}
|
||||||
|
, {type_info, [{binary, binary, binary, binary}]} %% {type hash, name, arg type, out type}
|
||||||
|
, {byte_code, binary} ];
|
||||||
|
serialization_template(?SOPHIA_CONTRACT_VSN_2) ->
|
||||||
|
[ {source_hash, binary}
|
||||||
|
, {type_info, [{binary, binary, binary, binary}]} %% {type hash, name, arg type, out type}
|
||||||
|
, {byte_code, binary}
|
||||||
|
, {compiler_version, binary} ];
|
||||||
|
serialization_template(?SOPHIA_CONTRACT_VSN_3) ->
|
||||||
|
[ {source_hash, binary}
|
||||||
|
, {type_info, [{binary, binary, bool, binary, binary}]} %% {type hash, name, payable, arg type, out type}
|
||||||
|
, {byte_code, binary}
|
||||||
|
, {compiler_version, binary}
|
||||||
|
, {payable, bool} ].
|
||||||
|
|
35
test/aeser_contract_code_tests.erl
Normal file
35
test/aeser_contract_code_tests.erl
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
-module(aeser_contract_code_tests).
|
||||||
|
|
||||||
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
-include("aeser_contract_code.hrl").
|
||||||
|
|
||||||
|
-define(DUMMY_CODE_MAP_1,
|
||||||
|
#{ byte_code => <<"DUMMY CODE">>
|
||||||
|
, type_info => [{<<>>, <<>>, <<>>, <<>>}]
|
||||||
|
, contract_source => "contract Foo = ..." }).
|
||||||
|
|
||||||
|
-define(DUMMY_CODE_MAP_2,
|
||||||
|
#{ byte_code => <<"DUMMY CODE">>
|
||||||
|
, type_info => [{<<>>, <<>>, <<>>, <<>>}]
|
||||||
|
, compiler_version => <<"3.1.4">>
|
||||||
|
, source_hash => <<1, 2, 3, 4>> }).
|
||||||
|
|
||||||
|
-define(DUMMY_CODE_MAP_3,
|
||||||
|
#{ byte_code => <<"DUMMY CODE">>
|
||||||
|
, type_info => [{<<>>, <<>>, false, <<>>, <<>>}]
|
||||||
|
, compiler_version => <<"3.1.4">>
|
||||||
|
, contract_source => "contract Foo = ..."
|
||||||
|
, payable => true} ).
|
||||||
|
|
||||||
|
vsn_1_test() ->
|
||||||
|
aeser_contract_code:deserialize(
|
||||||
|
aeser_contract_code:serialize(?DUMMY_CODE_MAP_1, ?SOPHIA_CONTRACT_VSN_1)).
|
||||||
|
|
||||||
|
vsn_2_test() ->
|
||||||
|
aeser_contract_code:deserialize(
|
||||||
|
aeser_contract_code:serialize(?DUMMY_CODE_MAP_2, ?SOPHIA_CONTRACT_VSN_2)).
|
||||||
|
|
||||||
|
vsn_3_test() ->
|
||||||
|
aeser_contract_code:deserialize(
|
||||||
|
aeser_contract_code:serialize(?DUMMY_CODE_MAP_3, ?SOPHIA_CONTRACT_VSN_3)).
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user