diff --git a/src/hz.erl b/src/hz.erl index bc49137..c76f82c 100644 --- a/src/hz.erl +++ b/src/hz.erl @@ -793,20 +793,43 @@ contract_code(ID) -> end. --spec contract_source(ID) -> {ok, Bytecode} | {error, Reason} +-spec contract_source(ID) -> Result +-spec contract_source(ID) -> {ok, Source} | {binary, Binary} | {error, Reason} when ID :: contract_id(), - Bytecode :: contract_byte_array(), + Result :: {ok, Source :: unicode:unicode_binary()} + | {archive, Archive :: list()} + | {binary, Binary :: binary()} + | {error, Reason}, Reason :: chain_error() | string(). %% @doc %% Retrieve the code of a contract as represented on chain. contract_source(ID) -> case request(["/v3/contracts/", ID, "/source"]) of - {ok, #{"source" := Source}} -> {ok, Source}; + {ok, #{"source" := Source}} -> maybe_gunzip(Source); {ok, #{"reason" := Reason}} -> {error, Reason}; Error -> Error end. +% NOTE: +% What we eventually want is a way to package entire projects as archives and have a new +% return like {archive, Binary} or maybe {archive, Structure}. +maybe_gunzip(Binary = <<16#1F, 16#8B, _/binary>>) -> + try + Uncompressed = zlib:gunzip(Binary), + case io_lib:printable_unicode_list(unicode:characters_to_list(Uncompressed)) of + true -> {ok, Uncompressed}; + false -> {binary, Uncompressed} + end + catch + _:_ -> {binary, Source} + end; +maybe_gunzip(Source) -> + case io_lib:printable_unicode_list(unicode:characters_to_list(Source)) of + true -> {ok, Source}; + false -> {binary, Source} + end. + -spec contract_poi(ID) -> {ok, Bytecode} | {error, Reason} when ID :: contract_id(), @@ -1156,7 +1179,16 @@ assemble_calldata(CreatorID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallDa assemble_calldata2(OwnerID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallData) -> Code = gmser_contract_code:serialize(Compiled), - Source = unicode:characters_to_binary(maps:get(contract_source, Compiled, <<>>)), + Binary = + case maps:get(project, Compiled, false) of + false -> + case unicode:characters_to_binary(maps:get(contract_source, Compiled, <<>>)) of + <<>> -> <<>>; + Source -> zlib:gzip(Source) + end; + Project -> + archive(Project) + end, VM = 1, ABI = 1, <> = <>, @@ -1166,7 +1198,7 @@ assemble_calldata2(OwnerID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallDat [{owner_id, gmser_id:create(account, OwnerID)}, {nonce, Nonce}, {code, Code}, - {source, Source}, + {source, Binary}, {ct_version, CTVersion}, {ttl, TTL}, {deposit, 0}, @@ -1193,6 +1225,12 @@ assemble_calldata2(OwnerID, Nonce, Amount, TTL, Gas, GasPrice, Compiled, CallDat error:Reason -> {error, Reason} end. +archive(Project) -> + TempFile = temp_file(), + ok = erl_tar:create(TempFile, Project, [compressed, dereference]), + {ok, Bytes} = file:read_file(TempFile), + Bytes. + -spec read_aci(Path) -> Result when Path :: file:filename(),