mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-14 00:58:09 +00:00
Merge remote-tracking branch 'bitcoin/0.16' into HEAD
This commit is contained in:
commit
ad3c330972
@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
|
||||
AC_PREREQ([2.60])
|
||||
define(_CLIENT_VERSION_MAJOR, 0)
|
||||
define(_CLIENT_VERSION_MINOR, 16)
|
||||
define(_CLIENT_VERSION_REVISION, 1)
|
||||
define(_CLIENT_VERSION_REVISION, 2)
|
||||
define(_CLIENT_VERSION_BUILD, 0)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
define(_COPYRIGHT_YEAR, 2018)
|
||||
|
@ -1,6 +1,6 @@
|
||||
PACKAGE=qt
|
||||
$(package)_version=5.7.1
|
||||
$(package)_download_path=http://download.qt.io/official_releases/qt/5.7/$($(package)_version)/submodules
|
||||
$(package)_download_path=https://download.qt.io/archive/qt/5.7/$($(package)_version)/submodules
|
||||
$(package)_suffix=opensource-src-$($(package)_version).tar.gz
|
||||
$(package)_file_name=qtbase-$($(package)_suffix)
|
||||
$(package)_sha256_hash=95f83e532d23b3ddbde7973f380ecae1bac13230340557276f75f2e37984e410
|
||||
|
@ -1,9 +1,9 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3.
|
||||
.TH LITECOIN-CLI "1" "June 2018" "litecoin-cli v0.16.1.0" "User Commands"
|
||||
.TH BITCOIN-CLI "1" "July 2018" "bitcoin-cli v0.16.2.0" "User Commands"
|
||||
.SH NAME
|
||||
litecoin-cli \- manual page for litecoin-cli v0.16.1.0
|
||||
bitcoin-cli \- manual page for bitcoin-cli v0.16.2.0
|
||||
.SH DESCRIPTION
|
||||
Litecoin Core RPC client version v0.16.1.0\-dirty
|
||||
Bitcoin Core RPC client version v0.16.2.0
|
||||
.SS "Usage:"
|
||||
.TP
|
||||
litecoin\-cli [options] <command> [params]
|
||||
|
@ -1,9 +1,9 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3.
|
||||
.TH LITECOIN-QT "1" "June 2018" "litecoin-qt v0.16.1.0" "User Commands"
|
||||
.TH BITCOIN-QT "1" "July 2018" "bitcoin-qt v0.16.2.0" "User Commands"
|
||||
.SH NAME
|
||||
litecoin-qt \- manual page for litecoin-qt v0.16.1.0
|
||||
bitcoin-qt \- manual page for bitcoin-qt v0.16.2.0
|
||||
.SH DESCRIPTION
|
||||
Litecoin Core version v0.16.1.0\-dirty (64\-bit)
|
||||
Bitcoin Core version v0.16.2.0 (64\-bit)
|
||||
Usage:
|
||||
.IP
|
||||
litecoin\-qt [command\-line options]
|
||||
|
@ -1,9 +1,9 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3.
|
||||
.TH LITECOIN-TX "1" "June 2018" "litecoin-tx v0.16.1.0" "User Commands"
|
||||
.TH BITCOIN-TX "1" "July 2018" "bitcoin-tx v0.16.2.0" "User Commands"
|
||||
.SH NAME
|
||||
litecoin-tx \- manual page for litecoin-tx v0.16.1.0
|
||||
bitcoin-tx \- manual page for bitcoin-tx v0.16.2.0
|
||||
.SH DESCRIPTION
|
||||
Litecoin Core litecoin\-tx utility version v0.16.1.0\-dirty
|
||||
Bitcoin Core bitcoin\-tx utility version v0.16.2.0
|
||||
.SS "Usage:"
|
||||
.TP
|
||||
litecoin\-tx [options] <hex\-tx> [commands]
|
||||
|
@ -1,9 +1,9 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3.
|
||||
.TH LITECOIND "1" "June 2018" "litecoind v0.16.1.0" "User Commands"
|
||||
.TH BITCOIND "1" "July 2018" "bitcoind v0.16.2.0" "User Commands"
|
||||
.SH NAME
|
||||
litecoind \- manual page for litecoind v0.16.1.0
|
||||
bitcoind \- manual page for bitcoind v0.16.2.0
|
||||
.SH DESCRIPTION
|
||||
Litecoin Core Daemon version v0.16.1.0\-dirty
|
||||
Bitcoin Core Daemon version v0.16.2.0
|
||||
.SS "Usage:"
|
||||
.TP
|
||||
litecoind [options]
|
||||
|
@ -1,9 +1,9 @@
|
||||
Bitcoin Core version 0.16.1 is now available from:
|
||||
Bitcoin Core version 0.16.2 is now available from:
|
||||
|
||||
<https://bitcoincore.org/bin/bitcoin-core-0.16.1/>
|
||||
<https://bitcoincore.org/bin/bitcoin-core-0.16.2/>
|
||||
|
||||
This is a new major version release, including new features, various bugfixes
|
||||
and performance improvements, as well as updated translations.
|
||||
This is a new minor version release, with various bugfixes
|
||||
as well as updated translations.
|
||||
|
||||
Please report bugs using the issue tracker at GitHub:
|
||||
|
||||
@ -46,100 +46,71 @@ the Linux kernel, macOS 10.8+, and Windows Vista and later. Windows XP is not su
|
||||
Bitcoin Core should also work on most other Unix-like systems but is not
|
||||
frequently tested on them.
|
||||
|
||||
Notable changes
|
||||
===============
|
||||
|
||||
Miner block size removed
|
||||
------------------------
|
||||
|
||||
The `-blockmaxsize` option for miners to limit their blocks' sizes was
|
||||
deprecated in version 0.15.1, and has now been removed. Miners should use the
|
||||
`-blockmaxweight` option if they want to limit the weight of their blocks'
|
||||
weights.
|
||||
|
||||
0.16.1 change log
|
||||
0.16.2 change log
|
||||
------------------
|
||||
|
||||
### Policy
|
||||
- #11423 `d353dd1` [Policy] Several transaction standardness rules (jl2012)
|
||||
|
||||
### Mining
|
||||
- #12756 `e802c22` [config] Remove blockmaxsize option (jnewbery)
|
||||
|
||||
### Block and transaction handling
|
||||
- #13199 `c71e535` Bugfix: ensure consistency of m_failed_blocks after reconsiderblock (sdaftuar)
|
||||
- #13023 `bb79aaf` Fix some concurrency issues in ActivateBestChain() (skeees)
|
||||
|
||||
### P2P protocol and network code
|
||||
- #12626 `f60e84d` Limit the number of IPs addrman learns from each DNS seeder (EthanHeilman)
|
||||
|
||||
### Wallet
|
||||
- #13265 `5d8de76` Exit SyncMetaData if there are no transactions to sync (laanwj)
|
||||
- #13030 `5ff571e` Fix zapwallettxes/multiwallet interaction. (jnewbery)
|
||||
- #13622 `c04a4a5` Remove mapRequest tracking that just effects Qt display. (TheBlueMatt)
|
||||
- #12905 `cfc6f74` [rpcwallet] Clamp walletpassphrase value at 100M seconds (sdaftuar)
|
||||
- #13437 `ed82e71` wallet: Erase wtxOrderd wtx pointer on removeprunedfunds (MarcoFalke)
|
||||
|
||||
### RPC and other APIs
|
||||
- #13451 `cbd2f70` rpc: expose CBlockIndex::nTx in getblock(header) (instagibbs)
|
||||
- #13507 `f7401c8` RPC: Fix parameter count check for importpubkey (kristapsk)
|
||||
- #13452 `6b9dc8c` rpc: have verifytxoutproof check the number of txns in proof structure (instagibbs)
|
||||
- #12837 `bf1f150` rpc: fix type mistmatch in `listreceivedbyaddress` (joemphilips)
|
||||
- #12743 `657dfc5` Fix csBestBlock/cvBlockChange waiting in rpc/mining (sipa)
|
||||
|
||||
### GUI
|
||||
- #12999 `1720eb3` Show the Window when double clicking the taskbar icon (ken2812221)
|
||||
- #12650 `f118a7a` Fix issue: "default port not shown correctly in settings dialog" (251Labs)
|
||||
- #13251 `ea487f9` Rephrase Bech32 checkbox texts, and enable it with legacy address default (fanquake)
|
||||
- #12432 `f78e7f6` [qt] send: Clear All also resets coin control options (Sjors)
|
||||
- #12617 `21dd512` gui: Show messages as text not html (laanwj)
|
||||
- #12793 `cf6feb7` qt: Avoid reseting on resetguisettigs=0 (MarcoFalke)
|
||||
|
||||
### Build system
|
||||
- #12474 `b0f692f` Allow depends system to support armv7l (hkjn)
|
||||
- #12585 `72a3290` depends: Switch to downloading expat from GitHub (fanquake)
|
||||
- #12648 `46ca8f3` test: Update trusted git root (MarcoFalke)
|
||||
- #11995 `686cb86` depends: Fix Qt build with Xcode 9 (fanquake)
|
||||
- #12636 `845838c` backport: #11995 Fix Qt build with Xcode 9 (fanquake)
|
||||
- #12946 `e055bc0` depends: Fix Qt build with XCode 9.3 (fanquake)
|
||||
- #12998 `7847b92` Default to defining endian-conversion DECLs in compat w/o config (TheBlueMatt)
|
||||
- #13544 `9fd3e00` depends: Update Qt download url (fanquake)
|
||||
- #12573 `88d1a64` Fix compilation when compiler do not support `__builtin_clz*` (532479301)
|
||||
|
||||
### Tests and QA
|
||||
- #12447 `01f931b` Add missing signal.h header (laanwj)
|
||||
- #12545 `1286f3e` Use wait_until to ensure ping goes out (Empact)
|
||||
- #12804 `4bdb0ce` Fix intermittent rpc_net.py failure. (jnewbery)
|
||||
- #12553 `0e98f96` Prefer wait_until over polling with time.sleep (Empact)
|
||||
- #12486 `cfebd40` Round target fee to 8 decimals in assert_fee_amount (kallewoof)
|
||||
- #12843 `df38b13` Test starting bitcoind with -h and -version (jnewbery)
|
||||
- #12475 `41c29f6` Fix python TypeError in script.py (MarcoFalke)
|
||||
- #12638 `0a76ed2` Cache only chain and wallet for regtest datadir (MarcoFalke)
|
||||
- #12902 `7460945` Handle potential cookie race when starting node (sdaftuar)
|
||||
- #12904 `6c26df0` Ensure bitcoind processes are cleaned up when tests end (sdaftuar)
|
||||
- #13049 `9ea62a3` Backports (MarcoFalke)
|
||||
- #13201 `b8aacd6` Handle disconnect_node race (sdaftuar)
|
||||
- #13061 `170b309` Make tests pass after 2020 (bmwiedemann)
|
||||
- #13192 `79c4fff` [tests] Fixed intermittent failure in `p2p_sendheaders.py` (lmanners)
|
||||
- #13300 `d9c5630` qa: Initialize lockstack to prevent null pointer deref (MarcoFalke)
|
||||
- #13545 `e15e3a9` tests: Fix test case `streams_serializedata_xor` Remove Boost dependency. (practicalswift)
|
||||
- #13304 `cbdabef` qa: Fix `wallet_listreceivedby` race (MarcoFalke)
|
||||
|
||||
### Miscellaneous
|
||||
- #12518 `a17fecf` Bump leveldb subtree (MarcoFalke)
|
||||
- #12442 `f3b8d85` devtools: Exclude patches from lint-whitespace (MarcoFalke)
|
||||
- #12988 `acdf433` Hold cs_main while calling UpdatedBlockTip() signal (skeees)
|
||||
- #12985 `0684cf9` Windows: Avoid launching as admin when NSIS installer ends. (JeremyRand)
|
||||
|
||||
### Documentation
|
||||
- #12637 `60086dd` backport: #12556 fix version typo in getpeerinfo RPC call help (fanquake)
|
||||
- #13184 `4087dd0` RPC Docs: `gettxout*`: clarify bestblock and unspent counts (harding)
|
||||
- #13246 `6de7543` Bump to Ubuntu Bionic 18.04 in build-windows.md (ken2812221)
|
||||
- #12556 `e730b82` Fix version typo in getpeerinfo RPC call help (tamasblummer)
|
||||
- #12887 `2291774` Add newlines to end of log messages (jnewbery)
|
||||
- #12859 `18b0c69` Bugfix: Include <memory> for `std::unique_ptr` (luke-jr)
|
||||
- #13131 `ce8aa54` Add Windows shutdown handler (ken2812221)
|
||||
- #13652 `20461fc` rpc: Fix that CWallet::AbandonTransaction would leave the grandchildren, etc. active (Empact)
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Thanks to everyone who directly contributed to this release:
|
||||
|
||||
- 251
|
||||
- 532479301
|
||||
- Ben Woosley
|
||||
- Bernhard M. Wiedemann
|
||||
- Chun Kuan Lee
|
||||
- David A. Harding
|
||||
- e0
|
||||
- Cory Fields
|
||||
- fanquake
|
||||
- Henrik Jonsson
|
||||
- JeremyRand
|
||||
- Jesse Cohen
|
||||
- Gregory Sanders
|
||||
- joemphilips
|
||||
- John Newbery
|
||||
- Johnson Lau
|
||||
- Karl-Johan Alm
|
||||
- Kristaps Kaupe
|
||||
- lmanners
|
||||
- Luke Dashjr
|
||||
- MarcoFalke
|
||||
- Matt Corallo
|
||||
- Pieter Wuille
|
||||
- practicalswift
|
||||
- Sjors Provoost
|
||||
- Suhas Daftuar
|
||||
- Tamas Blummer
|
||||
- Wladimir J. van der Laan
|
||||
|
||||
And to those that reported security issues:
|
||||
|
||||
- Braydon Fuller
|
||||
- Himanshu Mehta
|
||||
|
||||
As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/).
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <util.h>
|
||||
#include <utilstrencodings.h>
|
||||
|
||||
#include <memory>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <event2/buffer.h>
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <utilmoneystr.h>
|
||||
#include <utilstrencodings.h>
|
||||
|
||||
#include <memory>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <utilstrencodings.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <memory>
|
||||
|
||||
#include <chainparamsseeds.h>
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <util.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <memory>
|
||||
|
||||
const std::string CBaseChainParams::MAIN = "main";
|
||||
const std::string CBaseChainParams::TESTNET = "test";
|
||||
|
@ -82,12 +82,12 @@ void static inline WriteBE64(unsigned char* ptr, uint64_t x)
|
||||
/** Return the smallest number n such that (x >> n) == 0 (or 64 if the highest bit in x is set. */
|
||||
uint64_t static inline CountBits(uint64_t x)
|
||||
{
|
||||
#ifdef HAVE_DECL___BUILTIN_CLZL
|
||||
#if HAVE_DECL___BUILTIN_CLZL
|
||||
if (sizeof(unsigned long) >= sizeof(uint64_t)) {
|
||||
return x ? 8 * sizeof(unsigned long) - __builtin_clzl(x) : 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_DECL___BUILTIN_CLZLL
|
||||
#if HAVE_DECL___BUILTIN_CLZLL
|
||||
if (sizeof(unsigned long long) >= sizeof(uint64_t)) {
|
||||
return x ? 8 * sizeof(unsigned long long) - __builtin_clzll(x) : 0;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <dbwrapper.h>
|
||||
|
||||
#include <memory>
|
||||
#include <random.h>
|
||||
|
||||
#include <leveldb/cache.h>
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include <crypto/hmac_sha256.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/algorithm/string.hpp> // boost::trim
|
||||
|
||||
/** WWW-Authenticate to present with 401 Unauthorized response */
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <sync.h>
|
||||
#include <ui_interface.h>
|
||||
|
||||
#include <memory>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
13
src/init.cpp
13
src/init.cpp
@ -287,6 +287,7 @@ void Shutdown()
|
||||
* The execution context the handler is invoked in is not guaranteed,
|
||||
* so we restrict handler operations to just touching variables:
|
||||
*/
|
||||
#ifndef WIN32
|
||||
static void HandleSIGTERM(int)
|
||||
{
|
||||
fRequestShutdown = true;
|
||||
@ -296,6 +297,14 @@ static void HandleSIGHUP(int)
|
||||
{
|
||||
fReopenDebugLog = true;
|
||||
}
|
||||
#else
|
||||
static BOOL WINAPI consoleCtrlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
fRequestShutdown = true;
|
||||
Sleep(INFINITE);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
static void registerSignalHandler(int signal, void(*handler)(int))
|
||||
@ -679,7 +688,7 @@ void ThreadImport(std::vector<fs::path> vImportFiles)
|
||||
// scan for better chains in the block chain database, that are not yet connected in the active best chain
|
||||
CValidationState state;
|
||||
if (!ActivateBestChain(state, chainparams)) {
|
||||
LogPrintf("Failed to connect best block");
|
||||
LogPrintf("Failed to connect best block\n");
|
||||
StartShutdown();
|
||||
return;
|
||||
}
|
||||
@ -884,6 +893,8 @@ bool AppInitBasicSetup()
|
||||
|
||||
// Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#else
|
||||
SetConsoleCtrlHandler(consoleCtrlHandler, true);
|
||||
#endif
|
||||
|
||||
std::set_new_handler(new_handler_terminate);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
@ -115,6 +115,12 @@ public:
|
||||
* returns the merkle root, or 0 in case of failure
|
||||
*/
|
||||
uint256 ExtractMatches(std::vector<uint256> &vMatch, std::vector<unsigned int> &vnIndex);
|
||||
|
||||
/** Get number of transactions the merkle proof is indicating for cross-reference with
|
||||
* local blockchain knowledge.
|
||||
*/
|
||||
unsigned int GetNumTransactions() const { return nTransactions; };
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <validationinterface.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <ui_interface.h>
|
||||
#include <utilstrencodings.h>
|
||||
|
||||
#include <memory>
|
||||
#ifdef WIN32
|
||||
#include <string.h>
|
||||
#else
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <utilmoneystr.h>
|
||||
#include <utilstrencodings.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# error "Litecoin cannot be compiled without assertions."
|
||||
#endif
|
||||
@ -1219,9 +1221,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
||||
if (!push) {
|
||||
vNotFound.push_back(inv);
|
||||
}
|
||||
|
||||
// Track requests for our stuff.
|
||||
GetMainSignals().Inventory(inv.hash);
|
||||
}
|
||||
} // release cs_main
|
||||
|
||||
@ -1906,9 +1905,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||
pfrom->AskFor(inv);
|
||||
}
|
||||
}
|
||||
|
||||
// Track requests for our stuff
|
||||
GetMainSignals().Inventory(inv.hash);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <sync.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
#include <net.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QStringList>
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <wallet/wallet.h>
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
@ -688,7 +689,7 @@ int main(int argc, char *argv[])
|
||||
// Allow parameter interaction before we create the options model
|
||||
app.parameterSetup();
|
||||
// Load GUI settings from QSettings
|
||||
app.createOptionsModel(gArgs.IsArgSet("-resetguisettings"));
|
||||
app.createOptionsModel(gArgs.GetBoolArg("-resetguisettings", false));
|
||||
|
||||
// Subscribe to global signals from core
|
||||
uiInterface.InitMessage.connect(InitMessage);
|
||||
|
@ -923,6 +923,7 @@ void BitcoinGUI::message(const QString &title, const QString &message, unsigned
|
||||
|
||||
showNormalIfMinimized();
|
||||
QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons, this);
|
||||
mBox.setTextFormat(Qt::PlainText);
|
||||
int r = mBox.exec();
|
||||
if (ret != nullptr)
|
||||
*ret = r == QMessageBox::Ok;
|
||||
|
@ -27,8 +27,6 @@ static const bool DEFAULT_SPLASHSCREEN = true;
|
||||
#define COLOR_BAREADDRESS QColor(140, 140, 140)
|
||||
/* Transaction list -- TX status decoration - open until date */
|
||||
#define COLOR_TX_STATUS_OPENUNTILDATE QColor(64, 64, 255)
|
||||
/* Transaction list -- TX status decoration - offline */
|
||||
#define COLOR_TX_STATUS_OFFLINE QColor(192, 192, 192)
|
||||
/* Transaction list -- TX status decoration - danger, tx needs attention */
|
||||
#define COLOR_TX_STATUS_DANGER QColor(200, 100, 100)
|
||||
/* Transaction list -- TX status decoration - default color */
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include <openssl/x509_vfy.h>
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include <net_processing.h> // For CNodeStateStats
|
||||
#include <net.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QStringList>
|
||||
|
||||
|
@ -379,6 +379,12 @@ void SendCoinsDialog::on_sendButton_clicked()
|
||||
|
||||
void SendCoinsDialog::clear()
|
||||
{
|
||||
// Clear coin control settings
|
||||
CoinControlDialog::coinControl()->UnSelectAll();
|
||||
ui->checkBoxCoinControlChange->setChecked(false);
|
||||
ui->lineEditCoinControlChange->clear();
|
||||
coinControlUpdateLabels();
|
||||
|
||||
// Remove entries until only one left
|
||||
while(ui->entries->count())
|
||||
{
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include <qt/recentrequeststablemodel.h>
|
||||
#include <qt/receiverequestdialog.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QAbstractButton>
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
|
@ -36,8 +36,6 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
|
||||
int nDepth = wtx.GetDepthInMainChain();
|
||||
if (nDepth < 0)
|
||||
return tr("conflicted with a transaction with %1 confirmations").arg(-nDepth);
|
||||
else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
|
||||
return tr("%1/offline").arg(nDepth);
|
||||
else if (nDepth == 0)
|
||||
return tr("0/unconfirmed, %1").arg((wtx.InMempool() ? tr("in memory pool") : tr("not in memory pool"))) + (wtx.isAbandoned() ? ", "+tr("abandoned") : "");
|
||||
else if (nDepth < 6)
|
||||
@ -61,14 +59,6 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
||||
CAmount nNet = nCredit - nDebit;
|
||||
|
||||
strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx);
|
||||
int nRequests = wtx.GetRequestCount();
|
||||
if (nRequests != -1)
|
||||
{
|
||||
if (nRequests == 0)
|
||||
strHTML += tr(", has not been successfully broadcast yet");
|
||||
else if (nRequests > 0)
|
||||
strHTML += tr(", broadcast through %n node(s)", "", nRequests);
|
||||
}
|
||||
strHTML += "<br>";
|
||||
|
||||
strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
|
||||
|
@ -205,10 +205,6 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
|
||||
if (wtx.IsInMainChain())
|
||||
{
|
||||
status.matures_in = wtx.GetBlocksToMaturity();
|
||||
|
||||
// Check if the block was requested by anyone
|
||||
if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
|
||||
status.status = TransactionStatus::MaturesWarning;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -226,10 +222,6 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
|
||||
{
|
||||
status.status = TransactionStatus::Conflicted;
|
||||
}
|
||||
else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
|
||||
{
|
||||
status.status = TransactionStatus::Offline;
|
||||
}
|
||||
else if (status.depth == 0)
|
||||
{
|
||||
status.status = TransactionStatus::Unconfirmed;
|
||||
|
@ -21,7 +21,7 @@ class TransactionStatus
|
||||
public:
|
||||
TransactionStatus():
|
||||
countsForBalance(false), sortKey(""),
|
||||
matures_in(0), status(Offline), depth(0), open_for(0), cur_num_blocks(-1)
|
||||
matures_in(0), status(Unconfirmed), depth(0), open_for(0), cur_num_blocks(-1)
|
||||
{ }
|
||||
|
||||
enum Status {
|
||||
@ -29,14 +29,12 @@ public:
|
||||
/// Normal (sent/received) transactions
|
||||
OpenUntilDate, /**< Transaction not yet final, waiting for date */
|
||||
OpenUntilBlock, /**< Transaction not yet final, waiting for block */
|
||||
Offline, /**< Not sent to any other nodes **/
|
||||
Unconfirmed, /**< Not yet mined into a block **/
|
||||
Confirming, /**< Confirmed, but waiting for the recommended number of confirmations **/
|
||||
Conflicted, /**< Conflicts with other transaction or mempool **/
|
||||
Abandoned, /**< Abandoned from the wallet **/
|
||||
/// Generated (mined) transactions
|
||||
Immature, /**< Mined but waiting for maturity */
|
||||
MaturesWarning, /**< Transaction will likely not mature because no nodes have confirmed */
|
||||
NotAccepted /**< Mined but not accepted */
|
||||
};
|
||||
|
||||
|
@ -308,9 +308,6 @@ QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) cons
|
||||
case TransactionStatus::OpenUntilDate:
|
||||
status = tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx->status.open_for));
|
||||
break;
|
||||
case TransactionStatus::Offline:
|
||||
status = tr("Offline");
|
||||
break;
|
||||
case TransactionStatus::Unconfirmed:
|
||||
status = tr("Unconfirmed");
|
||||
break;
|
||||
@ -329,9 +326,6 @@ QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) cons
|
||||
case TransactionStatus::Immature:
|
||||
status = tr("Immature (%1 confirmations, will be available after %2)").arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in);
|
||||
break;
|
||||
case TransactionStatus::MaturesWarning:
|
||||
status = tr("This block was not received by any other nodes and will probably not be accepted!");
|
||||
break;
|
||||
case TransactionStatus::NotAccepted:
|
||||
status = tr("Generated but not accepted");
|
||||
break;
|
||||
@ -469,8 +463,6 @@ QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx)
|
||||
case TransactionStatus::OpenUntilBlock:
|
||||
case TransactionStatus::OpenUntilDate:
|
||||
return COLOR_TX_STATUS_OPENUNTILDATE;
|
||||
case TransactionStatus::Offline:
|
||||
return COLOR_TX_STATUS_OFFLINE;
|
||||
case TransactionStatus::Unconfirmed:
|
||||
return QIcon(":/icons/transaction_0");
|
||||
case TransactionStatus::Abandoned:
|
||||
@ -493,7 +485,6 @@ QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx)
|
||||
int part = (wtx->status.depth * 4 / total) + 1;
|
||||
return QIcon(QString(":/icons/transaction_%1").arg(part));
|
||||
}
|
||||
case TransactionStatus::MaturesWarning:
|
||||
case TransactionStatus::NotAccepted:
|
||||
return QIcon(":/icons/transaction_0");
|
||||
default:
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
#include <qt/walletmodel.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class SendCoinsRecipient;
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include <boost/thread/thread.hpp> // boost::thread::interrupt
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
@ -104,6 +105,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex)
|
||||
result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits)));
|
||||
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
|
||||
result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
|
||||
result.push_back(Pair("nTx", (uint64_t)blockindex->nTx));
|
||||
|
||||
if (blockindex->pprev)
|
||||
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
|
||||
@ -149,6 +151,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
|
||||
result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
|
||||
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
|
||||
result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
|
||||
result.push_back(Pair("nTx", (uint64_t)blockindex->nTx));
|
||||
|
||||
if (blockindex->pprev)
|
||||
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
|
||||
@ -678,6 +681,7 @@ UniValue getblockheader(const JSONRPCRequest& request)
|
||||
" \"bits\" : \"1d00ffff\", (string) The bits\n"
|
||||
" \"difficulty\" : x.xxx, (numeric) The difficulty\n"
|
||||
" \"chainwork\" : \"0000...1f3\" (string) Expected number of hashes required to produce the current chain (in hex)\n"
|
||||
" \"nTx\" : n, (numeric) The number of transactions in the block.\n"
|
||||
" \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
|
||||
" \"nextblockhash\" : \"hash\", (string) The hash of the next block\n"
|
||||
"}\n"
|
||||
@ -747,6 +751,7 @@ UniValue getblock(const JSONRPCRequest& request)
|
||||
" \"bits\" : \"1d00ffff\", (string) The bits\n"
|
||||
" \"difficulty\" : x.xxx, (numeric) The difficulty\n"
|
||||
" \"chainwork\" : \"xxxx\", (string) Expected number of hashes required to produce the chain up to this block (in hex)\n"
|
||||
" \"nTx\" : n, (numeric) The number of transactions in the block.\n"
|
||||
" \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
|
||||
" \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
|
||||
"}\n"
|
||||
|
@ -477,7 +477,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
|
||||
checktxtime = std::chrono::steady_clock::now() + std::chrono::minutes(1);
|
||||
|
||||
WaitableLock lock(csBestBlock);
|
||||
while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
|
||||
while (hashBestBlock == hashWatchedChain && IsRPCRunning())
|
||||
{
|
||||
if (cvBlockChange.wait_until(lock, checktxtime) == std::cv_status::timeout)
|
||||
{
|
||||
|
@ -290,7 +290,7 @@ UniValue verifytxoutproof(const JSONRPCRequest& request)
|
||||
"\nArguments:\n"
|
||||
"1. \"proof\" (string, required) The hex-encoded proof generated by gettxoutproof\n"
|
||||
"\nResult:\n"
|
||||
"[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof is invalid\n"
|
||||
"[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof can not be validated.\n"
|
||||
);
|
||||
|
||||
CDataStream ssMB(ParseHexV(request.params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
|
||||
@ -306,11 +306,16 @@ UniValue verifytxoutproof(const JSONRPCRequest& request)
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
if (!mapBlockIndex.count(merkleBlock.header.GetHash()) || !chainActive.Contains(mapBlockIndex[merkleBlock.header.GetHash()]))
|
||||
if (!mapBlockIndex.count(merkleBlock.header.GetHash()) || !chainActive.Contains(mapBlockIndex[merkleBlock.header.GetHash()]) || mapBlockIndex[merkleBlock.header.GetHash()]->nTx == 0)
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
|
||||
|
||||
for (const uint256& hash : vMatch)
|
||||
res.push_back(hash.GetHex());
|
||||
// Check if proof is valid, only add results if so
|
||||
if (mapBlockIndex[merkleBlock.header.GetHash()]->nTx == merkleBlock.txn.GetNumTransactions()) {
|
||||
for (const uint256& hash : vMatch) {
|
||||
res.push_back(hash.GetHex());
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
LockedPoolManager* LockedPoolManager::_instance = nullptr;
|
||||
std::once_flag LockedPoolManager::init_flag;
|
||||
|
20
src/sync.cpp
20
src/sync.cpp
@ -4,6 +4,7 @@
|
||||
|
||||
#include <sync.h>
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <util.h>
|
||||
#include <utilstrencodings.h>
|
||||
@ -72,7 +73,7 @@ struct LockData {
|
||||
std::mutex dd_mutex;
|
||||
} static lockdata;
|
||||
|
||||
static thread_local std::unique_ptr<LockStack> lockstack;
|
||||
static thread_local LockStack g_lockstack;
|
||||
|
||||
static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
|
||||
{
|
||||
@ -102,21 +103,18 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch,
|
||||
|
||||
static void push_lock(void* c, const CLockLocation& locklocation)
|
||||
{
|
||||
if (!lockstack)
|
||||
lockstack.reset(new LockStack);
|
||||
|
||||
std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
|
||||
|
||||
lockstack->push_back(std::make_pair(c, locklocation));
|
||||
g_lockstack.push_back(std::make_pair(c, locklocation));
|
||||
|
||||
for (const std::pair<void*, CLockLocation> & i : (*lockstack)) {
|
||||
for (const std::pair<void*, CLockLocation>& i : g_lockstack) {
|
||||
if (i.first == c)
|
||||
break;
|
||||
|
||||
std::pair<void*, void*> p1 = std::make_pair(i.first, c);
|
||||
if (lockdata.lockorders.count(p1))
|
||||
continue;
|
||||
lockdata.lockorders[p1] = (*lockstack);
|
||||
lockdata.lockorders[p1] = g_lockstack;
|
||||
|
||||
std::pair<void*, void*> p2 = std::make_pair(c, i.first);
|
||||
lockdata.invlockorders.insert(p2);
|
||||
@ -127,7 +125,7 @@ static void push_lock(void* c, const CLockLocation& locklocation)
|
||||
|
||||
static void pop_lock()
|
||||
{
|
||||
(*lockstack).pop_back();
|
||||
g_lockstack.pop_back();
|
||||
}
|
||||
|
||||
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
|
||||
@ -143,14 +141,14 @@ void LeaveCritical()
|
||||
std::string LocksHeld()
|
||||
{
|
||||
std::string result;
|
||||
for (const std::pair<void*, CLockLocation> & i : *lockstack)
|
||||
for (const std::pair<void*, CLockLocation>& i : g_lockstack)
|
||||
result += i.second.ToString() + std::string("\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
|
||||
{
|
||||
for (const std::pair<void*, CLockLocation> & i : *lockstack)
|
||||
for (const std::pair<void*, CLockLocation>& i : g_lockstack)
|
||||
if (i.first == cs)
|
||||
return;
|
||||
fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
|
||||
@ -159,7 +157,7 @@ void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine,
|
||||
|
||||
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
|
||||
{
|
||||
for (const std::pair<void*, CLockLocation>& i : *lockstack) {
|
||||
for (const std::pair<void*, CLockLocation>& i : g_lockstack) {
|
||||
if (i.first == cs) {
|
||||
fprintf(stderr, "Assertion failed: lock %s held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
|
||||
abort();
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <support/allocators/secure.h>
|
||||
#include <test/test_bitcoin.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(allocator_tests, BasicTestingSetup)
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <random.h>
|
||||
#include <test/test_bitcoin.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
// Test if a string consists entirely of null characters
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include <chainparams.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class CAddrManSerializationMock : public CAddrMan
|
||||
{
|
||||
public:
|
||||
|
@ -256,14 +256,14 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
|
||||
ar = r.get_array();
|
||||
BOOST_CHECK_EQUAL(ar.size(), 0);
|
||||
|
||||
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0/24 add 1607731200 true")));
|
||||
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0/24 add 9907731200 true")));
|
||||
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
|
||||
ar = r.get_array();
|
||||
o1 = ar[0].get_obj();
|
||||
adr = find_value(o1, "address");
|
||||
UniValue banned_until = find_value(o1, "banned_until");
|
||||
BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24");
|
||||
BOOST_CHECK_EQUAL(banned_until.get_int64(), 1607731200); // absolute time check
|
||||
BOOST_CHECK_EQUAL(banned_until.get_int64(), 9907731200); // absolute time check
|
||||
|
||||
BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
|
||||
|
||||
|
@ -6,11 +6,8 @@
|
||||
#include <support/allocators/zeroafterfree.h>
|
||||
#include <test/test_bitcoin.h>
|
||||
|
||||
#include <boost/assign/std/vector.hpp> // for 'operator+=()'
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace boost::assign; // bring 'operator+=()' into scope
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(streams_tests, BasicTestingSetup)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(streams_vector_writer)
|
||||
@ -80,14 +77,17 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
|
||||
|
||||
// Degenerate case
|
||||
|
||||
key += '\x00','\x00';
|
||||
key.push_back('\x00');
|
||||
key.push_back('\x00');
|
||||
ds.Xor(key);
|
||||
BOOST_CHECK_EQUAL(
|
||||
std::string(expected_xor.begin(), expected_xor.end()),
|
||||
std::string(ds.begin(), ds.end()));
|
||||
|
||||
in += '\x0f','\xf0';
|
||||
expected_xor += '\xf0','\x0f';
|
||||
in.push_back('\x0f');
|
||||
in.push_back('\xf0');
|
||||
expected_xor.push_back('\xf0');
|
||||
expected_xor.push_back('\x0f');
|
||||
|
||||
// Single character key
|
||||
|
||||
@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
|
||||
ds.insert(ds.begin(), in.begin(), in.end());
|
||||
key.clear();
|
||||
|
||||
key += '\xff';
|
||||
key.push_back('\xff');
|
||||
ds.Xor(key);
|
||||
BOOST_CHECK_EQUAL(
|
||||
std::string(expected_xor.begin(), expected_xor.end()),
|
||||
@ -105,14 +105,17 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
|
||||
|
||||
in.clear();
|
||||
expected_xor.clear();
|
||||
in += '\xf0','\x0f';
|
||||
expected_xor += '\x0f','\x00';
|
||||
in.push_back('\xf0');
|
||||
in.push_back('\x0f');
|
||||
expected_xor.push_back('\x0f');
|
||||
expected_xor.push_back('\x00');
|
||||
|
||||
ds.clear();
|
||||
ds.insert(ds.begin(), in.begin(), in.end());
|
||||
|
||||
key.clear();
|
||||
key += '\xff','\x0f';
|
||||
key.push_back('\xff');
|
||||
key.push_back('\x0f');
|
||||
|
||||
ds.Xor(key);
|
||||
BOOST_CHECK_EQUAL(
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include <txdb.h>
|
||||
#include <txmempool.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
extern uint256 insecure_rand_seed;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
enum TEST_ID {
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#include <net.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
std::unique_ptr<CConnman> g_connman;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <chain.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <atomic>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -210,6 +210,7 @@ CChain& chainActive = g_chainstate.chainActive;
|
||||
CBlockIndex *pindexBestHeader = nullptr;
|
||||
CWaitableCriticalSection csBestBlock;
|
||||
CConditionVariable cvBlockChange;
|
||||
uint256 hashBestBlock;
|
||||
int nScriptCheckThreads = 0;
|
||||
std::atomic_bool fImporting(false);
|
||||
std::atomic_bool fReindex(false);
|
||||
@ -2152,7 +2153,11 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
|
||||
// New best block
|
||||
mempool.AddTransactionsUpdated(1);
|
||||
|
||||
cvBlockChange.notify_all();
|
||||
{
|
||||
WaitableLock lock(csBestBlock);
|
||||
hashBestBlock = pindexNew->GetBlockHash();
|
||||
cvBlockChange.notify_all();
|
||||
}
|
||||
|
||||
std::vector<std::string> warningMessages;
|
||||
if (!IsInitialBlockDownload())
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
@ -165,6 +166,7 @@ extern uint64_t nLastBlockWeight;
|
||||
extern const std::string strMessageMagic;
|
||||
extern CWaitableCriticalSection csBestBlock;
|
||||
extern CConditionVariable cvBlockChange;
|
||||
extern uint256 hashBestBlock;
|
||||
extern std::atomic_bool fImporting;
|
||||
extern std::atomic_bool fReindex;
|
||||
extern int nScriptCheckThreads;
|
||||
|
@ -26,7 +26,6 @@ struct MainSignalsInstance {
|
||||
boost::signals2::signal<void (const std::shared_ptr<const CBlock> &)> BlockDisconnected;
|
||||
boost::signals2::signal<void (const CTransactionRef &)> TransactionRemovedFromMempool;
|
||||
boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
|
||||
boost::signals2::signal<void (const uint256 &)> Inventory;
|
||||
boost::signals2::signal<void (int64_t nBestBlockTime, CConnman* connman)> Broadcast;
|
||||
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
|
||||
boost::signals2::signal<void (const CBlockIndex *, const std::shared_ptr<const CBlock>&)> NewPoWValidBlock;
|
||||
@ -81,7 +80,6 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
|
||||
g_signals.m_internals->BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1));
|
||||
g_signals.m_internals->TransactionRemovedFromMempool.connect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1));
|
||||
g_signals.m_internals->SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
|
||||
g_signals.m_internals->Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
|
||||
g_signals.m_internals->Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
|
||||
g_signals.m_internals->BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
|
||||
g_signals.m_internals->NewPoWValidBlock.connect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2));
|
||||
@ -90,7 +88,6 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
|
||||
void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
|
||||
g_signals.m_internals->BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
|
||||
g_signals.m_internals->Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
|
||||
g_signals.m_internals->Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
|
||||
g_signals.m_internals->SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
|
||||
g_signals.m_internals->TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1));
|
||||
g_signals.m_internals->BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3));
|
||||
@ -106,7 +103,6 @@ void UnregisterAllValidationInterfaces() {
|
||||
}
|
||||
g_signals.m_internals->BlockChecked.disconnect_all_slots();
|
||||
g_signals.m_internals->Broadcast.disconnect_all_slots();
|
||||
g_signals.m_internals->Inventory.disconnect_all_slots();
|
||||
g_signals.m_internals->SetBestChain.disconnect_all_slots();
|
||||
g_signals.m_internals->TransactionAddedToMempool.disconnect_all_slots();
|
||||
g_signals.m_internals->BlockConnected.disconnect_all_slots();
|
||||
@ -172,12 +168,6 @@ void CMainSignals::SetBestChain(const CBlockLocator &locator) {
|
||||
});
|
||||
}
|
||||
|
||||
void CMainSignals::Inventory(const uint256 &hash) {
|
||||
m_internals->m_schedulerClient.AddToProcessQueue([hash, this] {
|
||||
m_internals->Inventory(hash);
|
||||
});
|
||||
}
|
||||
|
||||
void CMainSignals::Broadcast(int64_t nBestBlockTime, CConnman* connman) {
|
||||
m_internals->Broadcast(nBestBlockTime, connman);
|
||||
}
|
||||
|
@ -101,12 +101,6 @@ protected:
|
||||
* Called on a background thread.
|
||||
*/
|
||||
virtual void SetBestChain(const CBlockLocator &locator) {}
|
||||
/**
|
||||
* Notifies listeners about an inventory item being seen on the network.
|
||||
*
|
||||
* Called on a background thread.
|
||||
*/
|
||||
virtual void Inventory(const uint256 &hash) {}
|
||||
/** Tells listeners to broadcast their data. */
|
||||
virtual void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) {}
|
||||
/**
|
||||
@ -157,7 +151,6 @@ public:
|
||||
void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>> &);
|
||||
void BlockDisconnected(const std::shared_ptr<const CBlock> &);
|
||||
void SetBestChain(const CBlockLocator &);
|
||||
void Inventory(const uint256 &);
|
||||
void Broadcast(int64_t nBestBlockTime, CConnman* connman);
|
||||
void BlockChecked(const CBlock&, const CValidationState&);
|
||||
void NewPoWValidBlock(const CBlockIndex *, const std::shared_ptr<const CBlock>&);
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -432,7 +432,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
|
||||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
|
||||
throw std::runtime_error(
|
||||
"importpubkey \"pubkey\" ( \"label\" rescan )\n"
|
||||
"\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
|
||||
|
@ -1537,7 +1537,7 @@ UniValue listreceivedbyaddress(const JSONRPCRequest& request)
|
||||
" \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
|
||||
" \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
|
||||
" \"txids\": [\n"
|
||||
" n, (numeric) The ids of transactions received with the address \n"
|
||||
" \"txid\", (string) The ids of transactions received with the address \n"
|
||||
" ...\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
@ -2322,8 +2322,7 @@ UniValue walletpassphrase(const JSONRPCRequest& request)
|
||||
"This is needed prior to performing transactions related to private keys such as sending litecoins\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"passphrase\" (string, required) The wallet passphrase\n"
|
||||
"2. timeout (numeric, required) The time to keep the decryption key in seconds. Limited to at most 1073741824 (2^30) seconds.\n"
|
||||
" Any value greater than 1073741824 seconds will be set to 1073741824 seconds.\n"
|
||||
"2. timeout (numeric, required) The time to keep the decryption key in seconds; capped at 100000000 (~3 years).\n"
|
||||
"\nNote:\n"
|
||||
"Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
|
||||
"time that overrides the old one.\n"
|
||||
@ -2358,9 +2357,10 @@ UniValue walletpassphrase(const JSONRPCRequest& request)
|
||||
if (nSleepTime < 0) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Timeout cannot be negative.");
|
||||
}
|
||||
// Clamp timeout to 2^30 seconds
|
||||
if (nSleepTime > (int64_t)1 << 30) {
|
||||
nSleepTime = (int64_t)1 << 30;
|
||||
// Clamp timeout
|
||||
constexpr int64_t MAX_SLEEP_TIME = 100000000; // larger values trigger a macos/libevent bug?
|
||||
if (nSleepTime > MAX_SLEEP_TIME) {
|
||||
nSleepTime = MAX_SLEEP_TIME;
|
||||
}
|
||||
|
||||
if (strWalletPass.length() > 0)
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
/** Testing setup and teardown for wallet.
|
||||
*/
|
||||
struct WalletTestingSetup: public TestingSetup {
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <stdint.h>
|
||||
#include <utility>
|
||||
|
@ -891,7 +891,7 @@ bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
|
||||
|
||||
bool success = true;
|
||||
if (!walletdb.WriteTx(wtx)) {
|
||||
LogPrintf("%s: Updating walletdb tx %s failed", __func__, wtx.GetHash().ToString());
|
||||
LogPrintf("%s: Updating walletdb tx %s failed\n", __func__, wtx.GetHash().ToString());
|
||||
success = false;
|
||||
}
|
||||
|
||||
@ -913,11 +913,10 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
|
||||
CWalletTx& wtx = (*ret.first).second;
|
||||
wtx.BindWallet(this);
|
||||
bool fInsertedNew = ret.second;
|
||||
if (fInsertedNew)
|
||||
{
|
||||
if (fInsertedNew) {
|
||||
wtx.nTimeReceived = GetAdjustedTime();
|
||||
wtx.nOrderPos = IncOrderPosNext(&walletdb);
|
||||
wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr)));
|
||||
wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr)));
|
||||
wtx.nTimeSmart = ComputeTimeSmart(wtx);
|
||||
AddToSpends(hash);
|
||||
}
|
||||
@ -987,9 +986,12 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
|
||||
bool CWallet::LoadToWallet(const CWalletTx& wtxIn)
|
||||
{
|
||||
uint256 hash = wtxIn.GetHash();
|
||||
CWalletTx& wtx = mapWallet.emplace(hash, wtxIn).first->second;
|
||||
const auto& ins = mapWallet.emplace(hash, wtxIn);
|
||||
CWalletTx& wtx = ins.first->second;
|
||||
wtx.BindWallet(this);
|
||||
wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr)));
|
||||
if (/* insertion took place */ ins.second) {
|
||||
wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr)));
|
||||
}
|
||||
AddToSpends(hash);
|
||||
for (const CTxIn& txin : wtx.tx->vin) {
|
||||
auto it = mapWallet.find(txin.prevout.hash);
|
||||
@ -1122,7 +1124,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
|
||||
walletdb.WriteTx(wtx);
|
||||
NotifyTransactionChanged(this, wtx.GetHash(), CT_UPDATED);
|
||||
// Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too
|
||||
TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(hashTx, 0));
|
||||
TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
|
||||
while (iter != mapTxSpends.end() && iter->first.hash == now) {
|
||||
if (!done.count(iter->second)) {
|
||||
todo.insert(iter->second);
|
||||
@ -1506,45 +1508,6 @@ int64_t CWalletTx::GetTxTime() const
|
||||
return n ? n : nTimeReceived;
|
||||
}
|
||||
|
||||
int CWalletTx::GetRequestCount() const
|
||||
{
|
||||
// Returns -1 if it wasn't being tracked
|
||||
int nRequests = -1;
|
||||
{
|
||||
LOCK(pwallet->cs_wallet);
|
||||
if (IsCoinBase())
|
||||
{
|
||||
// Generated block
|
||||
if (!hashUnset())
|
||||
{
|
||||
std::map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
|
||||
if (mi != pwallet->mapRequestCount.end())
|
||||
nRequests = (*mi).second;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Did anyone request this transaction?
|
||||
std::map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
|
||||
if (mi != pwallet->mapRequestCount.end())
|
||||
{
|
||||
nRequests = (*mi).second;
|
||||
|
||||
// How about the block it's in?
|
||||
if (nRequests == 0 && !hashUnset())
|
||||
{
|
||||
std::map<uint256, int>::const_iterator _mi = pwallet->mapRequestCount.find(hashBlock);
|
||||
if (_mi != pwallet->mapRequestCount.end())
|
||||
nRequests = (*_mi).second;
|
||||
else
|
||||
nRequests = 1; // If it's in someone else's block it must have got out
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nRequests;
|
||||
}
|
||||
|
||||
void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived,
|
||||
std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const
|
||||
{
|
||||
@ -3085,9 +3048,6 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon
|
||||
}
|
||||
}
|
||||
|
||||
// Track how many getdata requests our transaction gets
|
||||
mapRequestCount[wtxNew.GetHash()] = 0;
|
||||
|
||||
// Get the inserted-CWalletTx from mapWallet so that the
|
||||
// fInMempool flag is cached properly
|
||||
CWalletTx& wtx = mapWallet[wtxNew.GetHash()];
|
||||
@ -3165,8 +3125,11 @@ DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256
|
||||
{
|
||||
AssertLockHeld(cs_wallet); // mapWallet
|
||||
DBErrors nZapSelectTxRet = CWalletDB(*dbw,"cr+").ZapSelectTx(vHashIn, vHashOut);
|
||||
for (uint256 hash : vHashOut)
|
||||
mapWallet.erase(hash);
|
||||
for (uint256 hash : vHashOut) {
|
||||
const auto& it = mapWallet.find(hash);
|
||||
wtxOrdered.erase(it->second.m_it_wtxOrdered);
|
||||
mapWallet.erase(it);
|
||||
}
|
||||
|
||||
if (nZapSelectTxRet == DB_NEED_REWRITE)
|
||||
{
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
@ -326,6 +327,7 @@ public:
|
||||
char fFromMe;
|
||||
std::string strFromAccount;
|
||||
int64_t nOrderPos; //!< position in ordered transaction list
|
||||
std::multimap<int64_t, std::pair<CWalletTx*, CAccountingEntry*>>::const_iterator m_it_wtxOrdered;
|
||||
|
||||
// memory only
|
||||
mutable bool fDebitCached;
|
||||
@ -477,7 +479,6 @@ public:
|
||||
bool IsTrusted() const;
|
||||
|
||||
int64_t GetTxTime() const;
|
||||
int GetRequestCount() const;
|
||||
|
||||
// RelayWalletTransaction may only be called if fBroadcastTransactions!
|
||||
bool RelayWalletTransaction(CConnman* connman);
|
||||
@ -833,7 +834,6 @@ public:
|
||||
|
||||
int64_t nOrderPosNext;
|
||||
uint64_t nAccountingEntryNumber;
|
||||
std::map<uint256, int> mapRequestCount;
|
||||
|
||||
std::map<CTxDestination, CAddressBookData> mapAddressBook;
|
||||
|
||||
@ -1042,16 +1042,6 @@ public:
|
||||
|
||||
const std::string& GetAccountName(const CScript& scriptPubKey) const;
|
||||
|
||||
void Inventory(const uint256 &hash) override
|
||||
{
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
|
||||
if (mi != mapRequestCount.end())
|
||||
(*mi).second++;
|
||||
}
|
||||
}
|
||||
|
||||
void GetScriptForMining(std::shared_ptr<CReserveScript> &script);
|
||||
|
||||
unsigned int GetKeyPoolSize()
|
||||
|
@ -260,10 +260,17 @@ class PruneTest(BitcoinTestFramework):
|
||||
# should not prune because chain tip of node 3 (995) < PruneAfterHeight (1000)
|
||||
assert_raises_rpc_error(-1, "Blockchain is too short for pruning", node.pruneblockchain, height(500))
|
||||
|
||||
# Save block transaction count before pruning, assert value
|
||||
block1_details = node.getblock(node.getblockhash(1))
|
||||
assert_equal(block1_details["nTx"], len(block1_details["tx"]))
|
||||
|
||||
# mine 6 blocks so we are at height 1001 (i.e., above PruneAfterHeight)
|
||||
node.generate(6)
|
||||
assert_equal(node.getblockchaininfo()["blocks"], 1001)
|
||||
|
||||
# Pruned block should still know the number of transactions
|
||||
assert_equal(node.getblockheader(node.getblockhash(1))["nTx"], block1_details["nTx"])
|
||||
|
||||
# negative heights should raise an exception
|
||||
assert_raises_rpc_error(-8, "Negative", node.pruneblockchain, -10)
|
||||
|
||||
|
@ -116,6 +116,7 @@ class BaseNode(P2PInterface):
|
||||
|
||||
self.block_announced = False
|
||||
self.last_blockhash_announced = None
|
||||
self.recent_headers_announced = []
|
||||
|
||||
def send_get_data(self, block_hashes):
|
||||
"""Request data for a list of block hashes."""
|
||||
@ -163,40 +164,45 @@ class BaseNode(P2PInterface):
|
||||
def on_headers(self, message):
|
||||
if len(message.headers):
|
||||
self.block_announced = True
|
||||
message.headers[-1].calc_sha256()
|
||||
for x in message.headers:
|
||||
x.calc_sha256()
|
||||
# append because headers may be announced over multiple messages.
|
||||
self.recent_headers_announced.append(x.sha256)
|
||||
self.last_blockhash_announced = message.headers[-1].sha256
|
||||
|
||||
def clear_last_announcement(self):
|
||||
def clear_block_announcements(self):
|
||||
with mininode_lock:
|
||||
self.block_announced = False
|
||||
self.last_message.pop("inv", None)
|
||||
self.last_message.pop("headers", None)
|
||||
self.recent_headers_announced = []
|
||||
|
||||
def check_last_announcement(self, headers=None, inv=None):
|
||||
"""Test whether the last announcement received had the right header or the right inv.
|
||||
|
||||
inv and headers should be lists of block hashes."""
|
||||
def check_last_headers_announcement(self, headers):
|
||||
"""Test whether the last headers announcements received are right.
|
||||
Headers may be announced across more than one message."""
|
||||
test_function = lambda: (len(self.recent_headers_announced) >= len(headers))
|
||||
wait_until(test_function, timeout=60, lock=mininode_lock)
|
||||
with mininode_lock:
|
||||
assert_equal(self.recent_headers_announced, headers)
|
||||
self.block_announced = False
|
||||
self.last_message.pop("headers", None)
|
||||
self.recent_headers_announced = []
|
||||
|
||||
def check_last_inv_announcement(self, inv):
|
||||
"""Test whether the last announcement received had the right inv.
|
||||
inv should be a list of block hashes."""
|
||||
|
||||
test_function = lambda: self.block_announced
|
||||
wait_until(test_function, timeout=60, lock=mininode_lock)
|
||||
|
||||
with mininode_lock:
|
||||
self.block_announced = False
|
||||
|
||||
compare_inv = []
|
||||
if "inv" in self.last_message:
|
||||
compare_inv = [x.hash for x in self.last_message["inv"].inv]
|
||||
if inv is not None:
|
||||
assert_equal(compare_inv, inv)
|
||||
|
||||
compare_headers = []
|
||||
if "headers" in self.last_message:
|
||||
compare_headers = [x.sha256 for x in self.last_message["headers"].headers]
|
||||
if headers is not None:
|
||||
assert_equal(compare_headers, headers)
|
||||
|
||||
assert_equal(compare_inv, inv)
|
||||
self.block_announced = False
|
||||
self.last_message.pop("inv", None)
|
||||
self.last_message.pop("headers", None)
|
||||
|
||||
class SendHeadersTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
@ -206,8 +212,8 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
def mine_blocks(self, count):
|
||||
"""Mine count blocks and return the new tip."""
|
||||
|
||||
# Clear out last block announcement from each p2p listener
|
||||
[x.clear_last_announcement() for x in self.nodes[0].p2ps]
|
||||
# Clear out block announcements from each p2p listener
|
||||
[x.clear_block_announcements() for x in self.nodes[0].p2ps]
|
||||
self.nodes[0].generate(count)
|
||||
return int(self.nodes[0].getbestblockhash(), 16)
|
||||
|
||||
@ -222,7 +228,7 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
sync_blocks(self.nodes, wait=0.1)
|
||||
for x in self.nodes[0].p2ps:
|
||||
x.wait_for_block_announcement(int(self.nodes[0].getbestblockhash(), 16))
|
||||
x.clear_last_announcement()
|
||||
x.clear_block_announcements()
|
||||
|
||||
tip_height = self.nodes[1].getblockcount()
|
||||
hash_to_invalidate = self.nodes[1].getblockhash(tip_height - (length - 1))
|
||||
@ -255,26 +261,26 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
tip = self.nodes[0].getblockheader(self.nodes[0].generate(1)[0])
|
||||
tip_hash = int(tip["hash"], 16)
|
||||
|
||||
inv_node.check_last_announcement(inv=[tip_hash], headers=[])
|
||||
test_node.check_last_announcement(inv=[tip_hash], headers=[])
|
||||
inv_node.check_last_inv_announcement(inv=[tip_hash])
|
||||
test_node.check_last_inv_announcement(inv=[tip_hash])
|
||||
|
||||
self.log.info("Verify getheaders with null locator and valid hashstop returns headers.")
|
||||
test_node.clear_last_announcement()
|
||||
test_node.clear_block_announcements()
|
||||
test_node.send_get_headers(locator=[], hashstop=tip_hash)
|
||||
test_node.check_last_announcement(headers=[tip_hash])
|
||||
test_node.check_last_headers_announcement(headers=[tip_hash])
|
||||
|
||||
self.log.info("Verify getheaders with null locator and invalid hashstop does not return headers.")
|
||||
block = create_block(int(tip["hash"], 16), create_coinbase(tip["height"] + 1), tip["mediantime"] + 1)
|
||||
block.nVersion = 0x20000000
|
||||
block.solve()
|
||||
test_node.send_header_for_blocks([block])
|
||||
test_node.clear_last_announcement()
|
||||
test_node.clear_block_announcements()
|
||||
test_node.send_get_headers(locator=[], hashstop=int(block.hash, 16))
|
||||
test_node.sync_with_ping()
|
||||
assert_equal(test_node.block_announced, False)
|
||||
inv_node.clear_last_announcement()
|
||||
inv_node.clear_block_announcements()
|
||||
test_node.send_message(msg_block(block))
|
||||
inv_node.check_last_announcement(inv=[int(block.hash, 16)], headers=[])
|
||||
inv_node.check_last_inv_announcement(inv=[int(block.hash, 16)])
|
||||
|
||||
def test_nonnull_locators(self, test_node, inv_node):
|
||||
tip = int(self.nodes[0].getbestblockhash(), 16)
|
||||
@ -285,8 +291,8 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
for i in range(4):
|
||||
old_tip = tip
|
||||
tip = self.mine_blocks(1)
|
||||
inv_node.check_last_announcement(inv=[tip], headers=[])
|
||||
test_node.check_last_announcement(inv=[tip], headers=[])
|
||||
inv_node.check_last_inv_announcement(inv=[tip])
|
||||
test_node.check_last_inv_announcement(inv=[tip])
|
||||
# Try a few different responses; none should affect next announcement
|
||||
if i == 0:
|
||||
# first request the block
|
||||
@ -297,7 +303,7 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
test_node.send_get_headers(locator=[old_tip], hashstop=tip)
|
||||
test_node.send_get_data([tip])
|
||||
test_node.wait_for_block(tip)
|
||||
test_node.clear_last_announcement() # since we requested headers...
|
||||
test_node.clear_block_announcements() # since we requested headers...
|
||||
elif i == 2:
|
||||
# this time announce own block via headers
|
||||
height = self.nodes[0].getblockcount()
|
||||
@ -310,8 +316,8 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
test_node.wait_for_getdata([new_block.sha256])
|
||||
test_node.send_message(msg_block(new_block))
|
||||
test_node.sync_with_ping() # make sure this block is processed
|
||||
inv_node.clear_last_announcement()
|
||||
test_node.clear_last_announcement()
|
||||
inv_node.clear_block_announcements()
|
||||
test_node.clear_block_announcements()
|
||||
|
||||
self.log.info("Part 1: success!")
|
||||
self.log.info("Part 2: announce blocks with headers after sendheaders message...")
|
||||
@ -325,8 +331,8 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
|
||||
# Now that we've synced headers, headers announcements should work
|
||||
tip = self.mine_blocks(1)
|
||||
inv_node.check_last_announcement(inv=[tip], headers=[])
|
||||
test_node.check_last_announcement(headers=[tip])
|
||||
inv_node.check_last_inv_announcement(inv=[tip])
|
||||
test_node.check_last_headers_announcement(headers=[tip])
|
||||
|
||||
height = self.nodes[0].getblockcount() + 1
|
||||
block_time += 10 # Advance far enough ahead
|
||||
@ -371,8 +377,8 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
assert "inv" not in inv_node.last_message
|
||||
assert "headers" not in inv_node.last_message
|
||||
tip = self.mine_blocks(1)
|
||||
inv_node.check_last_announcement(inv=[tip], headers=[])
|
||||
test_node.check_last_announcement(headers=[tip])
|
||||
inv_node.check_last_inv_announcement(inv=[tip])
|
||||
test_node.check_last_headers_announcement(headers=[tip])
|
||||
height += 1
|
||||
block_time += 1
|
||||
|
||||
@ -386,16 +392,16 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
# First try mining a reorg that can propagate with header announcement
|
||||
new_block_hashes = self.mine_reorg(length=7)
|
||||
tip = new_block_hashes[-1]
|
||||
inv_node.check_last_announcement(inv=[tip], headers=[])
|
||||
test_node.check_last_announcement(headers=new_block_hashes)
|
||||
inv_node.check_last_inv_announcement(inv=[tip])
|
||||
test_node.check_last_headers_announcement(headers=new_block_hashes)
|
||||
|
||||
block_time += 8
|
||||
|
||||
# Mine a too-large reorg, which should be announced with a single inv
|
||||
new_block_hashes = self.mine_reorg(length=8)
|
||||
tip = new_block_hashes[-1]
|
||||
inv_node.check_last_announcement(inv=[tip], headers=[])
|
||||
test_node.check_last_announcement(inv=[tip], headers=[])
|
||||
inv_node.check_last_inv_announcement(inv=[tip])
|
||||
test_node.check_last_inv_announcement(inv=[tip])
|
||||
|
||||
block_time += 9
|
||||
|
||||
@ -404,15 +410,15 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
|
||||
# Use getblocks/getdata
|
||||
test_node.send_getblocks(locator=[fork_point])
|
||||
test_node.check_last_announcement(inv=new_block_hashes, headers=[])
|
||||
test_node.check_last_inv_announcement(inv=new_block_hashes)
|
||||
test_node.send_get_data(new_block_hashes)
|
||||
test_node.wait_for_block(new_block_hashes[-1])
|
||||
|
||||
for i in range(3):
|
||||
# Mine another block, still should get only an inv
|
||||
tip = self.mine_blocks(1)
|
||||
inv_node.check_last_announcement(inv=[tip], headers=[])
|
||||
test_node.check_last_announcement(inv=[tip], headers=[])
|
||||
inv_node.check_last_inv_announcement(inv=[tip])
|
||||
test_node.check_last_inv_announcement(inv=[tip])
|
||||
if i == 0:
|
||||
# Just get the data -- shouldn't cause headers announcements to resume
|
||||
test_node.send_get_data([tip])
|
||||
@ -437,8 +443,8 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
test_node.sync_with_ping()
|
||||
# New blocks should now be announced with header
|
||||
tip = self.mine_blocks(1)
|
||||
inv_node.check_last_announcement(inv=[tip], headers=[])
|
||||
test_node.check_last_announcement(headers=[tip])
|
||||
inv_node.check_last_inv_announcement(inv=[tip])
|
||||
test_node.check_last_headers_announcement(headers=[tip])
|
||||
|
||||
self.log.info("Part 3: success!")
|
||||
|
||||
|
@ -185,6 +185,7 @@ class BlockchainTest(BitcoinTestFramework):
|
||||
assert_equal(header['confirmations'], 1)
|
||||
assert_equal(header['previousblockhash'], secondbesthash)
|
||||
assert_is_hex_string(header['chainwork'])
|
||||
assert_equal(header['nTx'], 1)
|
||||
assert_is_hash_string(header['hash'])
|
||||
assert_is_hash_string(header['previousblockhash'])
|
||||
assert_is_hash_string(header['merkleroot'])
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
from test_framework.mininode import FromHex, ToHex
|
||||
from test_framework.messages import CMerkleBlock
|
||||
|
||||
class MerkleBlockTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
@ -78,6 +80,27 @@ class MerkleBlockTest(BitcoinTestFramework):
|
||||
# We can't get a proof if we specify transactions from different blocks
|
||||
assert_raises_rpc_error(-5, "Not all transactions found in specified or retrieved block", self.nodes[2].gettxoutproof, [txid1, txid3])
|
||||
|
||||
# Now we'll try tweaking a proof.
|
||||
proof = self.nodes[3].gettxoutproof([txid1, txid2])
|
||||
assert txid1 in self.nodes[0].verifytxoutproof(proof)
|
||||
assert txid2 in self.nodes[1].verifytxoutproof(proof)
|
||||
|
||||
tweaked_proof = FromHex(CMerkleBlock(), proof)
|
||||
|
||||
# Make sure that our serialization/deserialization is working
|
||||
assert txid1 in self.nodes[2].verifytxoutproof(ToHex(tweaked_proof))
|
||||
|
||||
# Check to see if we can go up the merkle tree and pass this off as a
|
||||
# single-transaction block
|
||||
tweaked_proof.txn.nTransactions = 1
|
||||
tweaked_proof.txn.vHash = [tweaked_proof.header.hashMerkleRoot]
|
||||
tweaked_proof.txn.vBits = [True] + [False]*7
|
||||
|
||||
for n in self.nodes:
|
||||
assert not n.verifytxoutproof(ToHex(tweaked_proof))
|
||||
|
||||
# TODO: try more variants, eg transactions at different depths, and
|
||||
# verify that the proofs are invalid
|
||||
|
||||
if __name__ == '__main__':
|
||||
MerkleBlockTest().main()
|
||||
|
@ -836,6 +836,52 @@ class BlockTransactions():
|
||||
def __repr__(self):
|
||||
return "BlockTransactions(hash=%064x transactions=%s)" % (self.blockhash, repr(self.transactions))
|
||||
|
||||
class CPartialMerkleTree():
|
||||
def __init__(self):
|
||||
self.nTransactions = 0
|
||||
self.vHash = []
|
||||
self.vBits = []
|
||||
self.fBad = False
|
||||
|
||||
def deserialize(self, f):
|
||||
self.nTransactions = struct.unpack("<i", f.read(4))[0]
|
||||
self.vHash = deser_uint256_vector(f)
|
||||
vBytes = deser_string(f)
|
||||
self.vBits = []
|
||||
for i in range(len(vBytes) * 8):
|
||||
self.vBits.append(vBytes[i//8] & (1 << (i % 8)) != 0)
|
||||
|
||||
def serialize(self):
|
||||
r = b""
|
||||
r += struct.pack("<i", self.nTransactions)
|
||||
r += ser_uint256_vector(self.vHash)
|
||||
vBytesArray = bytearray([0x00] * ((len(self.vBits) + 7)//8))
|
||||
for i in range(len(self.vBits)):
|
||||
vBytesArray[i // 8] |= self.vBits[i] << (i % 8)
|
||||
r += ser_string(bytes(vBytesArray))
|
||||
return r
|
||||
|
||||
def __repr__(self):
|
||||
return "CPartialMerkleTree(nTransactions=%d, vHash=%s, vBits=%s)" % (self.nTransactions, repr(self.vHash), repr(self.vBits))
|
||||
|
||||
class CMerkleBlock():
|
||||
def __init__(self):
|
||||
self.header = CBlockHeader()
|
||||
self.txn = CPartialMerkleTree()
|
||||
|
||||
def deserialize(self, f):
|
||||
self.header.deserialize(f)
|
||||
self.txn.deserialize(f)
|
||||
|
||||
def serialize(self):
|
||||
r = b""
|
||||
r += self.header.serialize()
|
||||
r += self.txn.serialize()
|
||||
return r
|
||||
|
||||
def __repr__(self):
|
||||
return "CMerkleBlock(header=%s, txn=%s)" % (repr(self.header), repr(self.txn))
|
||||
|
||||
|
||||
# Objects that correspond to messages on the wire
|
||||
class msg_version():
|
||||
|
@ -64,9 +64,17 @@ class AbandonConflictTest(BitcoinTestFramework):
|
||||
signed2 = self.nodes[0].signrawtransaction(self.nodes[0].createrawtransaction(inputs, outputs))
|
||||
txABC2 = self.nodes[0].sendrawtransaction(signed2["hex"])
|
||||
|
||||
# Create a child tx spending ABC2
|
||||
signed3_change = Decimal("24.999")
|
||||
inputs = [ {"txid":txABC2, "vout":0} ]
|
||||
outputs = { self.nodes[0].getnewaddress(): signed3_change }
|
||||
signed3 = self.nodes[0].signrawtransaction(self.nodes[0].createrawtransaction(inputs, outputs))
|
||||
# note tx is never directly referenced, only abandoned as a child of the above
|
||||
self.nodes[0].sendrawtransaction(signed3["hex"])
|
||||
|
||||
# In mempool txs from self should increase balance from change
|
||||
newbalance = self.nodes[0].getbalance()
|
||||
assert_equal(newbalance, balance - Decimal("30") + Decimal("24.96"))
|
||||
assert_equal(newbalance, balance - Decimal("30") + signed3_change)
|
||||
balance = newbalance
|
||||
|
||||
# Restart the node with a higher min relay fee so the parent tx is no longer in mempool
|
||||
@ -81,7 +89,7 @@ class AbandonConflictTest(BitcoinTestFramework):
|
||||
# Not in mempool txs from self should only reduce balance
|
||||
# inputs are still spent, but change not received
|
||||
newbalance = self.nodes[0].getbalance()
|
||||
assert_equal(newbalance, balance - Decimal("24.96"))
|
||||
assert_equal(newbalance, balance - signed3_change)
|
||||
# Unconfirmed received funds that are not in mempool, also shouldn't show
|
||||
# up in unconfirmed balance
|
||||
unconfbalance = self.nodes[0].getunconfirmedbalance() + self.nodes[0].getbalance()
|
||||
|
@ -64,14 +64,15 @@ class WalletEncryptionTest(BitcoinTestFramework):
|
||||
assert_raises_rpc_error(-8, "Timeout cannot be negative.", self.nodes[0].walletpassphrase, passphrase2, -10)
|
||||
# Check the timeout
|
||||
# Check a time less than the limit
|
||||
expected_time = int(time.time()) + (1 << 30) - 600
|
||||
self.nodes[0].walletpassphrase(passphrase2, (1 << 30) - 600)
|
||||
MAX_VALUE = 100000000
|
||||
expected_time = int(time.time()) + MAX_VALUE - 600
|
||||
self.nodes[0].walletpassphrase(passphrase2, MAX_VALUE - 600)
|
||||
actual_time = self.nodes[0].getwalletinfo()['unlocked_until']
|
||||
assert_greater_than_or_equal(actual_time, expected_time)
|
||||
assert_greater_than(expected_time + 5, actual_time) # 5 second buffer
|
||||
# Check a time greater than the limit
|
||||
expected_time = int(time.time()) + (1 << 30) - 1
|
||||
self.nodes[0].walletpassphrase(passphrase2, (1 << 33))
|
||||
expected_time = int(time.time()) + MAX_VALUE - 1
|
||||
self.nodes[0].walletpassphrase(passphrase2, MAX_VALUE + 1000)
|
||||
actual_time = self.nodes[0].getwalletinfo()['unlocked_until']
|
||||
assert_greater_than_or_equal(actual_time, expected_time)
|
||||
assert_greater_than(expected_time + 5, actual_time) # 5 second buffer
|
||||
|
@ -6,10 +6,13 @@
|
||||
from decimal import Decimal
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (assert_array_result,
|
||||
assert_equal,
|
||||
assert_raises_rpc_error,
|
||||
)
|
||||
from test_framework.util import (
|
||||
assert_array_result,
|
||||
assert_equal,
|
||||
assert_raises_rpc_error,
|
||||
sync_blocks,
|
||||
)
|
||||
|
||||
|
||||
class ReceivedByTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
@ -18,6 +21,7 @@ class ReceivedByTest(BitcoinTestFramework):
|
||||
def run_test(self):
|
||||
# Generate block to get out of IBD
|
||||
self.nodes[0].generate(1)
|
||||
sync_blocks(self.nodes)
|
||||
|
||||
self.log.info("listreceivedbyaddress Test")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user