Skip to content

Conversation

ryanofsky
Copy link
Contributor

@ryanofsky ryanofsky commented Feb 8, 2024

Changes making it possible to call interface::Chain over a socket.

Note: The changes in this PR allow a bitcoin-node process to be controlled over a socket. The socket can either be an UNIX socket created by specifying the -ipcbind option, or it can be a socketpair created by a controlling process and passed to bitcoin-node via the -ipcfd=<n> with a file descriptor number. This PR is a dependency of #10102 which allows the wallet code to run in a separate process and use the Chain interface.


This PR is part of the process separation project.

@DrahtBot
Copy link
Contributor

DrahtBot commented Feb 8, 2024

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

Code Coverage & Benchmarks

For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/29409.

Reviews

See the guideline for information on the review process.

Type Reviewers
Concept ACK josibake, darosior
Stale ACK TheCharlatan
User requested bot ignore cbergqvist

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

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #32297 (bitcoin-cli: Add -ipcconnect option by ryanofsky)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@ryanofsky ryanofsky mentioned this pull request Feb 8, 2024
87 tasks
@ryanofsky ryanofsky marked this pull request as ready for review February 8, 2024 14:04
@DrahtBot
Copy link
Contributor

DrahtBot commented Feb 8, 2024

🚧 At least one of the CI tasks failed. Make sure to run all tests locally, according to the
documentation.

Possibly this is due to a silent merge conflict (the changes in this pull request being
incompatible with the current code in the target branch). If so, make sure to rebase on the latest
commit of the target branch.

Leave a comment here, if you need help tracking down a confusing failure.

Debug: https://github.com/bitcoin/bitcoin/runs/21365328047

Copy link
Contributor

@cbergqvist cbergqvist left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm eager for multiprocess to get in, but unable to do in-depth reviews in tolerable time due to lack of domain-knowledge. Did a surface level review of 2fd1042. Hope you don't mind.

Copy link
Contributor Author

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review!

Updated 2fd1042 -> 41831ab (pr/ipc-chain.2 -> pr/ipc-chain.3, compare) with suggested changes.

Copy link
Contributor

@cbergqvist cbergqvist left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for incorporating some of my suggestions. Surface-level ACK of 41831ab. :)

Copy link

@ariard ariard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

being able to work with any socket (TCP or UNIX) makes a lot of sense.
you could have bitcoin-node on some secure computing host.
and then one or more bitcoin-walet on over-the-network hosts.

