Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
0f8c0dc
wip: normalize unsigned ID gen for ANS104
samcamwilliams Nov 20, 2025
9c54682
wip: handle commitments on empty messages
JamesPiechota Nov 20, 2025
e182ea9
wip: hb_message_test_vectors pass
JamesPiechota Nov 20, 2025
17963c1
wip: more unsigned commitment fixes
JamesPiechota Nov 20, 2025
a656b98
wip: dev_codec_ans104 passes
JamesPiechota Nov 20, 2025
028c756
fix: some TX codec tests
samcamwilliams Nov 21, 2025
79cb95f
fix: hb_message_test_vectors
JamesPiechota Nov 21, 2025
33927ba
fix: dev_bundler_xxx tests pass
JamesPiechota Nov 21, 2025
e3d6722
fix: trusted-keys logic doesn't discard additional commitments
JamesPiechota Nov 21, 2025
8795fbc
fix: add trusted-keys to all commitments
JamesPiechota Nov 21, 2025
e36b7c0
fix: dev_query_test_vectors test fix
JamesPiechota Nov 21, 2025
4c28f23
fix: query-by-id
samcamwilliams Nov 24, 2025
af30c92
fix: add the default commitment (httpsig unsigned) to ans104 and tx
JamesPiechota Nov 25, 2025
354bcdd
wip: graphql query only returns matching ids
JamesPiechota Nov 25, 2025
4e21a82
wip: add `committer` field to unsigned ans104 and tx commitments so t…
JamesPiechota Nov 25, 2025
10b1d82
fix: revert earlier `committer => ID` change, remove unsigned IDs fro…
JamesPiechota Nov 25, 2025
64d52ec
fix: revert change to add default commitment
JamesPiechota Nov 25, 2025
f930bd6
wip: use all known unsigned IDs when `committers: none`
samcamwilliams Dec 2, 2025
7a88d63
fix: revert change to filter unsigned messages from graphql
JamesPiechota Dec 2, 2025
6dbafdd
fix: fix hb_store_gateway:remote_hyperbeam_node_ans104_test
JamesPiechota Dec 2, 2025
42c1e3d
fix: revert "use all knonw unsigned IDs", update tests
JamesPiechota Dec 2, 2025
576e9b2
fix: speed up dev_bundler tests
JamesPiechota Dec 2, 2025
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
50 changes: 32 additions & 18 deletions src/dev_bundler.erl
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,9 @@ tx_error_test() ->
?assertMatch({ok, _}, post_data_item(Node, Item1, ClientOpts)),
% After a tx request fails it should be retried indefinitely. We'll
% wait for a few retries then continue.
TXs = hb_mock_server:get_requests(tx, 4, ServerHandle),
?assert(length(TXs) >= 4),
Chunks = hb_mock_server:get_requests(chunk, 1, ServerHandle),
TXs = hb_mock_server:get_requests(tx, 2, ServerHandle),
?assert(length(TXs) >= 2),
Chunks = hb_mock_server:get_requests(chunk, 1, ServerHandle, 500),
?assertEqual([], Chunks),
ok
after
Expand Down Expand Up @@ -256,7 +256,7 @@ idle_test() ->
try
ClientOpts = #{},
Node = hb_http_server:start_node(NodeOpts#{
bundler_max_idle_time => 10000,
bundler_max_idle_time => 2000,
priv_wallet => hb:wallet(),
store => hb_test_utils:test_store(hb_store_lmdb)
}),
Expand All @@ -265,12 +265,12 @@ idle_test() ->
?assertMatch({ok, _}, post_data_item(Node, Item1, ClientOpts)),
% Wait just to give the server a chance to post a transaction
% (but it shouldn't)
timer:sleep(2000),
timer:sleep(1000),
?assertEqual(0, length(hb_mock_server:get_requests(tx, 0, ServerHandle))),
?assertEqual(0, length(hb_mock_server:get_requests(chunk, 0, ServerHandle))),
% Wait gain to give the server a chance to trip the max idle time.
% It should *now* post a transaction.
timer:sleep(8000),
timer:sleep(1000),
TXs = hb_mock_server:get_requests(tx, 1, ServerHandle),
?assertEqual(1, length(TXs)),
%% Wait for expected chunks
Expand All @@ -284,7 +284,7 @@ idle_test() ->
end.

dispatch_blocking_test() ->
BlockTime = 10000,
BlockTime = 2000,
Anchor = rand:bytes(32),
Price = 12345,
% NodeOpts redirects arweave gateway requests to the mock server.
Expand Down Expand Up @@ -327,7 +327,6 @@ dispatch_blocking_test() ->
{slowest, Slowest}, {max_allowed, 2 * Slowest}
}),
?assert(Time4 =< 2 * Slowest),
timer:sleep(BlockTime),
TXs = hb_mock_server:get_requests(tx, 1, ServerHandle),
?assertEqual(1, length(TXs)),
%% Wait for expected chunks
Expand All @@ -346,24 +345,39 @@ dispatch_blocking_test() ->
recover_unbundled_items_test() ->
Opts = #{store => hb_test_utils:test_store(hb_store_lmdb)},
% Create and cache some items
Item1 = hb_message:convert(new_data_item(1, 10), <<"structured@1.0">>, <<"ans104@1.0">>, Opts),
Item2 = hb_message:convert(new_data_item(2, 10), <<"structured@1.0">>, <<"ans104@1.0">>, Opts),
Item3 = hb_message:convert(new_data_item(3, 10), <<"structured@1.0">>, <<"ans104@1.0">>, Opts),
Item1 = hb_message:convert(
new_data_item(1, 10), <<"structured@1.0">>, <<"ans104@1.0">>, Opts),
Item2 = hb_message:convert(
new_data_item(2, 10), <<"structured@1.0">>, <<"ans104@1.0">>, Opts),
Item3 = hb_message:convert(
new_data_item(3, 10), <<"structured@1.0">>, <<"ans104@1.0">>, Opts),
ok = dev_bundler_cache:write_item(Item1, Opts),
ok = dev_bundler_cache:write_item(Item2, Opts),
ok = dev_bundler_cache:write_item(Item3, Opts),
% Bundle Item2 with a fake TX
FakeTX = ar_tx:sign(#tx{format = 2, tags = [{<<"test">>, <<"tx">>}]}, hb:wallet()),
StructuredTX = hb_message:convert(FakeTX, <<"structured@1.0">>, <<"tx@1.0">>, Opts),
FakeTX = ar_tx:sign(
#tx{format = 2, tags = [{<<"test">>, <<"tx">>}]}, hb:wallet()),
StructuredTX = hb_message:convert(
FakeTX, <<"structured@1.0">>, <<"tx@1.0">>, Opts),
ok = dev_bundler_cache:write_tx(StructuredTX, [Item2], Opts),
% Now recover unbundled items
{RecoveredItems, RecoveredBytes} = recover_unbundled_items(Opts),
?assertEqual(3924, RecoveredBytes),
RecoveredItems2 = [
hb_message:with_commitments(
#{ <<"commitment-device">> => <<"ans104@1.0">> }, Item, Opts)
#{
<<"commitment-device">> => <<"ans104@1.0">>,
<<"type">> => <<"rsa-pss-sha256">>
}, Item, Opts)
|| Item <- RecoveredItems],
?assertEqual(lists:sort([Item1, Item3]), lists:sort(RecoveredItems2)),
WrittenItems = [
hb_message:with_commitments(
#{
<<"commitment-device">> => <<"ans104@1.0">>,
<<"type">> => <<"rsa-pss-sha256">>
}, Item, Opts)
|| Item <- [Item1, Item3]],
?assertEqual(lists:sort(WrittenItems), lists:sort(RecoveredItems2)),
ok.

