-
Notifications
You must be signed in to change notification settings - Fork 720
Call wallet/validation notify callbacks in scheduler thread (without cs_main) #2203
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
Changes from all commits
1fa0d70
268be9c
40ed4c4
24a3ce4
f6df6e4
31a8790
c7ab490
7d05997
5f521fd
4d927b0
1c9fe10
51dea23
10efbe5
da7c0f7
31c7974
0c68e2f
cc91d44
0c4642c
596056c
67c754a
c3a281c
0dfebf4
296c956
b9249c5
4ed7024
e6770c8
de3c7ae
815667d
1ed753f
d97ace9
1423dba
756d0fa
65cf7e1
3ace13b
f8cd371
53497f0
bfd9a15
00cc6ec
ded2e8e
046386b
3d11027
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |
| #include "core_io.h" | ||
| #include "init.h" | ||
| #include "keystore.h" | ||
| #include "validationinterface.h" | ||
| #include "net.h" | ||
| #include "policy/policy.h" | ||
| #include "primitives/transaction.h" | ||
|
|
@@ -25,6 +26,7 @@ | |
| #include "wallet/wallet.h" | ||
| #endif | ||
|
|
||
| #include <future> | ||
| #include <stdint.h> | ||
|
|
||
| #include <univalue.h> | ||
|
|
@@ -518,6 +520,10 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) | |
| if (!pwalletMain) | ||
| throw std::runtime_error("wallet not initialized"); | ||
|
|
||
| // Make sure the results are valid at least up to the most recent block | ||
| // the user could have gotten from another RPC command prior to now | ||
| pwalletMain->BlockUntilSyncedToCurrentChain(); | ||
|
|
||
| RPCTypeCheck(request.params, {UniValue::VSTR}); | ||
|
|
||
| CTxDestination changeAddress = CNoDestination(); | ||
|
|
@@ -899,6 +905,8 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) | |
| "\nSend the transaction (signed hex)\n" + HelpExampleCli("sendrawtransaction", "\"signedhex\"") + | ||
| "\nAs a json rpc call\n" + HelpExampleRpc("sendrawtransaction", "\"signedhex\"")); | ||
|
|
||
| std::promise<void> promise; | ||
|
|
||
| RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}); | ||
|
|
||
| // parse hex string from parameter | ||
|
|
@@ -911,7 +919,8 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) | |
| if (request.params.size() > 1) | ||
| fOverrideFees = request.params[1].get_bool(); | ||
|
|
||
| AssertLockNotHeld(cs_main); | ||
| { // cs_main scope | ||
| LOCK(cs_main); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: should indent everything by 4 spaces after the new opening scope brace |
||
| CCoinsViewCache& view = *pcoinsTip; | ||
| bool fHaveChain = false; | ||
| for (size_t o = 0; !fHaveChain && o < mtx.vout.size(); o++) { | ||
|
|
@@ -923,7 +932,6 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) | |
| CValidationState state; | ||
| bool fMissingInputs; | ||
| { | ||
| LOCK(cs_main); | ||
|
Comment on lines
934
to
-926
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: can remove the code-block now |
||
| if (!AcceptToMemoryPool(mempool, state, MakeTransactionRef(std::move(mtx)), true, &fMissingInputs, false, !fOverrideFees)) { | ||
| if (state.IsInvalid()) { | ||
| throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason())); | ||
|
|
@@ -933,11 +941,25 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) | |
| } | ||
| throw JSONRPCError(RPC_TRANSACTION_ERROR, state.GetRejectReason()); | ||
| } | ||
| } else { | ||
| // If wallet is enabled, ensure that the wallet has been made aware | ||
| // of the new transaction prior to returning. This prevents a race | ||
| // where a user might call sendrawtransaction with a transaction | ||
| // to/from their wallet, immediately call some wallet RPC, and get | ||
| // a stale result because callbacks have not yet been processed. | ||
| CallFunctionInValidationInterfaceQueue([&promise] { | ||
| promise.set_value(); | ||
| }); | ||
| } | ||
| } | ||
| } else if (fHaveChain) { | ||
| throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain"); | ||
| } | ||
|
|
||
| } // cs_main | ||
|
|
||
| promise.get_future().wait(); | ||
|
|
||
| if(!g_connman) | ||
| throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); | ||
|
|
||
|
|
@@ -946,6 +968,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) | |
| { | ||
| pnode->PushInventory(inv); | ||
| }); | ||
|
|
||
| return hashTx.GetHex(); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -760,7 +760,7 @@ CAmount SaplingScriptPubKeyMan::GetShieldedChange(const CWalletTx& wtx) const | |
|
|
||
| bool SaplingScriptPubKeyMan::IsNoteSaplingChange(const SaplingOutPoint& op, libzcash::SaplingPaymentAddress address) const | ||
| { | ||
| LOCK(wallet->cs_KeyStore); | ||
| LOCK2(wallet->cs_wallet, wallet->cs_KeyStore); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can remove the |
||
| std::set<libzcash::PaymentAddress> shieldedAddresses = {address}; | ||
| std::set<std::pair<libzcash::PaymentAddress, uint256>> nullifierSet = GetNullifiersForAddresses(shieldedAddresses); | ||
| return IsNoteSaplingChange(nullifierSet, address, op); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,10 +54,15 @@ TestingSetup::TestingSetup() | |
| fs::create_directories(pathTemp); | ||
| gArgs.ForceSetArg("-datadir", pathTemp.string()); | ||
|
|
||
| // Start the lightweight task scheduler thread | ||
| CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler); | ||
| threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop)); | ||
|
|
||
| // Note that because we don't bother running a scheduler thread here, | ||
| // callbacks via CValidationInterface are unreliable, but that's OK, | ||
| // our unit tests aren't testing multiple parts of the code at once. | ||
|
Comment on lines
+57
to
63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, will tackle it in #2212. |
||
| GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); | ||
| GetMainSignals().RegisterWithMempoolSignals(mempool); | ||
|
|
||
| // Ideally we'd move all the RPC tests to the functional testing framework | ||
| // instead of unit tests, but for now we need these here. | ||
|
|
@@ -87,7 +92,9 @@ TestingSetup::~TestingSetup() | |
| threadGroup.interrupt_all(); | ||
| threadGroup.join_all(); | ||
| GetMainSignals().FlushBackgroundCallbacks(); | ||
| UnregisterAllValidationInterfaces(); | ||
| GetMainSignals().UnregisterBackgroundSignalScheduler(); | ||
| GetMainSignals().UnregisterWithMempoolSignals(mempool); | ||
| UnloadBlockIndex(); | ||
| delete pcoinsTip; | ||
| delete pcoinsdbview; | ||
|
|
||
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.
nit: