-
Notifications
You must be signed in to change notification settings - Fork 36.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Faster way to get block with prevouts in JSON-RPC #30495
Comments
There are a few strategies to speed this up on the client side instead:
Setting |
#30595 mentions "Traversing the block index as well and using block index entries for reading block and undo data." However, it does not return JSON-RPC, but a |
I also noticed using To investigate further, I conducted a benchmark on a VPS with specs:
I used a script to retrieve 1000 blocks starting at block
Benchmark Results Verbosity 1
Verbosity 2
Verbosity 3
The benchmark results showed a ~27.4% reduction in execution time when using parallel threading, which confirms the potential of client using threading to improve speed. I reviewed the edit Adding a |
@ismaelsadeeq nice find! I wonder, could you also benchmark batch requests? Sending a single request that contains |
I think there are two separate topics here:
For 1., @vostrnad have you seen #30595 ? For the specific ask of prevouts, I'm almost certain this will always be faster since the the kernel API provides the prevouts by reading the rev.dat files (admittedly, I haven't looked into how this is done with the Here is an example program I wrote using the kernel API via rust bindings: https://github.com/josibake/silent-payments-scanner/blob/74f883c370a26e2eaa5a1a7e8e18643e07ce2cff/src/scanner.rs#L135 I found this very easy to write and incredibly performant. The nice thing about using the kernel API for this is you can use whatever language you want (so long as that language supports C-bindings), and it does not require a running For experimenting / testing the API, there is https://github.com/theCharlatan/rust-bitcoinkernel, and I've also been meaning to create some python bindings, as well. If this is of interest to you, I'd be happy to explain more and of course would love your feedback on the C API PR. |
Thank you, @josibake, for highlighting this! I was able to perform some benchmarks to evaluate the performance you claimed of using
As you claimed, this is indeed more performant. Benchmark Results:I used the libbitcoinkernel library to imitate extracting block data for the same interval block heights 840000 to 841000, the average execution times are as follows:
For the Python bindings, I suspect the inefficiency arises from the deserialization process handled by https://github.com/petertodd/python-bitcoinlib because without the deserialization, the execution time drops significantly to around 62 seconds, which is much closer to the Rust result. The block data returned by these methods is equivalent to the But this approach has some downside I think:
The language bindings (Rust and Python) make it straightforward to build blockchain parsers and other applications, which is a significant advantage. However, this should not deter us from improving the performance of RPC calls, as they remain a widely-used interface for clients. Any chance to optimizing performance like #31490 #31539 #31179 would benefit a broader range of users.. I think this result is convincing enough to close this issue @vostrnad |
By adding a new REST endpoint for fetching block prevouts, it seems that we can get quite a good throughput rate when reading the data concurrently (tested with
@vostrnad WDYT? |
I am also interested in this. Even getrawblock response take 2-5 seconds depending on block size, which is very high. Few low hanging fruits that can be implemented:
|
This is a common request, but requires replacing libevent, which I'm working on: #31194 |
I often need to process the whole blockchain (or a large part of it) using an external script/program, for which I need blocks with prevout information included. However, the only current way to get that is
getblock <hash> 3
, which includes a lot of potentially unnecessary data and is quite slow, mainly (based on my experiments) because ofUniValue
overhead and descriptor inferring.I benchmarked current master, retrieving 1000 blocks sequentially starting at block 840000, with different
verbosity
parameters:As you can see, verbosity=3 is around 30 times slower than verbosity=0. It seems obvious that a faster way of getting blocks with prevout information is feasible.
Potential solutions that come to mind:
getblockundo
. This would be perfect for my needs, but it would require making the undo data serialization format non-internal (not sure if this would be a problem, as IIRC it hasn't changed in many years).getblock
that would only provide the minimum amount of data necessary (i.e. no addresses, descriptors, ASM scripts, TXIDs/WTXIDs etc.) while still providing prevouts. This would be better than nothing but would still leave a lot of performance on the table because ofUniValue
overhead.The text was updated successfully, but these errors were encountered: