aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.test.include8
-rw-r--r--src/ecwrapper.cpp2
-rw-r--r--src/ecwrapper.h4
-rw-r--r--src/main.cpp23
-rw-r--r--src/main.h29
-rw-r--r--src/miner.cpp4
-rw-r--r--src/qt/optionsdialog.h5
-rw-r--r--src/rpcblockchain.cpp2
-rw-r--r--src/rpcmining.cpp36
-rw-r--r--src/rpcprotocol.h11
-rw-r--r--src/rpcserver.h2
-rw-r--r--src/test/miner_tests.cpp2
-rw-r--r--src/txmempool.cpp6
-rw-r--r--src/utilstrencodings.cpp4
14 files changed, 96 insertions, 42 deletions
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 340eb9f1a7..6a8d9e58a4 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -42,8 +42,8 @@ BITCOIN_TESTS =\
test/bloom_tests.cpp \
test/checkblock_tests.cpp \
test/Checkpoints_tests.cpp \
- test/compress_tests.cpp \
test/coins_tests.cpp \
+ test/compress_tests.cpp \
test/crypto_tests.cpp \
test/DoS_tests.cpp \
test/getarg_tests.cpp \
@@ -58,7 +58,9 @@ BITCOIN_TESTS =\
test/rpc_tests.cpp \
test/script_P2SH_tests.cpp \
test/script_tests.cpp \
+ test/scriptnum_tests.cpp \
test/serialize_tests.cpp \
+ test/sighash_tests.cpp \
test/sigopcount_tests.cpp \
test/skiplist_tests.cpp \
test/test_bitcoin.cpp \
@@ -66,9 +68,7 @@ BITCOIN_TESTS =\
test/transaction_tests.cpp \
test/uint256_tests.cpp \
test/univalue_tests.cpp \
- test/util_tests.cpp \
- test/scriptnum_tests.cpp \
- test/sighash_tests.cpp
+ test/util_tests.cpp
if ENABLE_WALLET
BITCOIN_TESTS += \
diff --git a/src/ecwrapper.cpp b/src/ecwrapper.cpp
index e5db670927..ebaa350264 100644
--- a/src/ecwrapper.cpp
+++ b/src/ecwrapper.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2014 The Bitcoin developers
-// Distributed under the MIT/X11 software license, see the accompanying
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "ecwrapper.h"
diff --git a/src/ecwrapper.h b/src/ecwrapper.h
index 072da4a942..e2d1e7edc4 100644
--- a/src/ecwrapper.h
+++ b/src/ecwrapper.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2014 The Bitcoin developers
-// Distributed under the MIT/X11 software license, see the accompanying
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_EC_WRAPPER_H
@@ -43,4 +43,4 @@ public:
static bool SanityCheck();
};
-#endif
+#endif // BITCOIN_EC_WRAPPER_H
diff --git a/src/main.cpp b/src/main.cpp
index 008a059103..37891f3b0d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -152,6 +152,8 @@ struct CMainSignals {
boost::signals2::signal<void (const uint256 &)> Inventory;
// Tells listeners to broadcast their data.
boost::signals2::signal<void ()> Broadcast;
+ // Notifies listeners of a block validation result
+ boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
} g_signals;
} // anon namespace
@@ -163,9 +165,11 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn));
+ g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
}
void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
+ g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn));
g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
@@ -175,6 +179,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
}
void UnregisterAllValidationInterfaces() {
+ g_signals.BlockChecked.disconnect_all_slots();
g_signals.Broadcast.disconnect_all_slots();
g_signals.Inventory.disconnect_all_slots();
g_signals.SetBestChain.disconnect_all_slots();
@@ -1864,7 +1869,9 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
{
CCoinsViewCache view(pcoinsTip);
CInv inv(MSG_BLOCK, pindexNew->GetBlockHash());
- if (!ConnectBlock(*pblock, state, pindexNew, view)) {
+ bool rv = ConnectBlock(*pblock, state, pindexNew, view);
+ g_signals.BlockChecked(*pblock, state);
+ if (!rv) {
if (state.IsInvalid())
InvalidBlockFound(pindexNew, state);
return error("ConnectTip() : ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
@@ -2504,7 +2511,7 @@ void CBlockIndex::BuildSkip()
pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
}
-bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp)
+bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp)
{
// Preliminary checks
bool checked = CheckBlock(*pblock, state);
@@ -2513,7 +2520,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
LOCK(cs_main);
MarkBlockAsReceived(pblock->GetHash());
if (!checked) {
- return error("ProcessBlock() : CheckBlock FAILED");
+ return error("%s : CheckBlock FAILED", __func__);
}
// Store to disk
@@ -2523,11 +2530,11 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId();
}
if (!ret)
- return error("ProcessBlock() : AcceptBlock FAILED");
+ return error("%s : AcceptBlock FAILED", __func__);
}
if (!ActivateBestChain(state, pblock))
- return error("ProcessBlock() : ActivateBestChain failed");
+ return error("%s : ActivateBestChain failed", __func__);
return true;
}
@@ -3136,7 +3143,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
// process in case the block isn't known yet
if (mapBlockIndex.count(hash) == 0) {
CValidationState state;
- if (ProcessBlock(state, NULL, &block, dbp))
+ if (ProcessNewBlock(state, NULL, &block, dbp))
nLoaded++;
if (state.IsError())
break;
@@ -3156,7 +3163,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(),
head.ToString());
CValidationState dummy;
- if (ProcessBlock(dummy, NULL, &block, &it->second))
+ if (ProcessNewBlock(dummy, NULL, &block, &it->second))
{
nLoaded++;
queue.push_back(block.GetHash());
@@ -3934,7 +3941,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->AddInventoryKnown(inv);
CValidationState state;
- ProcessBlock(state, pfrom, &block);
+ ProcessNewBlock(state, pfrom, &block);
int nDoS;
if (state.IsInvalid(nDoS)) {
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
diff --git a/src/main.h b/src/main.h
index 1941ca7059..1bb0919817 100644
--- a/src/main.h
+++ b/src/main.h
@@ -39,8 +39,15 @@
#include <boost/unordered_map.hpp>
class CBlockIndex;
+class CBlockTreeDB;
class CBloomFilter;
class CInv;
+class CScriptCheck;
+class CValidationInterface;
+class CValidationState;
+
+struct CBlockTemplate;
+struct CNodeStateStats;
/** The maximum allowed size for a serialized block, in bytes (network rule) */
static const unsigned int MAX_BLOCK_SIZE = 1000000;
@@ -128,15 +135,6 @@ extern CBlockIndex *pindexBestHeader;
// Minimum disk space required - used in CheckDiskSpace()
static const uint64_t nMinDiskSpace = 52428800;
-
-class CBlockTreeDB;
-class CScriptCheck;
-class CValidationState;
-class CValidationInterface;
-struct CNodeStateStats;
-
-struct CBlockTemplate;
-
/** Register a wallet to receive updates from core */
void RegisterValidationInterface(CValidationInterface* pwalletIn);
/** Unregister a wallet from core */
@@ -151,8 +149,16 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals);
/** Unregister a network node */
void UnregisterNodeSignals(CNodeSignals& nodeSignals);
-/** Process an incoming block */
-bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL);
+/** Process an incoming block. This only returns after the best known valid
+ block is made active. Note that it does not, however, guarantee that the
+ specific block passed to it has been checked for validity!
+ @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state iff pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface - this will have its BlockChecked method called whenever *any* block completes validation.
+ @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid.
+ @param[in] pblock The block we want to process.
+ @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location.
+ @return True if state.IsValid()
+*/
+bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL);
/** Check whether enough disk space is available for an incoming block */
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
/** Open a block file (blk?????.dat) */
@@ -651,6 +657,7 @@ protected:
virtual void UpdatedTransaction(const uint256 &hash) {};
virtual void Inventory(const uint256 &hash) {};
virtual void ResendWalletTransactions() {};
+ virtual void BlockChecked(const CBlock&, const CValidationState&) {};
friend void ::RegisterValidationInterface(CValidationInterface*);
friend void ::UnregisterValidationInterface(CValidationInterface*);
friend void ::UnregisterAllValidationInterfaces();
diff --git a/src/miner.cpp b/src/miner.cpp
index 0235de3ab3..b5bfa9c7be 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -428,8 +428,8 @@ bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
// Process this block the same as if we had received it from another node
CValidationState state;
- if (!ProcessBlock(state, NULL, pblock))
- return error("BitcoinMiner : ProcessBlock, block not accepted");
+ if (!ProcessNewBlock(state, NULL, pblock))
+ return error("BitcoinMiner : ProcessNewBlock, block not accepted");
return true;
}
diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h
index 39c53f4391..2abd92cae5 100644
--- a/src/qt/optionsdialog.h
+++ b/src/qt/optionsdialog.h
@@ -7,10 +7,13 @@
#include <QDialog>
-class QDataWidgetMapper;
class OptionsModel;
class QValidatedLineEdit;
+QT_BEGIN_NAMESPACE
+class QDataWidgetMapper;
+QT_END_NAMESPACE
+
namespace Ui {
class OptionsDialog;
}
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 78f5569895..a7cd63bd95 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -474,7 +474,7 @@ struct CompareBlocksByHeight
bool operator()(const CBlockIndex* a, const CBlockIndex* b) const
{
/* Make sure that unequal blocks with the same height do not compare
- equal. Use the pointers themselves to make a distinction. */
+ equal. Use the pointers themselves to make a distinction. */
if (a->nHeight != b->nHeight)
return (a->nHeight > b->nHeight);
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index 8af3c46348..0be4e06164 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -527,6 +527,24 @@ Value getblocktemplate(const Array& params, bool fHelp)
return result;
}
+class submitblock_StateCatcher : public CValidationInterface
+{
+public:
+ uint256 hash;
+ bool found;
+ CValidationState state;
+
+ submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {};
+
+protected:
+ virtual void BlockChecked(const CBlock& block, const CValidationState& stateIn) {
+ if (block.GetHash() != hash)
+ return;
+ found = true;
+ state = stateIn;
+ };
+};
+
Value submitblock(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
@@ -559,8 +577,22 @@ Value submitblock(const Array& params, bool fHelp)
}
CValidationState state;
- bool fAccepted = ProcessBlock(state, NULL, &pblock);
- if (!fAccepted)
+ submitblock_StateCatcher sc(pblock.GetHash());
+ RegisterValidationInterface(&sc);
+ bool fAccepted = ProcessNewBlock(state, NULL, &pblock);
+ UnregisterValidationInterface(&sc);
+ if (fAccepted)
+ {
+ if (!sc.found)
+ return "inconclusive";
+ state = sc.state;
+ }
+ if (state.IsError())
+ {
+ std::string strRejectReason = state.GetRejectReason();
+ throw JSONRPCError(RPC_VERIFY_ERROR, strRejectReason);
+ }
+ if (state.IsInvalid())
return "rejected"; // TODO: report validation state
return Value::null;
diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h
index a9adb58803..9117248506 100644
--- a/src/rpcprotocol.h
+++ b/src/rpcprotocol.h
@@ -49,9 +49,14 @@ enum RPCErrorCode
RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter
RPC_DATABASE_ERROR = -20, // Database error
RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format
- RPC_TRANSACTION_ERROR = -25, // General error during transaction submission
- RPC_TRANSACTION_REJECTED = -26, // Transaction was rejected by network rules
- RPC_TRANSACTION_ALREADY_IN_CHAIN= -27, // Transaction already in chain
+ RPC_VERIFY_ERROR = -25, // General error during transaction or block submission
+ RPC_VERIFY_REJECTED = -26, // Transaction or block was rejected by network rules
+ RPC_VERIFY_ALREADY_IN_CHAIN = -27, // Transaction already in chain
+
+ // Aliases for backward compatibility
+ RPC_TRANSACTION_ERROR = RPC_VERIFY_ERROR,
+ RPC_TRANSACTION_REJECTED = RPC_VERIFY_REJECTED,
+ RPC_TRANSACTION_ALREADY_IN_CHAIN= RPC_VERIFY_ALREADY_IN_CHAIN,
// P2P client errors
RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected
diff --git a/src/rpcserver.h b/src/rpcserver.h
index cc444cef1f..dc46637399 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -7,8 +7,8 @@
#define _BITCOINRPC_SERVER_H_
#include "amount.h"
-#include "uint256.h"
#include "rpcprotocol.h"
+#include "uint256.h"
#include <list>
#include <map>
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 93b7fe189a..032ae983ce 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -79,7 +79,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
pblock->nNonce = blockinfo[i].nonce;
CValidationState state;
- BOOST_CHECK(ProcessBlock(state, NULL, pblock));
+ BOOST_CHECK(ProcessNewBlock(state, NULL, pblock));
BOOST_CHECK(state.IsValid());
pblock->hashPrevBlock = pblock->GetHash();
}
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index d3d9cb8a01..b5070d5104 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -332,7 +332,7 @@ public:
size_t numEntries;
filein >> numEntries;
if (numEntries <= 0 || numEntries > 10000)
- throw runtime_error("Corrupt estimates file. Must have between 1 and 10k entires.");
+ throw runtime_error("Corrupt estimates file. Must have between 1 and 10k entires.");
std::vector<CBlockAverage> fileHistory;
@@ -343,8 +343,8 @@ public:
fileHistory.push_back(entry);
}
- //Now that we've processed the entire fee estimate data file and not
- //thrown any errors, we can copy it to our history
+ // Now that we've processed the entire fee estimate data file and not
+ // thrown any errors, we can copy it to our history
nBestSeenHeight = nFileBestSeenHeight;
history = fileHistory;
assert(history.size() > 0);
diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp
index 81e156f43f..15094e5999 100644
--- a/src/utilstrencodings.cpp
+++ b/src/utilstrencodings.cpp
@@ -7,10 +7,10 @@
#include "tinyformat.h"
-#include <errno.h>
-#include <limits>
#include <cstdlib>
#include <cstring>
+#include <errno.h>
+#include <limits>
using namespace std;