diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/chainparamsbase.cpp | 44 | ||||
-rw-r--r-- | src/chainparamsbase.h | 5 | ||||
-rw-r--r-- | src/chainparamsseeds.h | 2 | ||||
-rw-r--r-- | src/init.cpp | 17 | ||||
-rw-r--r-- | src/key.cpp | 6 | ||||
-rw-r--r-- | src/net.cpp | 86 | ||||
-rw-r--r-- | src/net.h | 10 | ||||
-rw-r--r-- | src/net_processing.cpp | 4 | ||||
-rw-r--r-- | src/qt/README.md | 95 | ||||
-rw-r--r-- | src/qt/guiutil.cpp | 2 | ||||
-rw-r--r-- | src/qt/optionsmodel.cpp | 7 | ||||
-rw-r--r-- | src/rpc/rawtransaction.cpp | 2 | ||||
-rw-r--r-- | src/script/interpreter.h | 2 | ||||
-rw-r--r-- | src/script/ismine.h | 2 | ||||
-rw-r--r-- | src/test/data/tx_invalid.json | 4 | ||||
-rw-r--r-- | src/test/data/tx_valid.json | 4 | ||||
-rw-r--r-- | src/torcontrol.cpp | 6 | ||||
-rw-r--r-- | src/torcontrol.h | 2 | ||||
-rw-r--r-- | src/validation.cpp | 3 | ||||
-rw-r--r-- | src/wallet/feebumper.cpp | 45 | ||||
-rw-r--r-- | src/wallet/feebumper.h | 2 | ||||
-rw-r--r-- | src/wallet/wallet.cpp | 4 |
22 files changed, 219 insertions, 135 deletions
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 89dd8549b9..a04258fd40 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -24,44 +24,6 @@ void AppendParamsHelpMessages(std::string& strUsage, bool debugHelp) strUsage += HelpMessageOpt("-testnet", _("Use the test chain")); } -/** - * Main network - */ -class CBaseMainParams : public CBaseChainParams -{ -public: - CBaseMainParams() - { - nRPCPort = 8332; - } -}; - -/** - * Testnet (v3) - */ -class CBaseTestNetParams : public CBaseChainParams -{ -public: - CBaseTestNetParams() - { - nRPCPort = 18332; - strDataDir = "testnet3"; - } -}; - -/* - * Regression test - */ -class CBaseRegTestParams : public CBaseChainParams -{ -public: - CBaseRegTestParams() - { - nRPCPort = 18443; - strDataDir = "regtest"; - } -}; - static std::unique_ptr<CBaseChainParams> globalChainBaseParams; const CBaseChainParams& BaseParams() @@ -73,11 +35,11 @@ const CBaseChainParams& BaseParams() std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain) { if (chain == CBaseChainParams::MAIN) - return std::unique_ptr<CBaseChainParams>(new CBaseMainParams()); + return MakeUnique<CBaseChainParams>("", 8332); else if (chain == CBaseChainParams::TESTNET) - return std::unique_ptr<CBaseChainParams>(new CBaseTestNetParams()); + return MakeUnique<CBaseChainParams>("testnet3", 18332); else if (chain == CBaseChainParams::REGTEST) - return std::unique_ptr<CBaseChainParams>(new CBaseRegTestParams()); + return MakeUnique<CBaseChainParams>("regtest", 18443); else throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain)); } diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index b4d2bb4f08..2cb860380e 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -24,9 +24,10 @@ public: const std::string& DataDir() const { return strDataDir; } int RPCPort() const { return nRPCPort; } -protected: - CBaseChainParams() {} + CBaseChainParams() = delete; + CBaseChainParams(const std::string& data_dir, int rpc_port) : nRPCPort(rpc_port), strDataDir(data_dir) {} +private: int nRPCPort; std::string strDataDir; }; diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h index 2b102c464f..6e2b3c34a2 100644 --- a/src/chainparamsseeds.h +++ b/src/chainparamsseeds.h @@ -5,7 +5,7 @@ * AUTOGENERATED by contrib/seeds/generate-seeds.py * * Each line contains a 16-byte IPv6 address and a port. - * IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly. + * IPv4 as well as onion addresses are wrapped inside an IPv6 address accordingly. */ static SeedSpec6 pnSeed6_main[] = { {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x13,0x05,0x7f}, 8333}, diff --git a/src/init.cpp b/src/init.cpp index 84398d978c..b28baba779 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -165,6 +165,7 @@ void Interrupt() InterruptRPC(); InterruptREST(); InterruptTorControl(); + InterruptMapPort(); if (g_connman) g_connman->Interrupt(); } @@ -191,7 +192,7 @@ void Shutdown() #ifdef ENABLE_WALLET FlushWallets(); #endif - MapPort(false); + StopMapPort(); // Because these depend on each-other, we make sure that neither can be // using the other before destroying them. @@ -545,7 +546,8 @@ static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex std::string strCmd = gArgs.GetArg("-blocknotify", ""); if (!strCmd.empty()) { boost::replace_all(strCmd, "%s", pBlockIndex->GetBlockHash().GetHex()); - boost::thread t(runCommand, strCmd); // thread runs free + std::thread t(runCommand, strCmd); + t.detach(); // thread runs free } } @@ -1425,6 +1427,9 @@ bool AppInitMain() pcoinsTip.reset(); pcoinsdbview.reset(); pcoinscatcher.reset(); + // new CBlockTreeDB tries to delete the existing file, which + // fails if it's still open from the previous loop. Close it first: + pblocktree.reset(); pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, false, fReset)); if (fReset) { @@ -1671,12 +1676,14 @@ bool AppInitMain() LogPrintf("nBestHeight = %d\n", chain_active_height); if (gArgs.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) - StartTorControl(threadGroup, scheduler); + StartTorControl(); - Discover(threadGroup); + Discover(); // Map ports with UPnP - MapPort(gArgs.GetBoolArg("-upnp", DEFAULT_UPNP)); + if (gArgs.GetBoolArg("-upnp", DEFAULT_UPNP)) { + StartMapPort(); + } CConnman::Options connOptions; connOptions.nLocalServices = nLocalServices; diff --git a/src/key.cpp b/src/key.cpp index e998e3db6e..ffed989be1 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -44,7 +44,7 @@ static int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *ou if (end - privkey < 1 || !(*privkey & 0x80u)) { return 0; } - size_t lenb = *privkey & ~0x80u; privkey++; + ptrdiff_t lenb = *privkey & ~0x80u; privkey++; if (lenb < 1 || lenb > 2) { return 0; } @@ -52,7 +52,7 @@ static int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *ou return 0; } /* sequence length */ - size_t len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0u); + ptrdiff_t len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0u); privkey += lenb; if (end - privkey < len) { return 0; @@ -66,7 +66,7 @@ static int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *ou if (end - privkey < 2 || privkey[0] != 0x04u) { return 0; } - size_t oslen = privkey[1]; + ptrdiff_t oslen = privkey[1]; privkey += 2; if (oslen > 32 || end - privkey < oslen) { return 0; diff --git a/src/net.cpp b/src/net.cpp index 03ed7e7fc1..201914685c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1459,6 +1459,8 @@ void CConnman::WakeMessageHandler() #ifdef USE_UPNP +static CThreadInterrupt g_upnp_interrupt; +static std::thread g_upnp_thread; void ThreadMapPort() { std::string port = strprintf("%u", GetListenPort()); @@ -1509,35 +1511,29 @@ void ThreadMapPort() std::string strDesc = "Bitcoin " + FormatFullVersion(); - try { - while (true) { + do { #ifndef UPNPDISCOVER_SUCCESS - /* miniupnpc 1.5 */ - r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, - port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0); + /* miniupnpc 1.5 */ + r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, + port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0); #else - /* miniupnpc 1.6 */ - r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, - port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0"); + /* miniupnpc 1.6 */ + r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, + port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0"); #endif - if(r!=UPNPCOMMAND_SUCCESS) - LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", - port, port, lanaddr, r, strupnperror(r)); - else - LogPrintf("UPnP Port Mapping successful.\n"); - - MilliSleep(20*60*1000); // Refresh every 20 minutes - } - } - catch (const boost::thread_interrupted&) - { - r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); - LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); - freeUPNPDevlist(devlist); devlist = nullptr; - FreeUPNPUrls(&urls); - throw; + if(r!=UPNPCOMMAND_SUCCESS) + LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", + port, port, lanaddr, r, strupnperror(r)); + else + LogPrintf("UPnP Port Mapping successful.\n"); } + while(g_upnp_interrupt.sleep_for(std::chrono::minutes(20))); + + r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); + LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); + freeUPNPDevlist(devlist); devlist = nullptr; + FreeUPNPUrls(&urls); } else { LogPrintf("No valid UPnP IGDs found\n"); freeUPNPDevlist(devlist); devlist = nullptr; @@ -1546,27 +1542,39 @@ void ThreadMapPort() } } -void MapPort(bool fUseUPnP) +void StartMapPort() { - static std::unique_ptr<boost::thread> upnp_thread; + if (!g_upnp_thread.joinable()) { + assert(!g_upnp_interrupt); + g_upnp_thread = std::thread((std::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort))); + } +} - if (fUseUPnP) - { - if (upnp_thread) { - upnp_thread->interrupt(); - upnp_thread->join(); - } - upnp_thread.reset(new boost::thread(boost::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort))); +void InterruptMapPort() +{ + if(g_upnp_thread.joinable()) { + g_upnp_interrupt(); } - else if (upnp_thread) { - upnp_thread->interrupt(); - upnp_thread->join(); - upnp_thread.reset(); +} + +void StopMapPort() +{ + if(g_upnp_thread.joinable()) { + g_upnp_thread.join(); + g_upnp_interrupt.reset(); } } #else -void MapPort(bool) +void StartMapPort() +{ + // Intentionally left blank. +} +void InterruptMapPort() +{ + // Intentionally left blank. +} +void StopMapPort() { // Intentionally left blank. } @@ -2121,7 +2129,7 @@ bool CConnman::BindListenPort(const CService &addrBind, std::string& strError, b return true; } -void Discover(boost::thread_group& threadGroup) +void Discover() { if (!fDiscover) return; @@ -37,10 +37,6 @@ class CScheduler; class CNode; -namespace boost { - class thread_group; -} // namespace boost - /** Time between pings automatically sent out for latency probing and keepalive (in seconds). */ static const int PING_INTERVAL = 2 * 60; /** Time after which to disconnect, after waiting for a ping response (or inactivity). */ @@ -441,8 +437,10 @@ private: friend struct CConnmanTest; }; extern std::unique_ptr<CConnman> g_connman; -void Discover(boost::thread_group& threadGroup); -void MapPort(bool fUseUPnP); +void Discover(); +void StartMapPort(); +void InterruptMapPort(); +void StopMapPort(); unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index fc0ba82d8b..bf9307727a 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1226,10 +1226,10 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } // release cs_main - if (it != pfrom->vRecvGetData.end()) { + if (it != pfrom->vRecvGetData.end() && !pfrom->fPauseSend) { const CInv &inv = *it; - it++; if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK) { + it++; ProcessGetBlockData(pfrom, consensusParams, inv, connman, interruptMsgProc); } } diff --git a/src/qt/README.md b/src/qt/README.md new file mode 100644 index 0000000000..7ffea98170 --- /dev/null +++ b/src/qt/README.md @@ -0,0 +1,95 @@ +This directory contains the BitcoinQT graphical user interface (GUI). It uses the cross platform framework [QT](https://www1.qt.io/developers/). + +The current precise version for QT 5 is specified in [qt.mk](/depends/packages/qt.mk). QT 4 is also supported (see [#8263](https://github.com/bitcoin/bitcoin/issues/8263)). + +## Compile and run + +See build instructions ([OSX](/doc/build-osx.md), [Windows](/doc/build-windows.md), [Unix](/doc/build-unix.md), etc). + +To run: + +```sh +./src/qt/bitcoin-qt +``` + +## Files and directories + +### forms + +Contains [Designer UI](http://doc.qt.io/qt-5.9/designer-using-a-ui-file.html) files. They are created with [Qt Creator](#use-qt-Creator-as IDE), but can be edited using any text editor. + +### locale + +Contains translations. They are periodically updated. The process is described [here](/doc/translation_process.md). + +### res + +Resources such as the icon. + +### test + +Tests. + +### bitcoingui.(h/cpp) + +Represents the main window of the Bitcoin UI. + +### \*model.(h/cpp) + +The model. When it has a corresponding controller, it generally inherits from [QAbstractTableModel](http://doc.qt.io/qt-5/qabstracttablemodel.html). Models that are used by controllers as helpers inherit from other QT classes like [QValidator](http://doc.qt.io/qt-5/qvalidator.html). + +ClientModel is used by the main application `bitcoingui` and several models like `peertablemodel`. + +### \*page.(h/cpp) + +A controller. `:NAMEpage.cpp` generally includes `:NAMEmodel.h` and `forms/:NAME.page.ui` with a similar `:NAME`. + +### \*dialog.(h/cpp) + +Various dialogs, e.g. to open a URL. Inherit from [QDialog](http://doc.qt.io/qt-4.8/qdialog.html). + +### paymentserver.(h/cpp) + +Used to process BIP21 and BIP70 (see https://github.com/bitcoin/bitcoin/pull/11622) payment URI / requests. Also handles URI based application switching (e.g. when following a bitcoin:... link from a browser). + +### walletview.(h/cpp) + +Represents the view to a single wallet. + +### Other .h/cpp files + +* UI elements like BitcoinAmountField, which inherit from QWidget. +* `bitcoinstrings.cpp`: automatically generated +* `bitcoinunits.(h/cpp)`: BTC / mBTC / etc handling +* `callback.h` +* `guiconstants.h`: UI colors, app name, etc +* `guiutil.h`: several helper functions +* `macdockiconhandler.(h/cpp)` +* `macdockiconhandler.(h/cpp)`: display notifications in OSX + +## Contribute + +See [CONTRIBUTING.md](/CONTRIBUTING.md) for general guidelines. Specifically for QT: + +* don't change `local/bitcoin_en.ts`; this happens [automatically](/doc/translation_process.md#writing-code-with-translations) + +## Using Qt Creator as IDE + +You can use Qt Creator as an IDE. This is especially useful if you want to change +the UI layout. + +Download and install the community edition of [Qt Creator](https://www.qt.io/download/). +Uncheck everything except Qt Creator during the installation process. + +Instructions for OSX: + +1. Make sure you installed everything through Homebrew mentioned in the [OSX build instructions](/docs/build-osx.md) +2. Use `./configure` with the `--enable-debug` flag +3. In Qt Creator do "New Project" -> Import Project -> Import Existing Project +4. Enter "bitcoin-qt" as project name, enter src/qt as location +5. Leave the file selection as it is +6. Confirm the "summary page" +7. In the "Projects" tab select "Manage Kits..." +8. Select the default "Desktop" kit and select "Clang (x86 64bit in /usr/bin)" as compiler +9. Select LLDB as debugger (you might need to set the path to your installation) +10. Start debugging with Qt Creator (you might need to the executable to "bitcoin-qt" under "Run", which is where you can also add command line arguments) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 558d4f108c..edf1c29ea1 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -101,7 +101,7 @@ QFont fixedPitchFont() #endif } -// Just some dummy data to generate an convincing random-looking (but consistent) address +// Just some dummy data to generate a convincing random-looking (but consistent) address static const uint8_t dummydata[] = {0xeb,0x15,0x23,0x1d,0xfc,0xeb,0x60,0x92,0x58,0x86,0xb6,0x7d,0x06,0x52,0x99,0x92,0x59,0x15,0xae,0xb1,0x72,0xc0,0x66,0x47}; // Generate a dummy address with invalid CRC, starting with the network prefix. diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 4ade88d843..909be1c264 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -315,7 +315,12 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in break; case MapPortUPnP: // core option - can be changed on-the-fly settings.setValue("fUseUPnP", value.toBool()); - MapPort(value.toBool()); + if (value.toBool()) { + StartMapPort(); + } else { + InterruptMapPort(); + StopMapPort(); + } break; case MinimizeOnClose: fMinimizeOnClose = value.toBool(); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index fb70f9d596..24f2431efc 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -692,7 +692,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request) "\nArguments:\n" "1. \"hexstring\" (string, required) The transaction hex string\n" - "2. \"prevtxs\" (string, optional) An json array of previous dependent transaction outputs\n" + "2. \"prevtxs\" (string, optional) A json array of previous dependent transaction outputs\n" " [ (json array of json objects, or 'null' if none provided)\n" " {\n" " \"txid\":\"id\", (string, required) The transaction id\n" diff --git a/src/script/interpreter.h b/src/script/interpreter.h index e12329be76..4dad6b44c5 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -104,7 +104,7 @@ enum // SCRIPT_VERIFY_MINIMALIF = (1U << 13), - // Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed + // Signature(s) must be empty vector if a CHECK(MULTI)SIG operation failed // SCRIPT_VERIFY_NULLFAIL = (1U << 14), diff --git a/src/script/ismine.h b/src/script/ismine.h index b54879cc15..c1338c3a8e 100644 --- a/src/script/ismine.h +++ b/src/script/ismine.h @@ -29,7 +29,7 @@ enum isminetype typedef uint8_t isminefilter; /* isInvalid becomes true when the script is found invalid by consensus or policy. This will terminate the recursion - * and return a ISMINE_NO immediately, as an invalid script should never be considered as "mine". This is needed as + * and return ISMINE_NO immediately, as an invalid script should never be considered as "mine". This is needed as * different SIGVERSION may have different network rules. Currently the only use of isInvalid is indicate uncompressed * keys in SIGVERSION_WITNESS_V0 script, but could also be used in similar cases in the future */ diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json index 09442b7f9f..f8a1347c31 100644 --- a/src/test/data/tx_invalid.json +++ b/src/test/data/tx_invalid.json @@ -92,11 +92,11 @@ [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a010047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], -["As above, but using a OP_1"], +["As above, but using an OP_1"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000495147304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], -["As above, but using a OP_1NEGATE"], +["As above, but using an OP_1NEGATE"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000494f47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json index a845083636..7e39ec7599 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -23,11 +23,11 @@ [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a01ff47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], -["As above, but using a OP_1"], +["As above, but using an OP_1"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000495147304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], -["As above, but using a OP_1NEGATE"], +["As above, but using an OP_1NEGATE"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000494f47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index d875008ef2..717d1cf7e5 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -731,7 +731,7 @@ void TorController::reconnect_cb(evutil_socket_t fd, short what, void *arg) /****** Thread ********/ static struct event_base *gBase; -static boost::thread torControlThread; +static std::thread torControlThread; static void TorControlThread() { @@ -740,7 +740,7 @@ static void TorControlThread() event_base_dispatch(gBase); } -void StartTorControl(boost::thread_group& threadGroup, CScheduler& scheduler) +void StartTorControl() { assert(!gBase); #ifdef WIN32 @@ -754,7 +754,7 @@ void StartTorControl(boost::thread_group& threadGroup, CScheduler& scheduler) return; } - torControlThread = boost::thread(boost::bind(&TraceThread<void (*)()>, "torcontrol", &TorControlThread)); + torControlThread = std::thread(std::bind(&TraceThread<void (*)()>, "torcontrol", &TorControlThread)); } void InterruptTorControl() diff --git a/src/torcontrol.h b/src/torcontrol.h index 20514f7bbf..2be6701fa5 100644 --- a/src/torcontrol.h +++ b/src/torcontrol.h @@ -13,7 +13,7 @@ extern const std::string DEFAULT_TOR_CONTROL; static const bool DEFAULT_LISTEN_ONION = true; -void StartTorControl(boost::thread_group& threadGroup, CScheduler& scheduler); +void StartTorControl(); void InterruptTorControl(); void StopTorControl(); diff --git a/src/validation.cpp b/src/validation.cpp index 978aaf7d06..371460a6f0 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1182,7 +1182,8 @@ static void AlertNotify(const std::string& strMessage) safeStatus = singleQuote+safeStatus+singleQuote; boost::replace_all(strCmd, "%s", safeStatus); - boost::thread t(runCommand, strCmd); // thread runs free + std::thread t(runCommand, strCmd); + t.detach(); // thread runs free } static void CheckForkWarningConditions() diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index 9bfcab54a5..5234a69710 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -65,16 +65,39 @@ static feebumper::Result PreconditionChecks(const CWallet* wallet, const CWallet errors.push_back("Transaction has been mined, or is conflicted with a mined transaction"); return feebumper::Result::WALLET_ERROR; } + + if (!SignalsOptInRBF(*wtx.tx)) { + errors.push_back("Transaction is not BIP 125 replaceable"); + return feebumper::Result::WALLET_ERROR; + } + + if (wtx.mapValue.count("replaced_by_txid")) { + errors.push_back(strprintf("Cannot bump transaction %s which was already bumped by transaction %s", wtx.GetHash().ToString(), wtx.mapValue.at("replaced_by_txid"))); + return feebumper::Result::WALLET_ERROR; + } + + // check that original tx consists entirely of our inputs + // if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee) + if (!wallet->IsAllFromMe(*wtx.tx, ISMINE_SPENDABLE)) { + errors.push_back("Transaction contains inputs that don't belong to this wallet"); + return feebumper::Result::WALLET_ERROR; + } + + return feebumper::Result::OK; } namespace feebumper { -bool TransactionCanBeBumped(CWallet* wallet, const uint256& txid) +bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid) { LOCK2(cs_main, wallet->cs_wallet); const CWalletTx* wtx = wallet->GetWalletTx(txid); - return wtx && SignalsOptInRBF(*wtx->tx) && !wtx->mapValue.count("replaced_by_txid"); + if (wtx == nullptr) return false; + + std::vector<std::string> errors_dummy; + feebumper::Result res = PreconditionChecks(wallet, *wtx, errors_dummy); + return res == feebumper::Result::OK; } Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, CAmount total_fee, std::vector<std::string>& errors, @@ -94,23 +117,6 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin return result; } - if (!SignalsOptInRBF(*wtx.tx)) { - errors.push_back("Transaction is not BIP 125 replaceable"); - return Result::WALLET_ERROR; - } - - if (wtx.mapValue.count("replaced_by_txid")) { - errors.push_back(strprintf("Cannot bump transaction %s which was already bumped by transaction %s", txid.ToString(), wtx.mapValue.at("replaced_by_txid"))); - return Result::WALLET_ERROR; - } - - // check that original tx consists entirely of our inputs - // if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee) - if (!wallet->IsAllFromMe(*wtx.tx, ISMINE_SPENDABLE)) { - errors.push_back("Transaction contains inputs that don't belong to this wallet"); - return Result::WALLET_ERROR; - } - // figure out which output was change // if there was no change output or multiple change outputs, fail int nOutput = -1; @@ -228,6 +234,7 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin } } + return Result::OK; } diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h index 8eec30440c..7e36a9766b 100644 --- a/src/wallet/feebumper.h +++ b/src/wallet/feebumper.h @@ -26,7 +26,7 @@ enum class Result }; //! Return whether transaction can be bumped. -bool TransactionCanBeBumped(CWallet* wallet, const uint256& txid); +bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid); //! Create bumpfee transaction. Result CreateTransaction(const CWallet* wallet, diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 7f36aefeaf..513819606b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -34,7 +34,6 @@ #include <future> #include <boost/algorithm/string/replace.hpp> -#include <boost/thread.hpp> std::vector<CWalletRef> vpwallets; /** Transaction fee set by the user */ @@ -976,7 +975,8 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose) if (!strCmd.empty()) { boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex()); - boost::thread t(runCommand, strCmd); // thread runs free + std::thread t(runCommand, strCmd); + t.detach(); // thread runs free } return true; |