Fix wallet RPC race by waiting for callbacks in sendrawtransaction
This commit is contained in:
parent
e545dedf72
commit
cb06edf938
1 changed files with 22 additions and 1 deletions
|
@ -11,6 +11,7 @@
|
|||
#include "init.h"
|
||||
#include "keystore.h"
|
||||
#include "validation.h"
|
||||
#include "validationinterface.h"
|
||||
#include "merkleblock.h"
|
||||
#include "net.h"
|
||||
#include "policy/policy.h"
|
||||
|
@ -30,6 +31,7 @@
|
|||
#include "wallet/wallet.h"
|
||||
#endif
|
||||
|
||||
#include <future>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <univalue.h>
|
||||
|
@ -917,7 +919,9 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
|
|||
);
|
||||
|
||||
ObserveSafeMode();
|
||||
LOCK(cs_main);
|
||||
|
||||
std::promise<void> promise;
|
||||
|
||||
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});
|
||||
|
||||
// parse hex string from parameter
|
||||
|
@ -931,6 +935,8 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
|
|||
if (!request.params[1].isNull() && request.params[1].get_bool())
|
||||
nMaxRawTxFee = 0;
|
||||
|
||||
{ // cs_main scope
|
||||
LOCK(cs_main);
|
||||
CCoinsViewCache &view = *pcoinsTip;
|
||||
bool fHaveChain = false;
|
||||
for (size_t o = 0; !fHaveChain && o < tx->vout.size(); o++) {
|
||||
|
@ -952,10 +958,24 @@ 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");
|
||||
|
||||
|
@ -964,6 +984,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
|
|||
{
|
||||
pnode->PushInventory(inv);
|
||||
});
|
||||
|
||||
return hashTx.GetHex();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue