Skip to content

Treat std::shared_ptr nullptr as empty Data #235

@Sjors

Description

@Sjors

E.g. we have:

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

Which maps to:

submitSolution @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 bitcoin/bitcoin#34020 where I introduce:

virtual std::vector<CTransactionRef> getTransactions(const std::vector<Txid>& txids) = 0;
getTransactions @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;
             }));

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