-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Pause mining during JoinSplit creation #1932
Conversation
Awesome! Is there no way to disable mining via the RPC? (To avoid the scenario where this code would re-enable mining that has been disabled in some other way.) |
So, as best as I understand it, mining is enabled/disabled in the rpc via setgenerate(). If we were to use setgenerate(), we'd have to first check whether mining is enabled with getgenerate(), store that in a flag, disable mining, and then after the joinsplit, re-enable mining if appropriate. I can certainly take that approach (and submit a PR to that effect). I avoided doing that, because it seemed slightly more complex, but also because this approach avoids changing mapArgs, as it would under the above rpc approach. Since mapArgs appears intended to reflect the parameter state set by the user, I wanted to avoid writing code that would change it. Suppose, for example, the user starts a z_sendmany, and then sends an rpc command to disable mining. Under the RPC approach I described above, it's possible that upon the completion of the joinsplit that mining is re-enabled against the wishes of the user. |
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.
Concept ACK, but at least one necessary change.
@@ -697,6 +702,9 @@ bool AsyncRPCOperation_sendmany::main_impl() { | |||
} | |||
|
|||
sign_send_raw_transaction(obj); | |||
#ifdef ENABLE_WALLET | |||
GenerateBitcoins(GetBoolArg("-gen",false), pwalletMain, (int)GetArg("-genproclimit", -1)); |
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.
Should be GetArg("-genproclimit", 1)
to match the documented default for -genproclimit
(see init.cpp
). The defaults in rpcmining.cpp
for setgenerate
and getmininginfo
are inconsistent, and also not actually documented there.
@@ -144,6 +145,10 @@ bool AsyncRPCOperation_sendmany::main_impl() { | |||
|
|||
assert(isfromtaddr_ != isfromzaddr_); | |||
|
|||
#ifdef ENABLE_WALLET |
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.
If #1795 is merged before this PR, change this #ifdef
and the one below to:
#if defined(ENABLE_WALLET) && defined(ENABLE_MINING)
@@ -144,6 +145,10 @@ bool AsyncRPCOperation_sendmany::main_impl() { | |||
|
|||
assert(isfromtaddr_ != isfromzaddr_); | |||
|
|||
#ifdef ENABLE_WALLET | |||
GenerateBitcoins(false, NULL, 0); | |||
#endif |
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.
If #1965 is merged before this PR, change this entire #ifdef
block to:
#ifdef ENABLE_MINING
#ifdef ENABLE_WALLET
GenerateBitcoins(false, NULL, 0);
#else
GenerateBitcoins(false, 0);
#endif
#endif
and likewise below.
📌 Commit 92e4b29 has been approved by |
@zkbot r- |
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.
NACK. Thanks for the PR @aniemerg. After review, I see an issue which blocks this PR and two that are concept NACKs (which we can defer)
- Bug
- Test
- Concept: Addresses Pause mining while doing a JoinSplit #1522 but does it solve the problem?
- Concept: Design Pattern
Let me expand upon these:
- Bug
Mining is halted upon entering the operation's main_impl(). However, mining is only restored at the end of the function when a transaction has been created successfully. There are a bunch of errors that could occur between those two points. If there is an error, mining never restarts. One possible fix for this is to have the stopping and restarting in main(), surrounding the try catch block which calls main_impl().
- Test
Perhaps modify one of the Python qa rpc tests to check that the miner threads are disabled when a JoinSplit is in progress?
- Concept: Addresses Pause mining while doing a JoinSplit #1522 but does it solve the problem?
Ticket #1522 states "when a JoinSplit starts we should cancel all mining threads". This PR patches the async operation used by z_sendmany, but a user could make an rpc call to 'zcbenchmark createjoinsplit' which does not halt mining.
If there are parallel joinsplits, which we can do by re-enabling the option to have multiple async worker threads, there is a race condition where one joinsplit tx completes successfully and re-enables mining, while another joinsplit tx is still being processed.
- Concept: Design Pattern
Why should an async operation care or even know about the miner? We should try to avoid unnecessary coupling between two subsystems. It would be better if the JSDescription class signaled to interested listeners, like the miner, that it was about to generate a JoinSplit and signal again when it has finished (say in JSDescription::Randomized or create a wrapper which we call).
To handle the race condition mentioned in (3), you could use an atomic counter which the halt signal handler will increment and the resume signal handler decrements. At launch state, the counter is 0 which the miner treats as a green light to mine. If there are parallel JoinSplits, the counter will increase but when all the JoinSplits have finished, the counter will be back at 0 and mining can resume.
So next steps...
Please fix (1) and if possible, add a test (2) to confirm that mining threads stop and restart when a JoinSplit is created.
Would be great if you could implement a solution like described in (4). Since that's a bigger chunk of work and other members of the team might have some ideas, that might be best broken off into a new ticket, or added to #1522, and have this PR be a temporary/partial solution to the problem i.e. we leave #1522 open.
@aniemerg Hope the above makes sense, let me know otherwise.
@ebfull Thoughts on above and next steps?
Given the time requirements for 1.0.5 I will need to bump this to 1.0.6. |
We should have a test for this. |
Regarding a test, I've been unsure how to accomplish that using the rpc testing framework. The way that this PR currently works is to turn off mining in a way that isn't revealed when using rpc commands such as getgenerate. So I am not sure how to write the most natural test -- that is, turn on mining, start a joinsplit, and check to see that mining is off. |
Re @bitcartel's point 3, I don't think it's a problem if |
@aniemerg if we can fix @bitcartel's first point, then we'll merge and open another ticket to address point 4. |
@arcalinea commit 54c92a6 was intended to fix @bitcartel 's first point. I believe it still needs review. |
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.
utACK, but please squash when merging.
54c92a6
to
49c2cec
Compare
Squashed the commits. Can we get one more review before merging though? (@str4d?) |
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.
utACK, assuming a new ticket is opened for point 4.
📌 Commit 49c2cec has been approved by |
…alinea Pause mining during JoinSplit creation Closes #1522 .
💡 This pull request was already approved, no need to approve it again.
|
📌 Commit 49c2cec has been approved by |
☀️ Test successful - zcash |
Closes #1522 .