aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2013-03-15 13:10:34 -0400
committerGavin Andresen <gavinandresen@gmail.com>2013-03-17 21:52:47 -0400
commit8c222dca4f961ad13ec64d690134a40d09b20813 (patch)
treeb079ced3c000ecf0ad453febf18642f989e829ad
parent1a9ee5da327d8079a297ad292a1c16745b75df91 (diff)
CheckBlock rule until 15-May for 10,000 BDB lock compatibility
-rw-r--r--src/main.cpp19
-rw-r--r--src/test/checkblock_tests.cpp66
2 files changed, 85 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 9a06dbf13e..51ada0a0bb 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2056,6 +2056,25 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
if (vtx.empty() || vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return state.DoS(100, error("CheckBlock() : size limits failed"));
+ // Special short-term limits to avoid 10,000 BDB lock limit:
+ if (GetBlockTime() > 1363039171 && // 11 March 2013, timestamp of block before the big fork
+ GetBlockTime() < 1368576000) // 15 May 2013 00:00:00
+ {
+ // Rule is: #unique txids referenced <= 4,500
+ // ... to prevent 10,000 BDB lock exhaustion on old clients
+ set<uint256> setTxIn;
+ for (size_t i = 0; i < vtx.size(); i++)
+ {
+ setTxIn.insert(vtx[i].GetHash());
+ if (i == 0) continue; // skip coinbase txin
+ BOOST_FOREACH(const CTxIn& txin, vtx[i].vin)
+ setTxIn.insert(txin.prevout.hash);
+ }
+ size_t nTxids = setTxIn.size();
+ if (nTxids > 4500)
+ return error("CheckBlock() : 15 May maxlocks violation");
+ }
+
// Check proof of work matches claimed amount
if (fCheckPOW && !CheckProofOfWork(GetHash(), nBits))
return state.DoS(50, error("CheckBlock() : proof of work failed"));
diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp
new file mode 100644
index 0000000000..e167defb27
--- /dev/null
+++ b/src/test/checkblock_tests.cpp
@@ -0,0 +1,66 @@
+//
+// Unit tests for block.CheckBlock()
+//
+#include <algorithm>
+
+#include <boost/assign/list_of.hpp> // for 'map_list_of()'
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/foreach.hpp>
+
+#include "main.h"
+#include "wallet.h"
+#include "net.h"
+#include "util.h"
+
+BOOST_AUTO_TEST_SUITE(CheckBlock_tests)
+
+bool
+read_block(const std::string& filename, CBlock& block)
+{
+ namespace fs = boost::filesystem;
+ fs::path testFile = fs::current_path() / "test" / "data" / filename;
+#ifdef TEST_DATA_DIR
+ if (!fs::exists(testFile))
+ {
+ testFile = fs::path(BOOST_PP_STRINGIZE(TEST_DATA_DIR)) / filename;
+ }
+#endif
+ FILE* fp = fopen(testFile.string().c_str(), "rb");
+ if (!fp) return false;
+
+ fseek(fp, 8, SEEK_SET); // skip msgheader/size
+
+ CAutoFile filein = CAutoFile(fp, SER_DISK, CLIENT_VERSION);
+ if (!filein) return false;
+
+ filein >> block;
+
+ return true;
+}
+
+BOOST_AUTO_TEST_CASE(May15)
+{
+ // Putting a 1MB binary file in the git repository is not a great
+ // idea, so this test is only run if you manually download
+ // test/data/Mar12Fork.dat from
+ // http://sourceforge.net/projects/bitcoin/files/Bitcoin/blockchain/Mar12Fork.dat/download
+ unsigned int tMay15 = 1368576000;
+ SetMockTime(tMay15); // Test as if it was right at May 15
+
+ CBlock forkingBlock;
+ if (read_block("Mar12Fork.dat", forkingBlock))
+ {
+ CValidationState state;
+ BOOST_CHECK(!forkingBlock.CheckBlock(state, true, true));
+ BOOST_CHECK(!forkingBlock.CheckBlock(state, false, false));
+
+ // After May 15'th, big blocks are OK:
+ forkingBlock.nTime = tMay15; // Invalidates PoW
+ BOOST_CHECK(forkingBlock.CheckBlock(state, false, false));
+ }
+
+ SetMockTime(0);
+}
+
+BOOST_AUTO_TEST_SUITE_END()