diff options
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 154 |
1 files changed, 65 insertions, 89 deletions
diff --git a/src/main.cpp b/src/main.cpp index a5c1103ef4..c7ba15ef13 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,10 +20,10 @@ #include <sstream> -#include <boost/dynamic_bitset.hpp> #include <boost/algorithm/string/replace.hpp> #include <boost/filesystem.hpp> #include <boost/filesystem/fstream.hpp> +#include <boost/thread.hpp> using namespace std; using namespace boost; @@ -644,7 +644,7 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) // 2. P2SH scripts with a crazy number of expensive // CHECKSIG/CHECKMULTISIG operations // -bool AreInputsStandard(const CTransaction& tx, CCoinsViewCache& mapInputs) +bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) { if (tx.IsCoinBase()) return true; // Coinbases don't use vin normally @@ -717,7 +717,7 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx) return nSigOps; } -unsigned int GetP2SHSigOpCount(const CTransaction& tx, CCoinsViewCache& inputs) +unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs) { if (tx.IsCoinBase()) return 0; @@ -1470,7 +1470,7 @@ bool VerifySignature(const CCoins& txFrom, const CTransaction& txTo, unsigned in return CScriptCheck(txFrom, txTo, nIn, flags, nHashType)(); } -bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, std::vector<CScriptCheck> *pvChecks) +bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, std::vector<CScriptCheck> *pvChecks) { if (!tx.IsCoinBase()) { @@ -3527,75 +3527,6 @@ void static ProcessGetData(CNode* pfrom) } } -struct CCoin { - uint32_t nTxVer; // Don't call this nVersion, that name has a special meaning inside IMPLEMENT_SERIALIZE - uint32_t nHeight; - CTxOut out; - - IMPLEMENT_SERIALIZE( - READWRITE(nTxVer); - READWRITE(nHeight); - READWRITE(out); - ) -}; - -bool ProcessGetUTXOs(const vector<COutPoint> &vOutPoints, bool fCheckMemPool, vector<unsigned char> *result, vector<CCoin> *resultCoins) -{ - // Defined by BIP 64. - // - // Allows a peer to retrieve the CTxOut structures corresponding to the given COutPoints. - // Note that this data is not authenticated by anything: this code could just invent any - // old rubbish and hand it back, with the peer being unable to tell unless they are checking - // the outpoints against some out of band data. - // - // Also the answer could change the moment after we give it. However some apps can tolerate - // this, because they're only using the result as a hint or are willing to trust the results - // based on something else. For example we may be a "trusted node" for the peer, or it may - // be checking the results given by several nodes for consistency, it may - // run the UTXOs returned against scriptSigs of transactions obtained elsewhere (after checking - // for a standard script form), and because the height in which the UTXO was defined is provided - // a client that has a map of heights to block headers (as SPV clients do, for recent blocks) - // can request the creating block via hash. - // - // IMPORTANT: Clients expect ordering to be preserved! - if (vOutPoints.size() > MAX_INV_SZ) - return error("message getutxos size() = %u", vOutPoints.size()); - - LogPrint("net", "getutxos for %d queries %s mempool\n", vOutPoints.size(), fCheckMemPool ? "with" : "without"); - - boost::dynamic_bitset<unsigned char> hits(vOutPoints.size()); - { - LOCK2(cs_main, mempool.cs); - CCoinsViewMemPool cvMemPool(*pcoinsTip, mempool); - CCoinsViewCache view(fCheckMemPool ? cvMemPool : *pcoinsTip); - for (size_t i = 0; i < vOutPoints.size(); i++) - { - CCoins coins; - uint256 hash = vOutPoints[i].hash; - if (view.GetCoins(hash, coins)) - { - mempool.pruneSpent(hash, coins); - if (coins.IsAvailable(vOutPoints[i].n)) - { - hits[i] = true; - // Safe to index into vout here because IsAvailable checked if it's off the end of the array, or if - // n is valid but points to an already spent output (IsNull). - CCoin coin; - coin.nTxVer = coins.nVersion; - coin.nHeight = coins.nHeight; - coin.out = coins.vout.at(vOutPoints[i].n); - assert(!coin.out.IsNull()); - resultCoins->push_back(coin); - } - } - } - } - - boost::to_block_range(hits, std::back_inserter(*result)); - return true; -} - - bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived) { RandAddSeedPerfmon(); @@ -3944,22 +3875,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } - else if (strCommand == "getutxos") - { - bool fCheckMemPool; - vector<COutPoint> vOutPoints; - vRecv >> fCheckMemPool; - vRecv >> vOutPoints; - - vector<unsigned char> bitmap; - vector<CCoin> outs; - if (ProcessGetUTXOs(vOutPoints, fCheckMemPool, &bitmap, &outs)) - pfrom->PushMessage("utxos", chainActive.Height(), chainActive.Tip()->GetBlockHash(), bitmap, outs); - else - Misbehaving(pfrom->GetId(), 20); - } - - else if (strCommand == "tx") { vector<uint256> vWorkQueue; @@ -4664,7 +4579,68 @@ bool SendMessages(CNode* pto, bool fSendTrickle) } +bool CBlockUndo::WriteToDisk(CDiskBlockPos &pos, const uint256 &hashBlock) +{ + // Open history file to append + CAutoFile fileout = CAutoFile(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION); + if (!fileout) + return error("CBlockUndo::WriteToDisk : OpenUndoFile failed"); + + // Write index header + unsigned int nSize = fileout.GetSerializeSize(*this); + fileout << FLATDATA(Params().MessageStart()) << nSize; + + // Write undo data + long fileOutPos = ftell(fileout); + if (fileOutPos < 0) + return error("CBlockUndo::WriteToDisk : ftell failed"); + pos.nPos = (unsigned int)fileOutPos; + fileout << *this; + + // calculate & write checksum + CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION); + hasher << hashBlock; + hasher << *this; + fileout << hasher.GetHash(); + + // Flush stdio buffers and commit to disk before returning + fflush(fileout); + if (!IsInitialBlockDownload()) + FileCommit(fileout); + + return true; +} + +bool CBlockUndo::ReadFromDisk(const CDiskBlockPos &pos, const uint256 &hashBlock) +{ + // Open history file to read + CAutoFile filein = CAutoFile(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION); + if (!filein) + return error("CBlockUndo::ReadFromDisk : OpenBlockFile failed"); + + // Read block + uint256 hashChecksum; + try { + filein >> *this; + filein >> hashChecksum; + } + catch (std::exception &e) { + return error("%s : Deserialize or I/O error - %s", __func__, e.what()); + } + + // Verify checksum + CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION); + hasher << hashBlock; + hasher << *this; + if (hashChecksum != hasher.GetHash()) + return error("CBlockUndo::ReadFromDisk : Checksum mismatch"); + + return true; +} + std::string CBlockFileInfo::ToString() const { + return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, DateTimeStrFormat("%Y-%m-%d", nTimeFirst).c_str(), DateTimeStrFormat("%Y-%m-%d", nTimeLast).c_str()); + } |