diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 88d80a8f2e0..15d1a7450cc 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -1894,6 +1894,7 @@ Value getmemorypool(const Array& params, bool fHelp) " \"mintime\" : minimum timestamp appropriate for next block\n" " \"curtime\" : current timestamp\n" " \"bits\" : compressed target of next block\n" + " \"height\" : height of the next block (backported, required by BIP 34)\n" "If [data] is specified, tries to solve the block and returns true if it was successful."); if (params.size() == 0) @@ -1929,6 +1930,12 @@ Value getmemorypool(const Array& params, bool fHelp) pblock = NULL; } pblock = CreateNewBlock(reservekey); + if (!((!fTestNet && CBlockIndex::IsSuperMajority(2, pindexBest, 950, 1000)) || + (fTestNet && CBlockIndex::IsSuperMajority(2, pindexBest, 75, 100)))) + { + // As long as version 1 blocks are valid at all, use them to be more compatible with old implementations + pblock->nVersion = 1; + } if (!pblock) throw JSONRPCError(-7, "Out of memory"); @@ -1961,6 +1968,7 @@ Value getmemorypool(const Array& params, bool fHelp) result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); result.push_back(Pair("curtime", (int64_t)GetAdjustedTime())); result.push_back(Pair("bits", HexBits(pblock->nBits))); + result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); return result; } diff --git a/src/main.cpp b/src/main.cpp index 320a8df205b..ecf2fafc893 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1739,6 +1739,28 @@ bool CBlock::AcceptBlock() if (!Checkpoints::CheckBlock(nHeight, hash)) return DoS(100, error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight)); + // Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded: + if (nVersion < 2) + { + if ((!fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 950, 1000)) || + (fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 75, 100))) + { + return error("AcceptBlock() : rejected nVersion=1 block"); + } + } + // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height + if (nVersion >= 2) + { + // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): + if ((!fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 750, 1000)) || + (fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 51, 100))) + { + CScript expect = CScript() << nHeight; + if (!std::equal(expect.begin(), expect.end(), vtx[0].vin[0].scriptSig.begin())) + return error("AcceptBlock() : block height mismatch in coinbase"); + } + } + // Write block to history file if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION))) return error("AcceptBlock() : out of disk space"); @@ -1762,6 +1784,18 @@ bool CBlock::AcceptBlock() return true; } +bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned int nRequired, unsigned int nToCheck) +{ + unsigned int nFound = 0; + for (unsigned int i = 0; i < nToCheck && nFound < nRequired && pstart != NULL; i++) + { + if (pstart->nVersion >= minVersion) + ++nFound; + pstart = pstart->pprev; + } + return (nFound >= nRequired); +} + bool ProcessBlock(CNode* pfrom, CBlock* pblock) { // Check for duplicate @@ -1896,7 +1930,7 @@ FILE* AppendBlockFile(unsigned int& nFileRet) if (fseek(file, 0, SEEK_END) != 0) return NULL; // FAT32 file size max 4GB, fseek and ftell max 2GB, so we must stay under 2GB - if (ftell(file) < 0x7F000000 - MAX_SIZE) + if (ftell(file) < (long)(0x7F000000 - MAX_SIZE)) { nFileRet = nCurrentBlockFile; return file; @@ -3361,7 +3395,8 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& hashPrevBlock = pblock->hashPrevBlock; } ++nExtraNonce; - pblock->vtx[0].vin[0].scriptSig = (CScript() << pblock->nTime << CBigNum(nExtraNonce)) + COINBASE_FLAGS; + unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2 + pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CBigNum(nExtraNonce)) + COINBASE_FLAGS; assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100); pblock->hashMerkleRoot = pblock->BuildMerkleTree(); diff --git a/src/main.h b/src/main.h index a906ff51ca4..b9a19458618 100644 --- a/src/main.h +++ b/src/main.h @@ -386,6 +386,7 @@ typedef std::map > MapPrevTx; class CTransaction { public: + static const int CURRENT_VERSION=1; int nVersion; std::vector vin; std::vector vout; @@ -411,7 +412,7 @@ public: void SetNull() { - nVersion = 1; + nVersion = CTransaction::CURRENT_VERSION; vin.clear(); vout.clear(); nLockTime = 0; @@ -817,6 +818,7 @@ class CBlock { public: // header + static const int CURRENT_VERSION=2; int nVersion; uint256 hashPrevBlock; uint256 hashMerkleRoot; @@ -858,7 +860,7 @@ public: void SetNull() { - nVersion = 1; + nVersion = CBlock::CURRENT_VERSION; hashPrevBlock = 0; hashMerkleRoot = 0; nTime = 0; @@ -1181,6 +1183,12 @@ public: return pindex->GetMedianTimePast(); } + /** + * Returns true if there are nRequired or more blocks of minVersion or above + * in the last nToCheck blocks, starting at pstart and going backwards. + */ + static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, + unsigned int nRequired, unsigned int nToCheck); std::string ToString() const diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw index 5f0bdf67e9b..e746424a330 100644 --- a/src/makefile.linux-mingw +++ b/src/makefile.linux-mingw @@ -34,7 +34,10 @@ CFLAGS=-O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATH TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data) -ifdef USE_UPNP +ifndef USE_UPNP + override USE_UPNP = - +endif +ifneq (${USE_UPNP}, -) LIBPATHS += -L"$(DEPSDIR)/miniupnpc" LIBS += -l miniupnpc -l iphlpapi DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP) diff --git a/src/makefile.mingw b/src/makefile.mingw index 37201e36214..842b3c67ec3 100644 --- a/src/makefile.mingw +++ b/src/makefile.mingw @@ -29,7 +29,10 @@ CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(I TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data) -ifdef USE_UPNP +ifndef USE_UPNP + override USE_UPNP = - +endif +ifneq (${USE_UPNP}, -) INCLUDEPATHS += -I"C:\miniupnpc-1.6-mgw" LIBPATHS += -L"C:\miniupnpc-1.6-mgw" LIBS += -l miniupnpc -l iphlpapi diff --git a/src/makefile.osx b/src/makefile.osx index 11c62487675..16a0edfe82d 100644 --- a/src/makefile.osx +++ b/src/makefile.osx @@ -90,7 +90,10 @@ OBJS= \ obj/walletdb.o \ obj/noui.o -ifdef USE_UPNP +ifndef USE_UPNP + override USE_UPNP = - +endif +ifneq (${USE_UPNP}, -) DEFS += -DUSE_UPNP=$(USE_UPNP) ifdef STATIC LIBS += $(DEPSDIR)/lib/libminiupnpc.a @@ -111,7 +114,7 @@ version.cpp: obj/build.h DEFS += -DHAVE_BUILD_INFO obj/%.o: %.cpp - $(CXX) -c $(CFLAGS) -MMD -o $@ $< + $(CXX) -c $(CFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< @cp $(@:%.o=%.d) $(@:%.o=%.P); \ sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ @@ -123,7 +126,7 @@ bitcoind: $(OBJS:obj/%=obj/%) TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp)) obj-test/%.o: test/%.cpp - $(CXX) -c $(TESTDEFS) $(CFLAGS) -MMD -o $@ $< + $(CXX) -c $(TESTDEFS) $(CFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< @cp $(@:%.o=%.d) $(@:%.o=%.P); \ sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ diff --git a/src/makefile.unix b/src/makefile.unix index 58331cacce1..4d8f48143cb 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -121,7 +121,7 @@ version.cpp: obj/build.h DEFS += -DHAVE_BUILD_INFO obj/%.o: %.cpp - $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< + $(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< @cp $(@:%.o=%.d) $(@:%.o=%.P); \ sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ @@ -133,7 +133,7 @@ bitcoind: $(OBJS:obj/%=obj/%) TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp)) obj-test/%.o: test/%.cpp - $(CXX) -c $(TESTDEFS) $(xCXXFLAGS) -MMD -o $@ $< + $(CXX) -c $(TESTDEFS) $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< @cp $(@:%.o=%.d) $(@:%.o=%.P); \ sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 83e32e0d741..d9fcbd93908 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -53,6 +53,7 @@ #include #include +#include #include @@ -146,6 +147,15 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): progressBar->setAlignment(Qt::AlignCenter); progressBar->setVisible(false); + // Override style sheet for progress bar for styles that have a segmented progress bar, + // as they make the text unreadable (workaround for issue #1071) + // See https://qt-project.org/doc/qt-4.8/gallery.html + QString curStyle = qApp->style()->metaObject()->className(); + if(curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle") + { + progressBar->setStyleSheet("QProgressBar { background-color: #e8e8e8; border: 1px solid grey; border-radius: 7px; padding: 1px; text-align: center; } QProgressBar::chunk { background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #FF8000, stop: 1 orange); border-radius: 7px; margin: 0px; }"); + } + statusBar()->addWidget(progressBarLabel); statusBar()->addWidget(progressBar); statusBar()->addPermanentWidget(frameBlocks); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index f8f0d5f8a6a..9b70afaefab 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -131,28 +131,28 @@ void SendCoinsDialog::on_sendButton_clicked() break; case WalletModel::AmountExceedsBalance: QMessageBox::warning(this, tr("Send Coins"), - tr("Amount exceeds your balance"), + tr("The amount exceeds your balance."), QMessageBox::Ok, QMessageBox::Ok); break; case WalletModel::AmountWithFeeExceedsBalance: QMessageBox::warning(this, tr("Send Coins"), - tr("Total exceeds your balance when the %1 transaction fee is included"). + tr("The total exceeds your balance when the %1 transaction fee is included."). arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, sendstatus.fee)), QMessageBox::Ok, QMessageBox::Ok); break; case WalletModel::DuplicateAddress: QMessageBox::warning(this, tr("Send Coins"), - tr("Duplicate address found, can only send to each address once in one send operation"), + tr("Duplicate address found, can only send to each address once per send operation."), QMessageBox::Ok, QMessageBox::Ok); break; case WalletModel::TransactionCreationFailed: QMessageBox::warning(this, tr("Send Coins"), - tr("Error: Transaction creation failed "), + tr("Error: Transaction creation failed."), QMessageBox::Ok, QMessageBox::Ok); break; case WalletModel::TransactionCommitFailed: QMessageBox::warning(this, tr("Send Coins"), - tr("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."), + tr("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."), QMessageBox::Ok, QMessageBox::Ok); break; case WalletModel::Aborted: // User aborted, nothing to do diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index 5b11e39ea37..af2d358fc47 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -6,6 +6,11 @@ // This is all you need to run all the tests int main(int argc, char *argv[]) { + bool fInvalid = false; + URITests test1; - QTest::qExec(&test1); + if (QTest::qExec(&test1) != 0) + fInvalid = true; + + return fInvalid; } diff --git a/src/qt/test/uritests.cpp b/src/qt/test/uritests.cpp index a281c39ca56..4662f5ed31c 100644 --- a/src/qt/test/uritests.cpp +++ b/src/qt/test/uritests.cpp @@ -47,7 +47,7 @@ void URITests::uriTests() uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=100&label=Wikipedia Example")); QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); - QVERIFY(rv.amount == 10000000000); + QVERIFY(rv.amount == 10000000000LL); QVERIFY(rv.label == QString("Wikipedia Example")); uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address"));