recover_respects_max_items_test() ->
Expand Down Expand Up @@ -460,11 +474,11 @@ test_api_error(Responses) ->
}),
Item1 = new_data_item(1, floor(2.5 * ?DATA_CHUNK_SIZE)),
?assertMatch({ok, _}, post_data_item(Node, Item1, ClientOpts)),
% Since thre was an error either before or while posting the tx,
% Since there was an error either before or while posting the tx,
% no bundles should be posted and no chunks should be posted.
TXs = hb_mock_server:get_requests(tx, 1, ServerHandle),
TXs = hb_mock_server:get_requests(tx, 1, ServerHandle, 1000),
?assertEqual([], TXs),
Chunks = hb_mock_server:get_requests(chunk, 1, ServerHandle),
Chunks = hb_mock_server:get_requests(chunk, 1, ServerHandle, 1000),
?assertEqual([], Chunks),
% Now that we dispatch asynchronously, an error won't cause the
% Item to remain in the queue. Instead we'll rely on the retry
Expand Down
67 changes: 48 additions & 19 deletions src/dev_bundler_cache.erl
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,14 @@ basic_cache_test() ->
?assertEqual(<<"posted">>, get_tx_status(TX, Opts)),
ok = complete_tx(TX, Opts),
?assertEqual(<<"complete">>, get_tx_status(TX, Opts)),
?assertEqual(TX, read_cache(TXID, <<"tx@1.0">>, Opts)),
?assertEqual(Item, read_cache(ItemID, <<"ans104@1.0">>, Opts)),
?assertEqual(
hb_message:with_commitments(
#{ <<"type">> => <<"rsa-pss-sha256">> }, TX, Opts),
read_cache(TXID, <<"tx@1.0">>, Opts)),
?assertEqual(
hb_message:with_commitments(
#{ <<"type">> => <<"rsa-pss-sha256">> }, Item, Opts),
read_cache(ItemID, <<"ans104@1.0">>, Opts)),
ok.

load_unbundled_items_test() ->
Expand All @@ -278,15 +284,22 @@ load_unbundled_items_test() ->
% Link item2 to a bundle, leave others unbundled
ok = write_tx(TX, [Item2], Opts),
% Load unbundled items
UnbundledItems1 = load_unbundled_items(Opts),
UnbundledItems2 = [
LoadedItems1 = load_unbundled_items(Opts),
LoadedItems2 = [
hb_message:with_commitments(
#{ <<"commitment-device">> => <<"ans104@1.0">> },
Item, Opts) || Item <- UnbundledItems1
Item, Opts) || Item <- LoadedItems1
],
UnbundledItems3 = lists:sort(UnbundledItems2),
?event(debug_test, {unbundled_items, UnbundledItems3}),
?assertEqual(lists:sort([Item1, Item3]), UnbundledItems3),
LoadedItems3 = lists:sort(LoadedItems2),
WrittenItems = [
hb_message:with_commitments(
#{
<<"commitment-device">> => <<"ans104@1.0">>,
<<"type">> => <<"rsa-pss-sha256">>
},
Item, Opts) || Item <- [Item1, Item3]],
?event(debug_test, {loaded_items, LoadedItems3}),
?assertEqual(lists:sort(WrittenItems), LoadedItems3),
ok.

load_bundle_states_test() ->
Expand Down Expand Up @@ -320,23 +333,37 @@ load_bundled_items_test() ->
ok = write_tx(TX1, [Item1, Item2], Opts),
ok = write_tx(TX2, [Item3], Opts),
% Load items for bundle 1
Bundle1Items1 = load_bundled_items(tx_id(TX1, Opts), Opts),
Bundle1Items2 = [
Bundle1LoadedItems1 = load_bundled_items(tx_id(TX1, Opts), Opts),
Bundle1LoadedItems2 = [
hb_message:with_commitments(
#{ <<"commitment-device">> => <<"ans104@1.0">> },
Item, Opts) || Item <- Bundle1Items1
Item, Opts) || Item <- Bundle1LoadedItems1
],
Bundle1Items3 = lists:sort(Bundle1Items2),
?assertEqual(lists:sort([Item1, Item2]), Bundle1Items3),
Bundle1LoadedItems3 = lists:sort(Bundle1LoadedItems2),
Bundle1WrittenItems = [
hb_message:with_commitments(
#{
<<"commitment-device">> => <<"ans104@1.0">>,
<<"type">> => <<"rsa-pss-sha256">>
},
Item, Opts) || Item <- [Item1, Item2]],
?assertEqual(lists:sort(Bundle1WrittenItems), Bundle1LoadedItems3),
% Load items for bundle 2
Bundle2Items1 = load_bundled_items(tx_id(TX2, Opts), Opts),
Bundle2Items2 = [
Bundle2LoadedItems1 = load_bundled_items(tx_id(TX2, Opts), Opts),
Bundle2LoadedItems2 = [
hb_message:with_commitments(
#{ <<"commitment-device">> => <<"ans104@1.0">> },
Item, Opts) || Item <- Bundle2Items1
Item, Opts) || Item <- Bundle2LoadedItems1
],
Bundle2Items3 = lists:sort(Bundle2Items2),
?assertEqual(lists:sort([Item3]), Bundle2Items3),
Bundle2LoadedItems3 = lists:sort(Bundle2LoadedItems2),
Bundle2WrittenItems = [
hb_message:with_commitments(
#{
<<"commitment-device">> => <<"ans104@1.0">>,
<<"type">> => <<"rsa-pss-sha256">>
},
Item, Opts) || Item <- [Item3]],
?assertEqual(lists:sort(Bundle2WrittenItems), Bundle2LoadedItems3),
ok.