template<typename S>
auto Wrap(S& s)
{
return ParamsStream{s, TX_WITH_WITNESS, CAddress::V2_NETWORK};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think Wrap could be parameterized with any CAddress version.
e.g useful if someone wanna test the native crypto noise framework between bitcoin processes.
or in the future experiment with better crypto-primitives for bip324.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: #29409 (comment)

i think Wrap could be parameterized with any CAddress version. e.g useful if someone wanna test the native crypto noise framework between bitcoin processes. or in the future experiment with better crypto-primitives for bip324.

For now the Wrap function is basically a workaround for not having a serialization option that says "serialize all the data in this object to a stream, I don't care about the specific serialization format." So the formats here just chosen to preserve all data, and don't really matter otherwise.

But I could imagine use-cases like you are suggesting where we may want to customize which serialization format is used depending on the IPC connection. I think it would not be that hard to do by adding parameters to Wrap, which is not called many places, or by writing different CustomReadField/BuildField overloads which do not call Wrap. For now though the easiest thing is for the wrapped stream to just hardcode parameters that serialize all the data.

@DrahtBot DrahtBot marked this pull request as draft April 17, 2024 17:34
@ryanofsky ryanofsky marked this pull request as ready for review June 11, 2024 01:55
@TheCharlatan
Copy link
Contributor

I'm not sure what a good approach for reviewing this might be. How can I validate the changes without tests? Should I be running this as part of a parent pull request? The first two commits seem fairly mechanical, but the last one less so. The comments in the code are helpful, but some pointers in the PR description for what to look out for, or a broad description of the approaches taken would be helpful too. E.g. why is so much custom functionality introduced for findBlock?

@ryanofsky
Copy link
Contributor Author

re: #29409 (comment)

Thanks for the questions.

I'm not sure what a good approach for reviewing this might be. How can I validate the changes without tests? Should I be running this as part of a parent pull request?

You could test this as part of #10102, and I should probably add some unit test code to ipc_test.cpp to make sure new runtime code in capnp/chain.cpp and capnp/common-types.h functions has test coverage.

Most of the code in the PR is evaluated at compile time though, so for example, if there is a mismatch in any of the interface declarations there will be build errors.

The first two commits seem fairly mechanical, but the last one less so. The comments in the code are helpful, but some pointers in the PR description for what to look out for, or a broad description of the approaches taken would be helpful too.

This is helpful feedback, and I will try to add more comments. I know it needs more comments, but it's hard for me to know where to add them without being asked because I'm too familiar with everything here. This PR is a case where "Don't spend more than a few seconds trying to understand it" review really advice applies, so if something doesn't make sense, you should just ask so I can clarify. If something doesn't make sense to you, it probably doesn't make sense to other people either.

E.g. why is so much custom functionality introduced for findBlock?

Will add a comment, but Chain::findBlock and the handful of other Chain methods taking FoundBlock input/output arguments need custom code because these are converted to FoundBlockParam and FoundBlockResult Cap'n Proto structs to make IPC calls, and these structs are recursive. Libmultiprocess has decent support for converting back and forth between C++ classes and capnp structs generally, but it would be hard for it support recursive structs. It also might have a hard time in this case because there is a not 1:1 mapping between fields in the c++ class and capnp structs. So the conversion for these types is completely custom.

Similar custom code also exists for the C++ BlockInfo struct which is complicated to translate to the Capnp BlockInfo struct, because it has internal pointers and references, so it has custom code because it can't really be converted automatically.

Copy link
Contributor Author

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated ab6b795 -> eec0d31 (pr/ipc-chain.5 -> pr/ipc-chain.6, compare), rebasing and dropping no longer needed code after libmultiprocess update, adding comments and tests, and splitting up commits. There is still more to do to splitting up commits and adding tests, however.

This PR now shares a little bit of code with #30510, so will get smaller if #30510 is merged. #30510 is also simpler and should be easier to review, so will mark this as a draft, although feedback is still welcome on this PR especially if there are questions or things that need more explanation.


re: #29409 (review)

being able to work with any socket (TCP or UNIX) makes a lot of sense. you could have bitcoin-node on some secure computing host. and then one or more bitcoin-walet on over-the-network hosts

Yes this PR does not actually expose a socket but #30509 does, and #19460 uses it for the wallet (and #19461 uses it for the gui, and Sjors#48 and #30437 use it for the mining interface

template<typename S>
auto Wrap(S& s)
{
return ParamsStream{s, TX_WITH_WITNESS, CAddress::V2_NETWORK};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: #29409 (comment)

i think Wrap could be parameterized with any CAddress version. e.g useful if someone wanna test the native crypto noise framework between bitcoin processes. or in the future experiment with better crypto-primitives for bip324.

For now the Wrap function is basically a workaround for not having a serialization option that says "serialize all the data in this object to a stream, I don't care about the specific serialization format." So the formats here just chosen to preserve all data, and don't really matter otherwise.

But I could imagine use-cases like you are suggesting where we may want to customize which serialization format is used depending on the IPC connection. I think it would not be that hard to do by adding parameters to Wrap, which is not called many places, or by writing different CustomReadField/BuildField overloads which do not call Wrap. For now though the easiest thing is for the wrapped stream to just hardcode parameters that serialize all the data.

@ryanofsky ryanofsky marked this pull request as draft July 26, 2024 16:35
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Jun 24, 2025
This fixes behavior reported by Antoine Poinsot <darosior@protonmail.com>
bitcoin#29409 (comment) where if
an IPC client is connected, the node will wait forever for it to disconnect
before exiting.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Jun 24, 2025
This fixes behavior reported by Antoine Poinsot <darosior@protonmail.com>
bitcoin#29409 (comment) where if
an IPC client is connected, the node will wait forever for it to disconnect
before exiting.
Sjors pushed a commit to Sjors/bitcoin that referenced this pull request Jun 27, 2025
This fixes behavior reported by Antoine Poinsot <darosior@protonmail.com>
bitcoin#29409 (comment) where if
an IPC client is connected, the node will wait forever for it to disconnect
before exiting.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Jul 1, 2025
This fixes behavior reported by Antoine Poinsot <darosior@protonmail.com>
bitcoin#29409 (comment) where if
an IPC client is connected, the node will wait forever for it to disconnect
before exiting.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Jul 1, 2025
This fixes behavior reported by Antoine Poinsot <darosior@protonmail.com>
bitcoin#29409 (comment) where if
an IPC client is connected, the node will wait forever for it to disconnect
before exiting.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Jul 1, 2025
This fixes behavior reported by Antoine Poinsot <darosior@protonmail.com>
bitcoin#29409 (comment) where if
an IPC client is connected, the node will wait forever for it to disconnect
before exiting.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Jul 1, 2025
This fixes behavior reported by Antoine Poinsot <darosior@protonmail.com>
bitcoin#29409 (comment) where if
an IPC client is connected, the node will wait forever for it to disconnect
before exiting.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Jul 1, 2025
This fixes behavior reported by Antoine Poinsot <darosior@protonmail.com>
bitcoin#29409 (comment) where if
an IPC client is connected, the node will wait forever for it to disconnect
before exiting.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Jul 1, 2025
This fixes behavior reported by Antoine Poinsot <darosior@protonmail.com>
bitcoin#29409 (comment) where if
an IPC client is connected, the node will wait forever for it to disconnect
before exiting.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Jul 1, 2025
This fixes behavior reported by Antoine Poinsot <darosior@protonmail.com>
bitcoin#29409 (comment) where if
an IPC client is connected, the node will wait forever for it to disconnect
before exiting.
@zaidmstrr
Copy link
Contributor

The method rpcRunLater was removed in commit, thus there are some build errors.

ryanofsky and others added 4 commits July 23, 2025 11:44
- Add capnp ToBlob, ToArray, Wrap, Serialize, and Unserialize helper functions
- Add support for std::chrono::seconds capnp serialization
- Add support for util::Result capnp serialization
Expose Chain interface to external processes spawning or connecting to
bitcoin-node.
@ryanofsky
Copy link
Contributor Author

Rebased f92422e -> c0d9515 (pr/ipc-chain.14 -> pr/ipc-chain.15, compare) to fix silent merge conflict with #32862 and spelling error. (Thanks zaidmstrr and maflcko for pointing these out!)

@maflcko
Copy link
Member

maflcko commented Jul 24, 2025

For reference, the lint task still fails. Not sure if this is intentional or if you missed it.

@ryanofsky
Copy link
Contributor Author

re: #29409 (comment)

For reference, the lint task still fails. Not sure if this is intentional or if you missed it.

Thanks! The lint task was failing in https://cirrus-ci.com/task/5047676548415488 because the subtree was modified. The subtree was modified to work around a bug fixed in bitcoin-core/libmultiprocess#181 which is part of #32345 but not currently part of master. Implemented a different workaround for now.


Updated c0d9515 -> b372063 (pr/ipc-chain.15 -> pr/ipc-chain.16, compare) to fix failing lint task

ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Aug 8, 2025
This fixes behavior reported by Antoine Poinsot <darosior@protonmail.com>
bitcoin#29409 (comment) where if
an IPC client is connected, the node will wait forever for it to disconnect
before exiting.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Aug 8, 2025
This fixes behavior reported by Antoine Poinsot <darosior@protonmail.com>
bitcoin#29409 (comment) where if
an IPC client is connected, the node will wait forever for it to disconnect
before exiting.
Sjors pushed a commit to Sjors/bitcoin that referenced this pull request Aug 12, 2025
This fixes behavior reported by Antoine Poinsot <darosior@protonmail.com>
bitcoin#29409 (comment) where if
an IPC client is connected, the node will wait forever for it to disconnect
before exiting.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: In progress
Development

Successfully merging this pull request may close these issues.