Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 51 additions & 15 deletions src/ar_bundles.erl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
-export([id/1, id/2, hd/1, member/2, find/2]).
-export([new_item/4, sign_item/2, verify_item/1]).
-export([encode_tags/1, decode_tags/1]).
-export([serialize/1, deserialize/1, serialize_bundle/3]).
-export([serialize/1, deserialize/2, serialize_bundle/3]).
-export([data_item_signature_data/1]).
-include("include/hb.hrl").
-include_lib("eunit/include/eunit.hrl").
Expand Down Expand Up @@ -396,13 +396,13 @@ encode_vint(ZigZag, Acc) ->
%% and *not* a bundle. It may be an item that contains a bundle, though.
%% When deserializing a #tx it is the #tx.data that is deserialized (after
%% consulting the #tx.tags to confirm that data format).
deserialize(not_found) -> throw(not_found);
deserialize(Item) when is_record(Item, tx) ->
maybe_unbundle(Item);
deserialize(Binary) ->
deserialize_item(Binary).

deserialize_item(Binary) ->
deserialize(Item) -> deserialize(Item, #{}).
deserialize(not_found, _Opts) -> throw(not_found);
deserialize(Item, Opts) when is_record(Item, tx) ->
maybe_unbundle(Item, Opts);
deserialize(Binary, Opts) ->
deserialize_item(Binary, Opts).
deserialize_item(Binary, Opts) ->
{SignatureType, Signature, Owner, Rest} = decode_signature(Binary),
{Target, Rest2} = decode_optional_field(Rest),
{Anchor, Rest3} = decode_optional_field(Rest2),
Expand All @@ -418,14 +418,24 @@ deserialize_item(Binary) ->
tags = Tags,
data = Data,
data_size = byte_size(Data)
})
}),
Opts
).

maybe_unbundle(Item) ->
maybe_unbundle(Item, Opts) ->
case dev_arweave_common:type(Item) of
list -> unbundle_list(Item);
binary -> Item;
map -> unbundle_map(Item)
list ->
UnbundleBundles = hb_opts:get(<<"unbundle_bundles">>, true, Opts),
case UnbundleBundles of
true ->
unbundle_list(Item);
false ->
Item
end;
Comment on lines +428 to +434
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the core logic, everything else is making sure Opts is given to the functions.

binary ->
Item;
map ->
unbundle_map(Item)
end.

