diff --git a/share/genbuild.sh b/share/genbuild.sh index a15cb34e4..1ef77d706 100755 --- a/share/genbuild.sh +++ b/share/genbuild.sh @@ -15,7 +15,6 @@ fi DESC="" SUFFIX="" -LAST_COMMIT_DATE="" if [ -e "$(which git 2>/dev/null)" -a "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]; then # clean 'dirty' status of touched files that haven't been modified git diff >/dev/null 2>/dev/null @@ -29,9 +28,6 @@ if [ -e "$(which git 2>/dev/null)" -a "$(git rev-parse --is-inside-work-tree 2>/ # otherwise generate suffix from git, i.e. string like "59887e8-dirty" SUFFIX=$(git rev-parse --short HEAD) git diff-index --quiet HEAD -- || SUFFIX="$SUFFIX-dirty" - - # get a string like "2012-04-10 16:27:19 +0200" - LAST_COMMIT_DATE="$(git log -n 1 --format="%ci")" fi if [ -n "$DESC" ]; then @@ -45,7 +41,4 @@ fi # only update build.h if necessary if [ "$INFO" != "$NEWINFO" ]; then echo "$NEWINFO" >"$FILE" - if [ -n "$LAST_COMMIT_DATE" ]; then - echo "#define BUILD_DATE \"$LAST_COMMIT_DATE\"" >> "$FILE" - fi fi diff --git a/src/clientversion.cpp b/src/clientversion.cpp index aae0569bb..bfe9e16f8 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -67,16 +67,7 @@ const std::string CLIENT_NAME("Satoshi"); #endif #endif -#ifndef BUILD_DATE -#ifdef GIT_COMMIT_DATE -#define BUILD_DATE GIT_COMMIT_DATE -#else -#define BUILD_DATE __DATE__ ", " __TIME__ -#endif -#endif - const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX); -const std::string CLIENT_DATE(BUILD_DATE); static std::string FormatVersion(int nVersion) { diff --git a/src/clientversion.h b/src/clientversion.h index 652afbf6e..e929c1f48 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -59,7 +59,6 @@ static const int CLIENT_VERSION = extern const std::string CLIENT_NAME; extern const std::string CLIENT_BUILD; -extern const std::string CLIENT_DATE; std::string FormatFullVersion(); diff --git a/src/httpserver.cpp b/src/httpserver.cpp index ce1accb04..a98eff7c1 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -252,7 +252,7 @@ static std::string RequestMethodString(HTTPRequest::RequestMethod m) /** HTTP request callback */ static void http_request_cb(struct evhttp_request* req, void* arg) { - std::auto_ptr hreq(new HTTPRequest(req)); + std::unique_ptr hreq(new HTTPRequest(req)); LogPrint("http", "Received a %s request for %s from %s\n", RequestMethodString(hreq->GetRequestMethod()), hreq->GetURI(), hreq->GetPeer().ToString()); @@ -288,7 +288,7 @@ static void http_request_cb(struct evhttp_request* req, void* arg) // Dispatch to worker thread if (i != iend) { - std::auto_ptr item(new HTTPWorkItem(hreq.release(), path, i->handler)); + std::unique_ptr item(new HTTPWorkItem(hreq.release(), path, i->handler)); assert(workQueue); if (workQueue->Enqueue(item.get())) item.release(); /* if true, queue took ownership */ diff --git a/src/init.cpp b/src/init.cpp index 4b031e466..b2d8d9827 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -758,7 +758,7 @@ void InitLogging() fLogIPs = GetBoolArg("-logips", DEFAULT_LOGIPS); LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - LogPrintf("Bitcoin version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); + LogPrintf("Bitcoin version %s\n", FormatFullVersion()); } /** Initialize bitcoin. diff --git a/src/main.cpp b/src/main.cpp index fec12ade2..8a9261afa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,6 +48,10 @@ #include #include #include +#include +#include +#include +#include #include using namespace std; @@ -1883,9 +1887,32 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach UpdateCoins(tx, state, inputs, txundo, nHeight); } -class CachingTransactionSignatureCheckerWithBlockReader : public CachingTransactionSignatureChecker, public BaseBlockReader { +class CachingTransactionSignatureCheckerWithBlockReader : public CachingTransactionSignatureChecker, public BaseBlockReader +{ + typedef std::pair CoinbaseCacheItem; + typedef boost::multi_index_container< + CoinbaseCacheItem, + boost::multi_index::indexed_by< + boost::multi_index::sequenced<>, + boost::multi_index::ordered_unique< + boost::multi_index::member + > + > + > CoinbaseCacheContainer; + int nHeight; uint256 hash; + + mutable boost::mutex mutexCache; + mutable CoinbaseCacheContainer cacheCoinbase; // block hash -> block coinbase + + void UpdateCache(const CoinbaseCacheItem& coinbase) const; + + CTransaction ReadBlockCoinbase(CBlockIndex* pblockindex) const; + +public: +const unsigned int MAX_COUNT_ACKS_CACHE = 1000; + public: virtual int GetBlockNumber() const; @@ -1893,12 +1920,14 @@ public: virtual bool CountAcks(const std::vector& chainId, int periodAck, int periodLiveness, int& positive, int& negative) const; - CachingTransactionSignatureCheckerWithBlockReader(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn, int height) - :CachingTransactionSignatureChecker(txToIn, nInIn, storeIn), nHeight(height), hash(txToIn->GetHash()) - { - } + CachingTransactionSignatureCheckerWithBlockReader(const CTransaction* txToIn, unsigned int nInIn, bool storeIn, int height); }; +CachingTransactionSignatureCheckerWithBlockReader::CachingTransactionSignatureCheckerWithBlockReader(const CTransaction* txToIn, unsigned int nInIn, bool storeIn, int height) + : CachingTransactionSignatureChecker(txToIn, nInIn, storeIn), nHeight(height), hash(txToIn->GetHash()) +{ +} + int CachingTransactionSignatureCheckerWithBlockReader::GetBlockNumber() const { return nHeight; @@ -1913,13 +1942,30 @@ CTransaction CachingTransactionSignatureCheckerWithBlockReader::GetBlockCoinbase return CTransaction(); CBlockIndex* pblockindex = chainActive[nHeight]; + + { + boost::lock_guard lock(mutexCache); + CoinbaseCacheContainer::nth_index<1>::type::iterator it = cacheCoinbase.get<1>().find(*pblockindex->phashBlock); + if (it != cacheCoinbase.get<1>().end()) + return it->second; + } + CTransaction coinbase = ReadBlockCoinbase(pblockindex); + if (!coinbase.IsNull()) + UpdateCache(std::make_pair(*pblockindex->phashBlock, coinbase)); + + return coinbase; +} + +CTransaction CachingTransactionSignatureCheckerWithBlockReader::ReadBlockCoinbase(CBlockIndex* pblockindex) const +{ + CBlock block; if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) return CTransaction(); - if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) + if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) return CTransaction(); if (block.vtx.empty()) @@ -1931,6 +1977,17 @@ CTransaction CachingTransactionSignatureCheckerWithBlockReader::GetBlockCoinbase return block.vtx[0]; } +void CachingTransactionSignatureCheckerWithBlockReader::UpdateCache(const CachingTransactionSignatureCheckerWithBlockReader::CoinbaseCacheItem& coinbase) const +{ + boost::lock_guard lock(mutexCache); + std::pair result = cacheCoinbase.push_front(coinbase); + if (!result.second) { + cacheCoinbase.relocate(cacheCoinbase.begin(), result.first); + } else if (cacheCoinbase.size() > MAX_COUNT_ACKS_CACHE) { + cacheCoinbase.pop_back(); + } +} + bool CachingTransactionSignatureCheckerWithBlockReader::CountAcks(const std::vector& chainId, int periodAck, int periodLiveness, int& positiveAcks, int& negativeAcks) const { std::vector hashSpend(hash.begin(), hash.end()); @@ -1939,7 +1996,7 @@ bool CachingTransactionSignatureCheckerWithBlockReader::CountAcks(const std::vec bool CScriptCheck::operator()() { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; - if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, nHeight, cacheStore), &error)) { + if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, cacheStore), &error)) { return false; } return true; diff --git a/src/miner.cpp b/src/miner.cpp index 5d793e46f..093549eaf 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -96,7 +96,7 @@ int64_t GetMaxTransactionTime(CBlock* pblock) CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& scriptPubKeyIn, int64_t* pFees, bool fProofOfStake) { // Create new block - auto_ptr pblocktemplate(new CBlockTemplate()); + std::unique_ptr pblocktemplate(new CBlockTemplate()); if(!pblocktemplate.get()) return NULL; CBlock *pblock = &pblocktemplate->block; // pointer for convenience diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index ba052ffb5..27be0299d 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -162,7 +162,7 @@ UniValue generate(const UniValue& params, bool fHelp) UniValue blockHashes(UniValue::VARR); while (nHeight < nHeightEnd) { - auto_ptr pblocktemplate(CreateNewBlock(Params(), coinbaseScript->reserveScript, 0, false)); + std::unique_ptr pblocktemplate(CreateNewBlock(Params(), coinbaseScript->reserveScript, 0, false)); if (!pblocktemplate.get()) throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); CBlock *pblock = &pblocktemplate->block; diff --git a/src/script/drivechain.h b/src/script/drivechain.h index bcf1b4e47..fd5d616af 100644 --- a/src/script/drivechain.h +++ b/src/script/drivechain.h @@ -12,9 +12,52 @@ #include #include +#define LIMITED_VECTOR(obj, n) REF(MakeLimitedVector(obj)) + const unsigned char ACK_LABEL[] = {0x41, 0x43, 0x4B, 0x3A}; // "ACK:" const size_t ACK_LABEL_LENGTH = sizeof(ACK_LABEL); +template +class LimitedVector +{ +protected: + std::vector& vec; + +public: + LimitedVector(std::vector& vec) : vec(vec) {} + + template + void Unserialize(Stream& s, int, int = 0) + { + size_t size = ReadCompactSize(s); + if (size > Limit) { + throw std::ios_base::failure("String length limit exceeded"); + } + vec.resize(size); + if (size != 0) + s.read((char*)&vec[0], size); + } + + template + void Serialize(Stream& s, int, int = 0) const + { + WriteCompactSize(s, vec.size()); + if (!vec.empty()) + s.write((char*)&vec[0], vec.size()); + } + + unsigned int GetSerializeSize(int, int = 0) const + { + return GetSizeOfCompactSize(vec.size()) + vec.size(); + } +}; + +template +LimitedVector MakeLimitedVector(std::vector& obj) +{ + return LimitedVector(obj); +} + class Ack { public: @@ -28,26 +71,28 @@ public: { uint64_t nPayload = 0; if (!ser_action.ForRead()) - nPayload = CalcPayloadSize(); + nPayload = CalcPayloadSize(nType, nVersion); READWRITE(COMPACTSIZE(nPayload)); - READWRITE(prefix); + if (nPayload == 0) + throw std::runtime_error("Not valid ACK"); + READWRITE(LIMITED_VECTOR(prefix, 32)); // Empty preimage should not be serialized if (ser_action.ForRead()) { uint64_t nPrefix = prefix.size(); nPrefix += GetSizeOfCompactSize(nPrefix); if (nPayload > nPrefix) - READWRITE(preimage); - if (CalcPayloadSize() != nPayload) + READWRITE(LIMITED_VECTOR(preimage, 32)); + if (CalcPayloadSize(nType, nVersion) != nPayload) throw std::runtime_error("Not valid ACK"); } else { if (preimage.size() > 0) - READWRITE(preimage); + READWRITE(LIMITED_VECTOR(preimage, 32)); } } - uint64_t CalcPayloadSize() const + unsigned int CalcPayloadSize(int nType, int nVersion) const { - uint64_t nPayload = 0; + unsigned int nPayload = 0; nPayload += GetSizeOfCompactSize(prefix.size()); nPayload += prefix.size(); // Empty preimage should not be serialized @@ -58,12 +103,6 @@ public: return nPayload; } - uint64_t CalcSize() const - { - uint64_t nPayload = CalcPayloadSize(); - return GetSizeOfCompactSize(nPayload) + nPayload; - } - Ack() {} Ack(std::vector prefix, std::vector preimage = std::vector()) : prefix(prefix), preimage(preimage) @@ -83,14 +122,14 @@ public: { uint64_t sizePayload = 0; if (!ser_action.ForRead()) - sizePayload = CalcPayloadSize(); + sizePayload = CalcPayloadSize(nType, nVersion); READWRITE(COMPACTSIZE(sizePayload)); if (ser_action.ForRead()) { - uint64_t read = 0; + unsigned int read = 0; while (read < sizePayload) { Ack ack; READWRITE(ack); - read += ack.CalcSize(); + read += ack.GetSerializeSize(nType, nVersion); vAck.push_back(ack); } if (read != sizePayload) @@ -102,24 +141,15 @@ public: } } - uint64_t CalcPayloadSize() const + unsigned int CalcPayloadSize(int nType, int nVersion) const { - uint64_t nPayload = 0; + unsigned int nPayload = 0; for (const Ack& ack : vAck) { - nPayload += ack.CalcSize(); + nPayload += ack.GetSerializeSize(nType, nVersion); } return nPayload; } - uint64_t CalcSize() const - { - uint64_t nSize = 0; - uint64_t nPayloadSize = CalcPayloadSize(); - nSize += GetSizeOfCompactSize(nPayloadSize); - nSize += nPayloadSize; - return nSize; - } - AckList() {} AckList(std::vector acks) : vAck(acks) {} }; @@ -137,32 +167,23 @@ public: { uint64_t nPayload = 0; if (!ser_action.ForRead()) - nPayload = CalcPayloadSize(); + nPayload = CalcPayloadSize(nType, nVersion); READWRITE(COMPACTSIZE(nPayload)); - READWRITE(chainId); + READWRITE(LIMITED_VECTOR(chainId, 20)); READWRITE(ackList); - if (ser_action.ForRead() && nPayload != CalcPayloadSize()) + if (ser_action.ForRead() && nPayload != CalcPayloadSize(nType, nVersion)) throw std::runtime_error("Not valid CHAIN ACK LIST"); } - uint64_t CalcPayloadSize() const + unsigned int CalcPayloadSize(int nType, int nVersion) const { - uint64_t nPayload = 0; + unsigned int nPayload = 0; nPayload += GetSizeOfCompactSize(chainId.size()); nPayload += chainId.size(); - nPayload += ackList.CalcSize(); + nPayload += ackList.GetSerializeSize(nType, nVersion); return nPayload; } - uint64_t CalcSize() const - { - uint64_t nSize = 0; - uint64_t nPayloadSize = CalcPayloadSize(); - nSize += GetSizeOfCompactSize(nPayloadSize); - nSize += nPayloadSize; - return nSize; - } - ChainAckList& operator<<(Ack ack) { ackList.vAck.push_back(ack); @@ -185,14 +206,14 @@ public: { uint64_t sizePayload = 0; if (!ser_action.ForRead()) - sizePayload = CalcPayloadSize(); + sizePayload = CalcPayloadSize(nType, nVersion); READWRITE(COMPACTSIZE(sizePayload)); if (ser_action.ForRead()) { uint64_t read = 0; while (read < sizePayload) { ChainAckList chainAcks; READWRITE(chainAcks); - read += chainAcks.CalcSize(); + read += chainAcks.GetSerializeSize(nType, nVersion); vChainAcks.push_back(chainAcks); } if (read != sizePayload) @@ -204,24 +225,15 @@ public: } } - uint64_t CalcPayloadSize() const + unsigned int CalcPayloadSize(int nType, int nVersion) const { - uint64_t nPayloadSize = 0; + unsigned int nPayloadSize = 0; for (const auto& chainAcks : vChainAcks) { - nPayloadSize += chainAcks.CalcSize(); + nPayloadSize += chainAcks.GetSerializeSize(nType, nVersion); } return nPayloadSize; } - uint64_t CalcSize() const - { - uint64_t nSize = 0; - uint64_t nPayloadSize = CalcPayloadSize(); - nSize += GetSizeOfCompactSize(nPayloadSize); - nSize += nPayloadSize; - return nSize; - } - FullAckList& operator<<(Ack ack) { if (!vChainAcks.empty()) { diff --git a/src/script/script_error.h b/src/script/script_error.h index 26df33932..d9c88a809 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -51,6 +51,9 @@ typedef enum ScriptError_t /* softfork safeness */ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, + + /* count acks */ + SCRIPT_ERR_COUNT_ACKS_INVALID_PARAM, SCRIPT_ERR_ERROR_COUNT } ScriptError; diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 28b85e8d2..a49ca2fbb 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -116,7 +116,7 @@ BOOST_AUTO_TEST_CASE(sign) { CScript sigSave = txTo[i].vin[0].scriptSig; txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig; - bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false)(); + bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, -1)(); if (i == j) BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j)); else diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index acfc06b19..9b613f21b 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -485,7 +485,7 @@ UniValue dumpwallet(const UniValue& params, bool fHelp) std::sort(vKeyBirth.begin(), vKeyBirth.end()); // produce output - file << strprintf("# Wallet dump created by Bitcoin %s (%s)\n", CLIENT_BUILD, CLIENT_DATE); + file << strprintf("# Wallet dump created by Bitcoin %s\n", CLIENT_BUILD); file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime())); file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString()); file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime()));