Skip to content

hb_store_lmdb: committed message's commitments sub-group not listable (breaks ~query@1.0/graphql by-id) #1000

Description

@mbarispaksoy

Summary

hb_store_lmdb does not make a committed message's commitments sub-group children listable, while hb_store_fs does. Same message, same write path (hb_message:commit + hb_cache:write), only the store backend differs. This breaks dev_query_arweave:all_signed_ids, so ~query@1.0/graphql transaction(id) / transactions(ids: [...]) queries return null on any lmdb-backed node — even though the message is fully written, readable, and its top-level group lists fine.

Reproduction (no gateway/copycat needed)

W = ar_wallet:new(),
Msg = #{ <<"kx">> => <<"vv">> },
Test = fun(Store) ->
    Opts = #{ store => Store, priv_wallet => W },
    C = hb_message:commit(Msg, Opts),
    {ok, _} = hb_cache:write(C, Opts),
    ID = hb_message:id(C, all, #{ store => Store }),
    { hb_store:list(Store, <<ID/binary, "/commitments">>),
      hb_store:type(Store, <<ID/binary, "/commitments">>) }
end,
Fs   = [#{ <<"store-module">> => hb_store_fs,   <<"name">> => <<"/tmp/cmpfs">> }],
Lmdb = [#{ <<"store-module">> => hb_store_lmdb, <<"name">> => <<"/tmp/cmplm">> }],
{ fs, Test(Fs), lmdb, Test(Lmdb) }.

Result:

{ fs,   {{ok, [_CommitmentID]}, composite},
  lmdb, {{ok, []},              not_found} }

For the same committed message:

  • hb_store:list(Store, "<id>") returns the message keys (incl. "commitments") on both backends.
  • hb_cache:read/2 reconstructs the commitments map on both.
  • hb_store:resolve(Store, "<id>/commitments") resolves to a real content-addressed id on both.
  • But hb_store:list(Store, "<id>/commitments") returns the commitment children on fs and {ok, []} on lmdb, and hb_store:type of that path is composite on fs vs not_found on lmdb.

Impact

dev_query_arweave:all_signed_ids/3:

case hb_store:list(Store, <<ResolvedID/binary, "/commitments">>) of
    {ok, CommitmentIDs} -> lists:filter(...);   %% lmdb: {ok, []} -> filter([]) -> []
    _ -> [ID]                                   %% fs: not_found -> fallback works
end

On lmdb the empty {ok, []} takes the filter branch → returns [] → the resolver yields 0 edges → transaction(id) returns null. On fs, list returns not_found, hitting the [ID] fallback → works. So graphql by-id lookups are effectively broken on lmdb-backed nodes (the common production config).

Suggested fixes (either)

  1. hb_store_lmdb:list/2 should return not_found for a non-existent path (consistent with hb_store:type and with hb_store_fs), rather than {ok, []}. and/or
  2. Make hb_store_lmdb list the children of a committed message's commitments group (parity with hb_store_fs).
  3. Defensive: dev_query_arweave:all_signed_ids could treat {ok, []} like not_found and fall back to [ID].

Environment

  • Branch feat/community-node @ 79bfffd0, genesis_wasm release.
  • elmdb 0.1.0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions