Treat std::shared_ptr nullptr as empty Data #235

issue Sjors opened this issue on December 5, 2025
  1. Sjors commented at 5:24 PM on December 5, 2025: member

    E.g. we have:

    virtual bool submitSolution(uint32_t version, uint32_t timestamp, uint32_t nonce, CTransactionRef coinbase) = 0;
    

    Which maps to:

    submitSolution [@9](/bitcoin-core-multiprocess/contributor/9/) (context: Proxy.Context, version: UInt32, timestamp: UInt32, nonce: UInt32, coinbase :Data) -> (result: Bool);
    

    Which crashes when you pass an empty coinbase.

    I think the solution is to convert an empty Data to nullptr and vice versa.

    That would make my life easier in https://github.com/bitcoin/bitcoin/pull/34020 where I introduce:

    virtual std::vector<CTransactionRef> getTransactions(const std::vector<Txid>& txids) = 0;
    
    getTransactions [@6](/bitcoin-core-multiprocess/contributor/6/) (context :Proxy.Context, txids: List(Data)) -> (result: List(Data));
    

    A quick LLM session suggests this should do the trick:

    diff --git a/src/ipc/libmultiprocess/include/mp/type-pointer.h b/src/ipc/libmultiprocess/include/mp/type-pointer.h
    index 98b7aa817f..af7d42c710 100644
    --- a/src/ipc/libmultiprocess/include/mp/type-pointer.h
    +++ b/src/ipc/libmultiprocess/include/mp/type-pointer.h
    @@ -50,34 +50,40 @@ decltype(auto) CustomReadField(TypeList<std::shared_ptr<LocalType>>,
         ReadDest&& read_dest)
     {
         return read_dest.update([&](auto& value) {
             if (!input.has()) {
                 value.reset();
    +        } else if (input.get().size() == 0) {
    +            value.reset();
             } else if (value) {
                 ReadField(TypeList<LocalType>(), invoke_context, input, ReadDestUpdate(*value));
             } else {
                 ReadField(TypeList<LocalType>(), invoke_context, input,
                     ReadDestEmplace(TypeList<LocalType>(), [&](auto&&... args) -> auto& {
                         value = std::make_shared<LocalType>(std::forward<decltype(args)>(args)...);
                         return *value;
                     }));
             }
         });
     }
    
     template <typename LocalType, typename Input, typename ReadDest>
     decltype(auto) CustomReadField(TypeList<std::shared_ptr<const LocalType>>,
         Priority<1>,
         InvokeContext& invoke_context,
         Input&& input,
         ReadDest&& read_dest)
     {
         return read_dest.update([&](auto& value) {
             if (!input.has()) {
                 value.reset();
                 return;
             }
    +        if (input.get().size() == 0) {
    +            value.reset();
    +            return;
    +        }
             ReadField(TypeList<LocalType>(), invoke_context, std::forward<Input>(input),
                 ReadDestEmplace(TypeList<LocalType>(), [&](auto&&... args) -> auto& {
                     value = std::make_shared<LocalType>(std::forward<decltype(args)>(args)...);
                     return *value;
                 }));
    
  2. Sjors commented at 5:22 AM on January 5, 2026: member

    @ryanofsky do you plan to open a PR for this or should I take your commit from https://github.com/bitcoin/bitcoin/pull/34020#issuecomment-3624001654 and open one?

  3. Sjors commented at 1:08 PM on March 12, 2026: member

    This was done in #242.

  4. Sjors closed this on Mar 12, 2026

Contributors

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin-core/libmultiprocess. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-18 08:30 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me