unbundle_list(Item) ->
Expand Down Expand Up @@ -475,7 +485,7 @@ decode_bundle_items([], <<>>) ->
[];
decode_bundle_items([{_ID, Size} | RestItems], ItemsBin) ->
[
deserialize_item(binary:part(ItemsBin, 0, Size))
deserialize_item(binary:part(ItemsBin, 0, Size), #{})
|
decode_bundle_items(
RestItems,
Expand Down Expand Up @@ -815,7 +825,7 @@ serialize_deserialize_deep_signed_bundle_test() ->
?assert(verify_item(Item3)).

%% @doc Deserialize and reserialize a data item produced by the arbundles JS
%% library. This validates both that we can read an arbundles.js data itme
%% library. This validates both that we can read an arbundles.js data item
%% but also that our data item serialization code is compatible with it.
arbundles_item_roundtrip_test() ->
{ok, Bin} = file:read_file(<<"test/arbundles.js/ans104-item.bundle">>),
Expand Down Expand Up @@ -881,6 +891,32 @@ arbundles_list_bundle_roundtrip_test() ->
?assertEqual(Bin, Reserialized#tx.data),
ok.

%% @doc Do not unbundle bundles if store option <<"unbundle_bundles">>
%% is set to false
arbundles_list_bundle_not_unbundled_roundtrip_test() ->
W = ar_wallet:new(),
{ok, Bin} = file:read_file(<<"test/arbundles.js/ans104-list-bundle.bundle">>),
TX = sign_item(#tx{
format = ans104,
data = Bin,
data_size = byte_size(Bin),
tags = ?BUNDLE_TAGS
}, W),
?event(debug_test, {tx, {explicit, TX}}),
?assert(verify_item(TX)),

Opts = #{<<"unbundle_bundles">> => false},
Deserialized = deserialize(TX, Opts),
?assert(is_binary(Deserialized#tx.data)),
?assert(binary:match(Deserialized#tx.data, <<"first">>) /= nomatch),
?assert(binary:match(Deserialized#tx.data, <<"second">>) /= nomatch),
?assert(binary:match(Deserialized#tx.data, <<"third">>) /= nomatch),

Reserialized = dev_arweave_common:normalize(Deserialized),
?assert(verify_item(Reserialized)),
?assertEqual(Bin, Reserialized#tx.data),
ok.

arbundles_single_list_bundle_roundtrip_test() ->
W = ar_wallet:new(),
{ok, Bin} = file:read_file(<<"test/arbundles.js/ans104-single-list-bundle.bundle">>),
Expand Down
2 changes: 1 addition & 1 deletion src/dev_codec_ans104.erl
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ from(TX, Req, Opts) when is_record(TX, tx) ->
end.
do_from(RawTX, Req, Opts) ->
% Ensure the TX is fully deserialized.
TX = ar_bundles:deserialize(dev_arweave_common:normalize(RawTX)),
TX = ar_bundles:deserialize(dev_arweave_common:normalize(RawTX), Opts),
?event({from, {parsed_tx, TX}}),
% Get the fields, tags, and data from the TX.
Fields = dev_codec_ans104_from:fields(TX, <<>>, Opts),
Expand Down
2 changes: 1 addition & 1 deletion src/dev_codec_tx.erl
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ do_from(RawTX, Req, Opts) ->
% Assert a minimally valid TX record so we can avoid a lot of edge case
% handling in the rest of the code.
enforce_valid_tx(RawTX),
TX = ar_bundles:deserialize(dev_arweave_common:normalize(RawTX)),
TX = ar_bundles:deserialize(dev_arweave_common:normalize(RawTX), Opts),
?event({from, {parsed_tx, hb_util:human_id(TX#tx.id)}}),
% Get the fields, tags, and data from the TX.
Fields = dev_codec_tx_from:fields(TX, <<>>, Opts),
Expand Down
4 changes: 2 additions & 2 deletions src/hb_http.erl
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ outbound_result_to_message(<<"ans104@1.0">>, Status, Headers, Body, Opts) ->
{result_is_ans104, {headers, Headers}, {body, Body}},
Opts
),
try ar_bundles:deserialize(Body) of
try ar_bundles:deserialize(Body, Opts) of
Deserialized ->
{
response_status_to_atom(Status),
Expand Down Expand Up @@ -869,7 +869,7 @@ req_to_tabm_singleton(Req, Body, Opts) ->
),
httpsig_to_tabm_singleton(PrimitiveMsg, Req, Body, Opts);
<<"ans104@1.0">> ->
Item = ar_bundles:deserialize(Body),
Item = ar_bundles:deserialize(Body, Opts),
?event(debug_accept,
{deserialized_ans104,
{item, Item},
Expand Down
9 changes: 7 additions & 2 deletions src/hb_opts.erl
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,16 @@ default_message() ->
<<"value">> => <<"ao">>
}
],
<<"local-store">> => [?DEFAULT_PRIMARY_STORE]
<<"local-store">> => [?DEFAULT_PRIMARY_STORE],
%% By default bundle transactions will be unbundled. This can take some
%% time depending on the bundle size. To avoid the unbundle, set this
%% to false.
<<"unbundle_bundles">> => true
},
#{
<<"store-module">> => hb_store_gateway,
<<"local-store">> => [?DEFAULT_PRIMARY_STORE]
<<"local-store">> => [?DEFAULT_PRIMARY_STORE],
<<"unbundle_bundles">> => true
}
],
priv_store =>
Expand Down