new_data_item(Index, SizeOrData, Opts) ->
Expand Down Expand Up @@ -365,7 +392,9 @@ new_tx(Index, Opts) ->
hb_message:convert(TX, <<"structured@1.0">>, <<"tx@1.0">>, Opts).

read_cache(ID, Device, Opts) ->
{ok, Resolved} = hb_ao:resolve(#{ <<"path">> => ID }, Opts),
% {ok, Resolved} = hb_ao:resolve(#{ <<"path">> => ID }, Opts),
{ok, Resolved} = hb_cache:read(ID, Opts),
Loaded = hb_cache:ensure_all_loaded(Resolved, Opts),
?event(debug_test, {loaded, Loaded}),
hb_message:with_commitments(
#{ <<"commitment-device">> => Device }, Loaded, Opts).
9 changes: 8 additions & 1 deletion src/dev_bundler_dispatch.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1001,8 +1001,15 @@ recover_bundles_test() ->
hb_message:with_commitments(
#{ <<"commitment-device">> => <<"ans104@1.0">> }, Item, Opts)
|| Item <- Bundle#bundle.items],
WrittenItems = [
hb_message:with_commitments(
#{
<<"commitment-device">> => <<"ans104@1.0">>,
<<"type">> => <<"rsa-pss-sha256">>
},
Item, Opts) || Item <- [Item1, Item2, Item3]],
?assertEqual(
lists:sort([Item1, Item2, Item3]),
lists:sort(WrittenItems),
lists:sort(RecoveredItems)),
?assertEqual(tx_posted, Bundle#bundle.status),
?assert(hb_message:verify(Bundle#bundle.tx)),
Expand Down
Loading