-
Notifications
You must be signed in to change notification settings - Fork 64
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
fix: fix batch ordering issue #160
base: master
Are you sure you want to change the base?
fix: fix batch ordering issue #160
Conversation
@marshallyale thanks for identifying and working on this. Please rebase your branch since I just merged #159 which changes this projects MSRV and CI checks. Also you have a few clippy errors that need to be fixed. We'll need to give time to get it reviewed, so be patient with getting this merged. 🙂 |
Fixes issue bitcoindevkit#75 Raw client waiting map was using the same channel for every request/response. When items were put back into the channel inside of _reader_thread the waiting receiver in recv would just take the next response without validating it on request id request. This fixes this by using unique channels for each request response inside of the waiting map.
8c98446
to
2d3f4a5
Compare
No worries, I should have just rebased and pushed this. I'm working off my forked repo currently so there's no rush on getting any changes synced. Let me know if there's anything else I need to change! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this fix!
I've reviewed the issue and proposed changes, it seems it's a library problem as it's not management and matching context between requests and responses, as the response for a batch call may be out of ordered (as per JSON-RPC spec).
Using an exclusive channel for each request in a batch, solves the problem, however I'm trying to think about any shortcomings of that approach.
I'm taking another look at this one this week, and I think it's best to come up with two |
I think the unique channels approach in this PR is a valid solution. Perhaps an alternative would be to change |
Fixes issue #75
This is my first open source pull request so I apologize for any formatting issues. Additionally, I don't know the repository as well as others so there may be a better way to implement the fix.
I believe I found the root cause of this. I added a pull request to fix, but I'm going to copy/paste what I believe is causing the error.
The main issue in the code is inside raw_client.rs inside the
recv
method implementation (snippet below):rust-electrum-client/src/raw_client.rs
Lines 671 to 685 in 805ea0a
When this is first called, the
self._reader_thread
will run. Inside theself._reader_thread
, if the request id matches the response id, everything works fine. However, if the request id does not match the response id, we run the following code:rust-electrum-client/src/raw_client.rs
Lines 602 to 612 in 805ea0a
The channel that the response is sent back into is not unique, but rather all the channels share the same sender.clone() and receiver. The only validation that is done is to check that the request id is still being searched for inside
self.waiting_map
. This means that the receiver channel receives whatever the next response is into the channel without any validation that it matches the request id which happens herematch receiver.recv()?
.This is fixed by implementing unique channels for every request id. This fix can be verified with the code @johnzweng used to show the issue
If you run this with the initial code, it will error out after 1-10 cycles normally. However, after the fix this runs indefinitely.