rust-bitcoin / rust-bitcoincore-rpc

Rust RPC client library for the Bitcoin Core JSON-RPC API.
343 stars 258 forks source link

RFC: Total refactor to support sync & async clients #294

Open stevenroose opened 1 year ago

stevenroose commented 1 year ago

This is a reboot of https://github.com/rust-bitcoin/rust-bitcoincore-rpc/pull/212.

So this turned into an insane amount of changes that I've been working on on and off for the last several years.

The current state of things is

Some highlights of the changes:

As for review, I realize the changes are massive and I believe it makes more sense to first review the new code as is, looking at requests.rs, sync_client.rs, async_client.rs and maybe client.rs. And only then review changes to maybe integration_test/src/main.rs to check if nothing accidentally got removed.

By way of not forgetting, I keep a todo.md file inside the branch so that I don't lose them, current items are:

Kixunil commented 1 year ago

Perhaps it'd make sense to upgrade to bitcoin 0.30 first and hen do this PR? Also I just remembered setting version to 1.0.0 is literally wrong because this crate has an unstable dependency in public API: bitcoin.

Kixunil commented 1 year ago
  • Many argument types have been generalized, so you can easily pass &Transaction, &Vec<u8> or &str as arguments for txs f.e.. Same for blocks, addresses, PSBTs and sighash types.

Also this looks like a footgun unless it's explicit. (didn't check)

stevenroose commented 1 year ago

Perhaps it'd make sense to upgrade to bitcoin 0.30 first and hen do this PR?

That already happened in master.

Also I just remembered setting version to 1.0.0 is literally wrong because this crate has an unstable dependency in public API: bitcoin.

What do you mean with an unstable dependency? The 0.x in just a convention.. rust-miniscript has major versions and relies on _hashes and secp that have not.. But anyway the version is just a placeholder now, but I wouldn't mind bumping to 1.0.0 either way, this crate will have breaking changes quite often anyway so whether we could 0.x.0 or x.0.0 doesn't make much difference.

stevenroose commented 1 year ago
  • Many argument types have been generalized, so you can easily pass &Transaction, &Vec<u8> or &str as arguments for txs f.e.. Same for blocks, addresses, PSBTs and sighash types.

Also this looks like a footgun unless it's explicit. (didn't check)

It's so that you can pass in hex txs as well. Same for string addresses, etc. You can argue that people should be encouraged to use strong types, and that's what the default return values are, but it's just more efficient to pass in strings, especially if you have methods that allow you to get strings too.

Kixunil commented 1 year ago

Yes, it's a convention that is so common that it's probably best to consider it a rule. 0.x means unstable API - frequent changes, 1+.x means stable API - infrequent changes. It's a shame miniscript got this wrong. Anyway we're trying to push for stabilizing bitcoin or its parts and there's a good chance we could stabilize parts needed here somewhat sooner. But don't expect anything less than a year.

I understand why Vec<u8> (should be &[u8], I guess) or &str are accepted. I just think it should be explicit. Something like RawBytes(b) and HexStr(s).

tcharding commented 1 year ago

Have you considered just having a single Client and using maybe_async to add the async/await stuff?

tcharding commented 1 year ago

I had a read and it looks good to me.

Kixunil commented 1 year ago

@tcharding that one uses feature flags to switch between sync and async which is a horrible approach. NACK from me.

tcharding commented 1 year ago

Not disagreeing just wanting to understand; why is a feature flag approach bad? I can't come up with an example usecase that one would want both an async client and a sync client.

stevenroose commented 1 year ago

@tcharding that one uses feature flags to switch between sync and async which is a horrible approach. NACK from me.

Yeah same opinion.

stevenroose commented 1 year ago

Not disagreeing just wanting to understand; why is a feature flag approach bad? I can't come up with an example usecase that one would want both an async client and a sync client.

Just off the top of my head, not 100% sure this scenario makes sense. But basically it's trivial to turn an async client into a sync one, so a library that somehow doesn't want to support async code (tokio..) could take a sync client as an input and a larger project using async can still pass a sync client (wrapped async one) into that lib. In the feature approach, the sync-only lib wouldn't even compile, or would not be able to compile in the same project as any other lib that uses async-only.

stevenroose commented 1 year ago

Thanks for the review! I'm really wanting to get this out of my head, so I'd like to either get this out as a 1.0.0-rc0 and invite others to help improve from there, or maybe fork into another lib. Or just drop it alltogether.

tcharding commented 1 year ago

Don't you have to push https://github.com/apoelstra/rust-jsonrpc/pull/56 through first? I'm happy to review that if/when in comes off WIP or is it ready to go (excluding rebase on master). To rebase you'll need to add SyncTransport impl for MnreqHttpTransport.

stevenroose commented 1 year ago

I'm seeing them two as a change together though, the jsonrpc change is only useful in function of this MR, if no one wants this or if this will never land there is no point in making the jsonrpc changes.

tcharding commented 1 year ago

The LDK folk want to see async in rust-json so I do not think you'll get any pushback against the changes there being merged. The reason for the quietness is, in my opinion, not negative just neither I nor Andrew care much and no one else seems to review/watch/comment on rust-jsonrpc. If you get the two PRs ready, I'll review them. The LDK folk have been hounding us so this is actually quite useful work. JSONRPC is just not that exciting to me.

apoelstra commented 1 year ago

Agreed, I'd love to have async support in rust-jsonprc and here, but I don't ever use async and I have enough borrowck issues without introducing implicit state machines and Pins everywhere. So I'm not going to write (or review) any code since I never use async.

tcharding commented 1 year ago

Perhaps some of the LDK folk will review it? CC @TheBlueMatt to see if anyone in his crew is psyched enough for this to do reviews.