multiprocess: Add basic type conversion hooks #28921

pull ryanofsky wants to merge 3 commits into bitcoin:master from ryanofsky:pr/ipcc changing 9 files +267 −1
  1. ryanofsky commented at 10:12 pm on November 20, 2023: contributor

    Add type conversion hooks to allow UniValue objects, and objects that have CDataStream Serialize and Unserialize methods to be used as arguments and return values in Cap’nProto interface methods. Also add unit test to verify the hooks are working and data can be round-tripped correctly.

    The non-test code in this PR was previously part of #10102 and has been split off for easier review, but the test code is new.


    This PR is part of the process separation project.

  2. DrahtBot commented at 10:12 pm on November 20, 2023: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Code Coverage

    For detailed information about the code coverage, see the test coverage report.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK dergoegge, achow101

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

    Conflicts

    No conflicts as of last run.

  3. ryanofsky renamed this:
    multiprocess: Add basic type conversion hoois
    multiprocess: Add basic type conversion hooks
    on Nov 20, 2023
  4. ryanofsky force-pushed on Nov 20, 2023
  5. DrahtBot added the label CI failed on Nov 20, 2023
  6. DrahtBot removed the label CI failed on Nov 20, 2023
  7. in src/ipc/capnp/common-types.h:66 in 118d60e95c outdated
    61+    // that strips cv references, to prevent this CustomBuildField overload from
    62+    // taking precedence over more narrow overloads for specific LocalTypes.
    63+    typename std::enable_if_t<ipc::capnp::Serializable<LocalType>::value &&
    64+                              std::is_same_v<LocalType, std::remove_cv_t<std::remove_reference_t<LocalType>>>>* enable = nullptr)
    65+{
    66+    CDataStream stream(SER_NETWORK, CLIENT_VERSION);
    


    maflcko commented at 8:00 am on November 21, 2023:
    0    DataStream stream{};
    

    The values are ignored either way, so it seems better to remove them. CDataStream will go away anyway, soon.


    ryanofsky commented at 11:09 am on November 21, 2023:

    re: #28921 (review)

    The values are ignored either way, so it seems better to remove them. CDataStream will go away anyway, soon.

    Thanks, will update. This previously was used to serialize transactions, but now with #28438 that is broken anyway, so I’ll need to find something different to do for transactions.

  8. in src/test/ipc_test.capnp:16 in 118d60e95c outdated
    11+$Proxy.include("test/ipc_test.h");
    12+$Proxy.includeTypes("ipc/capnp/common-types.h");
    13+
    14+interface FooInterface $Proxy.wrap("FooImplementation") {
    15+    add @0 (a :Int32, b :Int32) -> (result :Int32);
    16+    passOutPoint @1 (arg :Data) -> (result :Data);
    


    dergoegge commented at 12:47 pm on November 21, 2023:

    This type of interface where we pass serialized objects (using our serialization) via capnp data obviously fits in quite well with our code base, but I am wondering if this is a nice design for external use? since now anybody using it needs capnp and our serialization format.

    I might have missed prior discussion on this, is the plan to gradually convert more of the interface to native capnp types?


    I really like this conversion glue by the way (i.e. $Proxy.wrap, etc.)! I’ve been working on a clone of https://github.com/google/libprotobuf-mutator for capnp, which I eventually would like to use to fuzz the multi-process interfaces. Conversion from capnp to c++ types is always a bit annoying, so your work on this could integrate quite well I think.


    ryanofsky commented at 2:54 pm on November 21, 2023:

    re: #28921 (review)

    This type of interface where we pass serialized objects (using our serialization) via capnp data obviously fits in quite well with our code base, but I am wondering if this is a nice design for external use? since now anybody using it needs capnp and our serialization format.

    I think the choice will vary on a case-by-case basis. If you look at chain.capnp, node.capnp, wallet.capnp you’ll see a lot of custom capnp structs being defined and used to send data, but types that support bitcoin serialization are just being passed as Data fields, and some types that support JSON serialization are being passed as Text fields. Using pre-existing serialization formats is nice because it saves code, but the resulting nested data format is not very pretty, and like you say it basically makes writing internal code easier at the expense of making writing external code harder. I think as long as we consider the API unstable and willing to break it, the best thing to do is start with a simple implementation and improve it later. There are other parts of the API that are unwieldy too (like basically the whole Chain interface) so I expect there will be a lot of chances to make improvements.

  9. ryanofsky force-pushed on Nov 21, 2023
  10. ryanofsky commented at 7:28 pm on November 21, 2023: contributor
    Updated 42a51f8939200845c1702b3029377ebcf0aa3610 -> 118d60e95cc5c8c0d5a88c0d16904355c7e0c5f6 (pr/ipcc.1 -> pr/ipcc.2, compare) fixing lint error and making minor cleanups Updated 118d60e95cc5c8c0d5a88c0d16904355c7e0c5f6 -> 33d796411dd4d8098287e1307f1337b6e2eab3e7 (pr/ipcc.2 -> pr/ipcc.3, compare) replacing CDataStream with DataStream as suggested and making minor cleanups Updated 33d796411dd4d8098287e1307f1337b6e2eab3e7 -> a506148b7a7058b4c60e5c497e70688134ee9a3f (pr/ipcc.3 -> pr/ipcc.4, compare) to try to fix MSVC link error https://github.com/bitcoin/bitcoin/actions/runs/6948636857/job/18905029537?pr=28921
  11. ryanofsky force-pushed on Nov 21, 2023
  12. in src/ipc/capnp/common-types.h:64 in 3315f33e7c outdated
    58+    // qualified. If LocalType is cv or reference qualified, it is important to
    59+    // fall back to lower-priority Priority<0> implementation of this function
    60+    // that strips cv references, to prevent this CustomBuildField overload from
    61+    // taking precedence over more narrow overloads for specific LocalTypes.
    62+    std::enable_if_t<ipc::capnp::Serializable<LocalType>::value &&
    63+                     std::is_same_v<LocalType, std::remove_cv_t<std::remove_reference_t<LocalType>>>>* enable = nullptr)
    


    dergoegge commented at 12:49 pm on November 22, 2023:

    I’m gonna try to summarize my understanding of this to make sure I actually got it right.

    We want this specialization of CustomBuildField for (most) of our serializable types. So we can either define it manually for each type or we can make use of sfinae (like you do here) to automatically only create the specialization for each of the required serializable types.

    We also want to be able to further overload CustomBuildField for serializable types that can’t use this generic specialization (e.g. if we need to use TX_WITH_WITNESS), so we specify Priority<1> such that another overload with Priority<2> would take precedence.

    What I don’t understand is making this exclusive to non cv and reference qualified types.

    If LocalType is cv or reference qualified, it is important to fall back to lower-priority Priority<0> … to prevent this CustomBuildField overload from taking precedence

    As I understand it, this comment implies that (without && std::is_same_v<LocalType, std::remove_cv_t<std::remove_reference_t<LocalType>>>) the following would not take precedence, even though it has Priority<2>?

    0template <typename LocalType, typename Output>
    1void CustomBuildField(TypeList<LocalType>, Priority<2>, InvokeContext& invoke_context, const CTransaction& value, Output&& output)
    2{
    3    DataStream stream;
    4    stream << TX_WITH_WITNESS(value);
    5    auto result = output.init(stream.size());
    6    memcpy(result.begin(), stream.data(), stream.size());
    7}
    

    ryanofsky commented at 3:29 pm on November 22, 2023:

    As I understand it, this comment implies that (without && std::is_same_v<LocalType, std::remove_cv_t<std::remove_reference_t<LocalType>>>) the following would not take precedence, even though it has Priority<2>?

    0template <typename LocalType, typename Output>
    1void CustomBuildField(TypeList<LocalType>, Priority<2>, InvokeContext& invoke_context, const CTransaction& value, Output&& output)
    

    Yes that’s right, but it would be more correct to say “would not reliably take precedence”. For example, in the case where a const CTransaction argument was passed then the Priority<2> function actually would take precedence, but if a non-const CTransaction were passed the precedence would be ambiguous. This is because if you passed a non-const CTransaction, the types of the two functions after template type deduction would be:

    0void CustomBuildField(TypeList<LocalType>, Priority<1>, InvokeContext&, CTransaction&, Output&& output);
    1void CustomBuildField(TypeList<LocalType>, Priority<2>, InvokeContext&, const CTransaction&, Output&& output);
    

    So with a non-const CTransaction argument, it would be ambiguous whether to call the Priority<2> function that requires a const conversion, or a Priority<1> function not requiring a const-conversion, and there would be a compile error about the overload being ambiguous.

  13. dergoegge approved
  14. dergoegge commented at 10:10 am on November 23, 2023: member

    Code review ACK a506148b7a7058b4c60e5c497e70688134ee9a3f

    CI failure looks spurious.

  15. test: add ipc test to test multiprocess type conversion code
    Add unit test to test IPC method calls and type conversion between bitcoin c++
    types and capnproto messages.
    
    Right now there are custom type hooks in bitcoin IPC code, so the test is
    simple, but in upcoming commits, code will be added to convert bitcoin types to
    capnproto messages, and the test will be expanded.
    4aaee23921
  16. multiprocess: Add type conversion code for serializable types
    Allow any C++ object that has Serialize and Unserialize methods and can be
    serialized to a bitcoin CDataStream to be converted to a capnproto Data field
    and passed as arguments or return values to capnproto methods using the Data
    type.
    
    Extend IPC unit test to cover this and verify the serialization happens
    correctly.
    0cc74fce72
  17. multiprocess: Add type conversion code for UniValue types
    Extend IPC unit test to cover this and verify the serialization happens
    correctly.
    6acec6b9ff
  18. ryanofsky force-pushed on Nov 28, 2023
  19. ryanofsky commented at 9:41 pm on November 28, 2023: contributor
    Rebased a506148b7a7058b4c60e5c497e70688134ee9a3f -> 6acec6b9ff02b91de132bb1575d75908a8a2d27b (pr/ipcc.4 -> pr/ipcc.5, compare) due to silent conflicts with #28922 and #28912
  20. dergoegge approved
  21. dergoegge commented at 10:07 am on November 29, 2023: member
    reACK 6acec6b9ff02b91de132bb1575d75908a8a2d27b
  22. DrahtBot added the label CI failed on Jan 16, 2024
  23. achow101 commented at 9:15 pm on January 23, 2024: member
    ACK 6acec6b9ff02b91de132bb1575d75908a8a2d27b
  24. achow101 merged this on Jan 23, 2024
  25. achow101 closed this on Jan 23, 2024


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-07-01 13:12 UTC

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