Compare commits

...

78 Commits

Author SHA1 Message Date
Wladimir J. van der Laan
9d11aba4c4 Merge #5765: Implement BIP66 (0.8) 2015-02-17 10:04:23 +01:00
Pieter Wuille
6690ef7fea Backport of some of BIP66's tests 2015-02-06 11:17:29 -08:00
Pieter Wuille
534e6dac47 Raise version of created blocks, and enforce DERSIG in mempool 2015-02-06 11:17:29 -08:00
Pieter Wuille
da7ba593d7 Implement BIP 66 validation rules and switchover logic 2015-02-06 11:17:29 -08:00
Wladimir J. van der Laan
f19dded6e4 Improve robustness of DER recoding code
Add some defensive programming on top of #5634.

This copies the respective OpenSSL code in ECDSA_verify in
OpenSSL pre-1.0.1k (e.g. https://github.com/openssl/openssl/blob/OpenSSL_1_0_1j/crypto/ecdsa/ecs_vrf.c#L89)
more closely.

As reported by @sergiodemianlerner.

Github-Pull: #5640
Rebased-From: c6b7b29f23
2015-01-12 11:05:04 +01:00
Cory Fields
91e1332011 fail immediately on an empty signature
Github-Pull: #5634
Rebased-From: 8dccba6a45
2015-01-10 09:14:17 +01:00
Cory Fields
f4134ee301 consensus: guard against openssl's new strict DER checks
New versions of OpenSSL will reject non-canonical DER signatures. However,
it'll happily decode them. Decode then re-encode before verification in order
to ensure that it is properly consumed.

Github-Pull: #5634
Rebased-From: 488ed32f2a
2015-01-10 09:13:53 +01:00
Wladimir J. van der Laan
03a7d67387 Release notes for 0.8.6 2013-12-05 13:11:26 +01:00
theuni
d3381e71a1 leveldb: Use native Darwin memory barriers 2013-12-05 13:10:24 +01:00
Warren Togami
77f7bcb352 LevelDB: use PosixWriteableFile only on MacOS X
mmap is proven on the other platforms, we are not changing it at
the last moment before release.
2013-12-05 13:10:24 +01:00
Patrick Strateman
5f553f8422 dont use mmap in leveldb, this is a marginal performance hit
fail on short writes

Ensure new files referred to by the manifest are in the filesystem.
2013-12-05 13:10:24 +01:00
Wladimir J. van der Laan
1eb11e32e8 Prevent empty transactions from being added to vtxPrev
CWalletTx::AddSupportingTransactions() was adding empty transaction
to vtxPrev in some cases. Skip over these.

Part one of the solution to #3190. This prevents invalid vtxPrev from
entering the wallet, but not current ones being transmitted.
2013-12-05 11:05:14 +01:00
Wladimir J. van der Laan
ec93d0aa43 Refuse to retransmit transactions without vins
Versions of bitcoin before 0.8.6 have a bug that inserted
empty transactions into the vtxPrev in the wallet, which will cause the node to be
banned when retransmitted, hence add a check for !tx.vin.empty()
before RelayTransaction.
2013-12-05 11:05:14 +01:00
Wladimir J. van der Laan
8c3ba8be01 qt: use deleteLater to remove send entries
Use deleteLater() instead of delete, as it is not allowed
to delete widgets directly in an event handler.
Should solve the MacOSX random crashes on send with coincontrol.

Rebased-From: 6c98cca9e4
2013-12-05 09:16:48 +01:00
Wladimir J. van der Laan
a0a5b20156 release notes: add warning about 32-bit systems 2013-12-05 09:16:48 +01:00
Gavin Andresen
22db46cf11 Fix typo: make default maxblocksize 350k (not 300) 2013-12-05 09:16:48 +01:00
Philip Kaufmann
bfb0856986 Bitcoin-Qt: Fix display of window when bitcoin: URI is opened
WalletView:
- add new signal showNormalIfMinimized()
- emit the new signal in handleURI() to fix a bug, preventing the main
  window to show up when using bitcoin: URIs

Upstream: dbc0a6aba2
2013-12-05 09:15:41 +01:00
Timothy Stranex
3b8868dca4 Fix typo in a comment: it's base58, not base48. 2013-12-05 09:15:41 +01:00
Robert Backhaus
df0f6d020a Don't attempt to resize vector to negative size. 2013-12-05 09:15:41 +01:00
Daniel Larimer
27e35bf840 fix memory leak in CKey::SetCompactSignature() 2013-12-05 09:15:41 +01:00
Daniel Larimer
6f21e7317e Fix memory leak on exception in Key::SignCompact 2013-12-05 09:15:41 +01:00
Micha
daf9e4627f Made the build/release process completable verbatim as listed in
release-process.md

Conflicts:
	doc/release-process.md
2013-12-05 09:15:40 +01:00
Wladimir J. van der Laan
138705a173 Create parent directories if needed in GetDataDir
One-line change. Fixes #2752.
2013-12-05 09:15:40 +01:00
Warren Togami
96896a0ece Add wtogami to gitian download scripts. 2013-12-05 09:15:40 +01:00
Cozz Lovan
901ae4bffd fix comment about dust logic
Conflicts:
	src/core.h
2013-12-05 09:15:40 +01:00
Michael Ford
c9c67b00df Update HomeBrew osx makefile patch to account for recent changes to makefile 2013-12-05 09:15:40 +01:00
Gregory Maxwell
d3fe7c44f7 Make the rand tests determinstic. (fixes #2714)
This avoids spurious errors with the old tests but still tests
 enough that if the rng is replaced with a totally broken one
 it should still fail.
2013-12-05 09:15:40 +01:00
Mark Friedenbach
98289bbe25 Fix typo in README.md 2013-12-05 09:15:40 +01:00
Han Lin Yap
9f7fc8b332 fix typo in README.md 2013-12-05 09:15:40 +01:00
Philip Kaufmann
1b350f25a6 fix invalid conversion error with MinGW 4.8.1 in net.cpp
- fixes src\net.cpp:1601: Error:invalid conversion from 'void*' to
  'const char*' [-fpermissive] in a setsockopt() call on Win32 that was
  found by using MinGW 4.8.1 compiler suite
2013-12-05 09:15:39 +01:00
Luke Dashjr
89c2ea0891 Bugfix: Move boost/version include from db.cpp to walletdb.cpp where BOOST_VERSION is used 2013-12-05 09:15:39 +01:00
Roman Mindalev
df238b1975 Add missing 0x prefix in chainparams.cpp
Conflicts:
	src/chainparams.cpp
2013-12-05 09:15:39 +01:00
Robert Backhaus
187f8a5675 Explictly cast calculation to int, to allow std::max to work. 2013-12-05 09:15:39 +01:00
Gavin Andresen
9612e4c0d9 Lower maximum size for free transaction creation
Changes the maximum size of a free transaction that will be created
from 10,000 bytes to 1,000 bytes.

The idea behind this change is to make the free transaction area
available to a greater number of people; with the default 27K-per-block,
just three very-large very-high-priority transactions could fill the space.
2013-11-28 07:59:54 +01:00
Gavin Andresen
1ca8a75cb4 Remove CENT-output free transaction rule when relaying
Remove the (relay/mempool) rule that all outputs of free transactions
must be greater than 0.01 XBT. Dust spam is now taken care of by making
dusty outputs non-standard.
2013-11-28 07:59:54 +01:00
Gavin Andresen
5c029630f9 Increase default -blockmaxsize/prioritysize to 300K/30K 2013-11-28 07:59:53 +01:00
Mike Hearn
7120d76dc6 Store and use a sanitized subVer
Rebased-from: a946aa8d3e
2013-11-28 11:03:33 +10:00
Mike Hearn
1c53d0a4fb Add some additional logging to give extra network insight. 2013-11-28 11:03:33 +10:00
Philip Kaufmann
3779de9d89 special case DoS value == 0 in ProcessMessage()
- prevents unneeded log messages, which could make users think something
  bad was happening

Squashed: style-police code cleanup
2013-11-28 11:03:33 +10:00
Gavin Andresen
56ce843314 Refactor: pull alert string sanitization into util
Rebased-from: 17faf56262
2013-11-28 11:03:33 +10:00
Warren Togami
e564297156 Silence useless warning in src/json/json_spirit_writer_template.h to make important warnings easier to see.
warning: typedef ‘Char_type’ locally defined but not used [-Wunused-local-typedefs]
2013-11-28 11:03:33 +10:00
Wladimir J. van der Laan
83efc9104f Squashed 'src/leveldb/' changes from be1b0ff..be91006
936b461 Merge upstream LevelDB 1.13.
748539c LevelDB 1.13

git-subtree-dir: src/leveldb
git-subtree-split: be9100673b05cec1662a54d0b7a59e4317fdda86
2013-11-28 11:03:32 +10:00
Wladimir J. van der Laan
e4be09cfae Bump version numbers for 0.8.6 release 2013-11-26 14:00:48 +01:00
Cory Fields
068996daa5 osx: fix bitcoin-qt startup crash when clicking dock icon
Crash probably introduced by 4d17a1b0.
Inialize the window to NULL and verify it before use.

Rebased-By: Wladimir J. van der Laan <laanwj@gmail.com>
2013-11-26 14:00:48 +01:00
Pieter Wuille
99f73bd2fd Fix build date for from-tarball builds 2013-11-26 14:00:48 +01:00
Philip Kaufmann
f607729b26 exclude CreatePidFile() function on WIN32 as it is unused 2013-11-26 14:00:48 +01:00
phelixbtc
e88eb41b6c Porting MinGW multithreading bugfix to makefile.mingw
Original fix:
https://github.com/bitcoin/bitcoin/commit
/8864019f6d88b13d3442843d9e6ebeb8dd938831
2013-11-26 14:00:48 +01:00
David Hill
0119e0c592 Hurricane Electric uses block 2001:470::, not 2011:470:: 2013-11-26 14:00:48 +01:00
Gregory Maxwell
f46f128b9a More fixes for blockchain corruption on OSX.
As we'd previously learned, OSX's fsync is a data eating lie.

Since 0.8.4 we're still getting some reports of disk corruption on
 OSX but now all of it looks like the block files have gotten out of
 sync with the database. It turns out that we were still using fsync()
 on the block files, so this isn't surprising.
2013-11-26 14:00:47 +01:00
Philip Kaufmann
05ea79052c make -logtimestamps default on and rework help-message
Rebased-By: Wladimir J. van der Laan <laanwj@gmail.com>
Rebased-From: 959e62f
2013-11-26 14:00:47 +01:00
Jeff Garzik
c4892eb4b3 Log reason for non-standard transaction rejection
Conflicts:
	src/main.cpp

Rebased-from: cb3076a3da
2013-11-26 14:00:47 +01:00
Philip Kaufmann
633d95ec22 log start and end of Shutdown()
- could be helpful when debugging shutdown related problems

Rebased-by:   Warren Togami <wtogami@gmail.com>
Rebased-from: ced3c24816
2013-11-26 14:00:47 +01:00
theuni
3e89dbb132 Fix uninitialized variable added in 5c55bf5
After discussing with BlueMatt, this appears to be harmless in its
current state since it's always set before it's used. Initialize it
anyway for readability and future safety.

Rebased-By: Wladimir J. van der Laan <laanwj@gmail.com>
Rebased-From: 106f133de6
2013-11-26 10:32:16 +01:00
Matt Corallo
5c55bf5af0 Fix comparison tool by asking for blocks more aggressively
Rebased-from: b33b9a6fef
2013-11-26 10:15:57 +01:00
Patrick Strateman
7084756f4f process received messages one at a time without sleeping between messages 2013-11-26 10:15:49 +01:00
Gavin Andresen
ef14a26b12 Bump version numbers for 0.8.5 release 2013-09-12 13:35:18 +10:00
Pieter Wuille
27fefeac71 Fix out-of-bounds check 2013-09-12 12:41:17 +10:00
Gregory Maxwell
f0a1d87b00 Longer term workaround for chainstate corruption from negative versions.
This also makes negative transaction versions non-standard.

This avoids an issue triggered in block 256818 where transactions with
negative version numbers were incorrectly serialized into the UTXO set.

On restart nodes detect the inconsistency and refuse to start so long as
a block with these transactions is inside the self-consistency check
window, logging "coin database inconsistencies found". The software
recommends reindexing, but reindexing does not correct the problem.

This should be fixed by changing the chainstate serialization, but
working around it seems harmless for now because the version is not
used by any network rule currently.

A patch free workaround is to start with -checklevel=2 which skips
the consistency checks, but the IsStandard change is important for
miners in order to protect unpatched nodes.
2013-09-10 10:03:06 +10:00
Gregory Maxwell
839c7d1fa8 Update the bloom state on the real object, not the temporary one.
This resulted in just passing all transactions to filtered wallets
which worked surprisingly well, except where it didn't.
2013-08-21 11:07:28 +10:00
Pieter Wuille
d7fdc5fac3 Fix non-standard disconnected transactions causing mempool orphans
Conflicts:
	src/main.cpp
2013-08-21 09:13:49 +10:00
theuni
5e18c6ccbc fixed: don't use thread::sleep_for where it's known to be broken
Fixes #2690.
2013-08-21 08:49:00 +10:00
theuni
708c75c0ee fixed: include boost header as necessary
Without this include, sometimes BOOST_VERSION was defined and sometimes
it was not, depending on which includes came before it. The result was a
random mix of sleep or sleep_for for boost versions >= 1.50.
2013-08-21 08:49:00 +10:00
Gregory Maxwell
ac7c960067 Performance optimization for bloom filters.
This reduces a peer's ability to attack network resources by
 using a full bloom filter, but without reducing the usability
 of bloom filters.  It sets a default match everything filter
 for peers and it generalizes a prior optimization to
 cover more cases.
2013-08-21 08:49:00 +10:00
Pieter Wuille
980b1c3571 Merge commit '6519339fe849bdbbff047d9eef8ab6c5fbb3e2a4' 2013-08-21 00:43:20 +02:00
Pieter Wuille
6519339fe8 Squashed 'src/leveldb/' changes from a02ddf9..be1b0ff
be1b0ff On Mac OS X fsync does not guarantee write to disk. Use fcntl F_FULLFSYNC instead.

git-subtree-dir: src/leveldb
git-subtree-split: be1b0ff1fcd6ad820a7fd111ac671fb51cc68001
2013-08-21 00:43:09 +02:00
Pieter Wuille
e6552eed63 Merge commit 'cb1e39f0a35cc2b36fb748c26f69cd27e0ed5332' as 'src/leveldb' 2013-08-20 14:17:45 +02:00
Pieter Wuille
cb1e39f0a3 Squashed 'src/leveldb/' content from commit a02ddf9
git-subtree-dir: src/leveldb
git-subtree-split: a02ddf9b14d145e88185ee209ab8b01d8826663a
2013-08-20 14:17:45 +02:00
Pieter Wuille
5c739c574f Remove inline LevelDB to prepare for git-subtree version 2013-08-20 14:03:29 +02:00
Gavin Andresen
20b611770f Checkpoint at block 250,000 2013-08-20 17:36:50 +10:00
Gavin Andresen
21696c12f3 Simplify storage of orphan transactions
Orphan transactions were stored as a CDataStream pointer;
this changes the mapOrphanTransactions data structures to
store orphans as a CTransaction.

This also fixes CVE-2013-4627 by always re-serializing
transactions before relaying them.
2013-08-20 14:52:38 +10:00
Gavin Andresen
08dd92060b Revert "Truncate oversize 'tx' messages before relaying/storing."
This reverts commit 7cc960f8f5.
2013-08-20 14:46:01 +10:00
Gavin Andresen
cdb3441b5c Make RPC password resistant to timing attacks
Fixes issue#2838; this is a tweaked version of pull#2845 that
should not leak the length of the password and is more generic,
in case we run into other situations where we need
timing-attack-resistant comparisons.
2013-08-20 12:19:40 +10:00
Matt Corallo
38863afbcc Fix multi-block reorg transaction resurrection 2013-08-20 12:18:50 +10:00
Gavin Andresen
6f315b4016 Fix Gnome bitcoin: URI handler 2013-08-20 12:18:39 +10:00
Gavin Andresen
6929f2a45f Bump version numbers to prep for 0.8.4 release 2013-08-20 11:20:04 +10:00
Gavin Andresen
40809aed65 Bump version numbers for 0.8.3 release 2013-06-25 10:27:24 -04:00
Pieter Wuille
65c20dbf55 Dump addresses every 15 minutes instead of 10 seconds 2013-06-25 10:21:02 -04:00
Peter Todd
7cc960f8f5 Truncate oversize 'tx' messages before relaying/storing.
Fixes a memory exhaustion attack on low-memory peers.
2013-06-25 09:59:31 -04:00
78 changed files with 1519 additions and 421 deletions

View File

@@ -15,7 +15,7 @@ out collectively by the network. Bitcoin is also the name of the open source
software which enables the use of this currency.
For more information, as well as an immediately useable, binary version of
the Bitcoin client sofware, see http://www.bitcoin.org.
the Bitcoin client software, see http://www.bitcoin.org.
License
-------
@@ -38,7 +38,7 @@ submitter will be asked to start a discussion (if they haven't already) on the
The patch will be accepted if there is broad consensus that it is a good thing.
Developers should expect to rework and resubmit patches if the code doesn't
match the project's coding conventions (see `doc/coding.txt`) or are
match the project's coding conventions (see `doc/coding.md`) or are
controversial.
The `master` branch is regularly built and tested, but is not guaranteed to be

View File

@@ -1,7 +1,7 @@
TEMPLATE = app
TARGET = bitcoin-qt
macx:TARGET = "Bitcoin-Qt"
VERSION = 0.8.2
VERSION = 0.8.6
INCLUDEPATH += src src/json src/qt
QT += network
DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE

View File

@@ -4,7 +4,7 @@ Name=Bitcoin
Comment=Bitcoin P2P Cryptocurrency
Comment[fr]=Bitcoin, monnaie virtuelle cryptographique pair à pair
Comment[tr]=Bitcoin, eşten eşe kriptografik sanal para birimi
Exec=/usr/bin/bitcoin-qt
Exec=/usr/bin/bitcoin-qt %u
Terminal=false
Type=Application
Icon=/usr/share/pixmaps/bitcoin128.png

View File

@@ -35,4 +35,8 @@ signers:
weight: 40
name: "Wladimir J. van der Laan"
key: laanwj
AEC1884398647C47413C1C3FB1179EB7347DC10D:
weight: 40
name: "Warren Togami"
key: wtogami
minimum_weight: 120

View File

@@ -35,4 +35,8 @@ signers:
weight: 40
name: "Wladimir J. van der Laan"
key: laanwj
AEC1884398647C47413C1C3FB1179EB7347DC10D:
weight: 40
name: "Warren Togami"
key: wtogami
minimum_weight: 120

View File

@@ -0,0 +1,131 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.13 (GNU/Linux)
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
=icdI
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -1,5 +1,5 @@
diff --git a/src/makefile.osx b/src/makefile.osx
index 8b7c559..8a0560c 100644
index bef0ef3..07ef8d3 100644
--- a/src/makefile.osx
+++ b/src/makefile.osx
@@ -7,17 +7,21 @@
@@ -28,7 +28,7 @@ index 8b7c559..8a0560c 100644
USE_UPNP:=1
USE_IPV6:=1
@@ -31,13 +35,13 @@ ifdef STATIC
@@ -31,14 +35,14 @@ ifdef STATIC
TESTLIBS += \
$(DEPSDIR)/lib/libboost_unit_test_framework-mt.a
LIBS += \
@@ -38,6 +38,7 @@ index 8b7c559..8a0560c 100644
$(DEPSDIR)/lib/libboost_filesystem-mt.a \
$(DEPSDIR)/lib/libboost_program_options-mt.a \
$(DEPSDIR)/lib/libboost_thread-mt.a \
$(DEPSDIR)/lib/libboost_chrono-mt.a \
- $(DEPSDIR)/lib/libssl.a \
- $(DEPSDIR)/lib/libcrypto.a \
+ $(OPENSSLDIR)/lib/libssl.a \

View File

@@ -18,7 +18,7 @@ WORKINGDIR="/tmp/bitcoin"
TMPFILE="hashes.tmp"
#this URL is used if a version number is not specified as an argument to the script
SIGNATUREFILE="http://downloads.sourceforge.net/project/bitcoin/Bitcoin/bitcoin-0.8.2/SHA256SUMS.asc"
SIGNATUREFILE="http://downloads.sourceforge.net/project/bitcoin/Bitcoin/bitcoin-0.8.6/SHA256SUMS.asc"
SIGNATUREFILENAME="SHA256SUMS.asc"
RCSUBDIR="test/"

118
db/autocompact_test.cc Normal file
View File

@@ -0,0 +1,118 @@
// Copyright (c) 2013 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include "leveldb/db.h"
#include "db/db_impl.h"
#include "leveldb/cache.h"
#include "util/testharness.h"
#include "util/testutil.h"
namespace leveldb {
class AutoCompactTest {
public:
std::string dbname_;
Cache* tiny_cache_;
Options options_;
DB* db_;
AutoCompactTest() {
dbname_ = test::TmpDir() + "/autocompact_test";
tiny_cache_ = NewLRUCache(100);
options_.block_cache = tiny_cache_;
DestroyDB(dbname_, options_);
options_.create_if_missing = true;
options_.compression = kNoCompression;
ASSERT_OK(DB::Open(options_, dbname_, &db_));
}
~AutoCompactTest() {
delete db_;
DestroyDB(dbname_, Options());
delete tiny_cache_;
}
std::string Key(int i) {
char buf[100];
snprintf(buf, sizeof(buf), "key%06d", i);
return std::string(buf);
}
uint64_t Size(const Slice& start, const Slice& limit) {
Range r(start, limit);
uint64_t size;
db_->GetApproximateSizes(&r, 1, &size);
return size;
}
void DoReads(int n);
};
static const int kValueSize = 200 * 1024;
static const int kTotalSize = 100 * 1024 * 1024;
static const int kCount = kTotalSize / kValueSize;
// Read through the first n keys repeatedly and check that they get
// compacted (verified by checking the size of the key space).
void AutoCompactTest::DoReads(int n) {
std::string value(kValueSize, 'x');
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
// Fill database
for (int i = 0; i < kCount; i++) {
ASSERT_OK(db_->Put(WriteOptions(), Key(i), value));
}
ASSERT_OK(dbi->TEST_CompactMemTable());
// Delete everything
for (int i = 0; i < kCount; i++) {
ASSERT_OK(db_->Delete(WriteOptions(), Key(i)));
}
ASSERT_OK(dbi->TEST_CompactMemTable());
// Get initial measurement of the space we will be reading.
const int64_t initial_size = Size(Key(0), Key(n));
const int64_t initial_other_size = Size(Key(n), Key(kCount));
// Read until size drops significantly.
std::string limit_key = Key(n);
for (int read = 0; true; read++) {
ASSERT_LT(read, 100) << "Taking too long to compact";
Iterator* iter = db_->NewIterator(ReadOptions());
for (iter->SeekToFirst();
iter->Valid() && iter->key().ToString() < limit_key;
iter->Next()) {
// Drop data
}
delete iter;
// Wait a little bit to allow any triggered compactions to complete.
Env::Default()->SleepForMicroseconds(1000000);
uint64_t size = Size(Key(0), Key(n));
fprintf(stderr, "iter %3d => %7.3f MB [other %7.3f MB]\n",
read+1, size/1048576.0, Size(Key(n), Key(kCount))/1048576.0);
if (size <= initial_size/10) {
break;
}
}
// Verify that the size of the key space not touched by the reads
// is pretty much unchanged.
const int64_t final_other_size = Size(Key(n), Key(kCount));
ASSERT_LE(final_other_size, initial_other_size + 1048576);
ASSERT_GE(final_other_size, initial_other_size/5 - 1048576);
}
TEST(AutoCompactTest, ReadAll) {
DoReads(kCount);
}
TEST(AutoCompactTest, ReadHalf) {
DoReads(kCount/2);
}
} // namespace leveldb
int main(int argc, char** argv) {
return leveldb::test::RunAllTests();
}

View File

@@ -34,7 +34,7 @@ PROJECT_NAME = Bitcoin
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 0.5.0
PROJECT_NUMBER = 0.8.6
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer

View File

@@ -1,4 +1,4 @@
Bitcoin 0.8.2 BETA
Bitcoin 0.8.6 BETA
====================
Copyright (c) 2009-2013 Bitcoin Developers
@@ -43,4 +43,4 @@ Other Pages
- [Release Notes](release-notes.md)
- [Multiwallet Qt Development](multiwallet-qt.md)
- [Unit Tests](unit-tests.md)
- [Translation Process](translation_process.md)
- [Translation Process](translation_process.md)

View File

@@ -1,4 +1,4 @@
Bitcoin 0.8.2 BETA
Bitcoin 0.8.5 BETA
Copyright (c) 2009-2013 Bitcoin Developers
Distributed under the MIT/X11 software license, see the accompanying

View File

@@ -1,80 +1,43 @@
(note: this is a temporary file, to be added-to by anybody, and deleted at
release time)
Fee Policy changes
------------------
0.8.6 changes
=============
The default fee for low-priority transactions is lowered from 0.0005 BTC
(for each 1,000 bytes in the transaction; an average transaction is
about 500 bytes) to 0.0001 BTC.
- Default block size increase for miners
(see https://gist.github.com/gavinandresen/7670433#086-accept-into-block)
Payments (transaction outputs) of 0.543 times the minimum relay fee
(0.00005430 BTC) are now considered 'non-standard', because storing them
costs the network more than they are worth and spending them will usually
cost their owner more in transaction fees than they are worth.
- Remove the all-outputs-must-be-greater-than-CENT-to-qualify-as-free rule for relaying
(see https://gist.github.com/gavinandresen/7670433#086-relaying)
Non-standard transactions are not relayed across the network, are not included
in blocks by most miners, and will not show up in your wallet until they are
included in a block.
- Lower maximum size for free transaction creation
(see https://gist.github.com/gavinandresen/7670433#086-wallet)
The default fee policy can be overridden using the -mintxfee and -minrelaytxfee
command-line options, but note that we intend to replace the hard-coded fees
with code that automatically calculates and suggests appropriate fees in the
0.9 release and note that if you set a fee policy significantly different from
the rest of the network your transactions may never confirm.
- OSX block chain database corruption fixes
- Update leveldb to 1.13
- Use fcntl with `F_FULLSYNC` instead of fsync on OSX
- Use native Darwin memory barriers
- Replace use of mmap in leveldb for improved reliability (only on OSX)
Bitcoin-Qt changes
------------------
- Fix nodes forwarding transactions with empty vins and getting banned
- New icon and splash screen
- Improve reporting of synchronization process
- Remove hardcoded fee recommendations
- Improve metadata of executable on MacOSX and Windows
- Move export button to individual tabs instead of toolbar
- Add "send coins" command to context menu in address book
- Add "copy txid" command to copy transaction IDs from transaction overview
- Save & restore window size and position when showing & hiding window
- New translations: Arabic (ar), Bosnian (bs), Catalan (ca), Welsh (cy), Esperanto (eo), Interlingua (la), Latvian (lv) and many improvements to current translations
- Network code performance and robustness improvements
MacOSX:
- Additional debug.log logging for diagnosis of network problems, log timestamps by default
- OSX support for click-to-pay (bitcoin:) links
- Fix GUI disappearing problem on MacOSX (issue #1522)
- Fix Bitcoin-Qt startup crash when clicking dock icon on OSX
Linux/Unix:
- Fix memory leaks in CKey::SetCompactSignature() and Key::SignCompact()
- Copy addresses to middle-mouse-button clipboard
- Fix rare GUI crash on send
- Various small GUI, documentation and build fixes
Command-line options
--------------------
Warning
--------
* `-walletnotify` will call a command on receiving transactions that affect the wallet.
* `-alertnotify` will call a command on receiving an alert from the network.
* `-par` now takes a negative number, to leave a certain amount of cores free.
JSON-RPC API changes
--------------------
* `listunspent` now lists account and address infromation.
* `getinfo` now also returns the time adjustment estimated from your peers.
* `getpeerinfo` now returns bytessent, bytesrecv and syncnode.
* `gettxoutsetinfo` returns statistics about the unspent transaction output database.
* `gettxout` returns information about a specific unspent transaction output.
Networking changes
------------------
* Significant changes to the networking code, reducing latency and memory consumption.
* Avoid initial block download stalling.
* Remove IRC seeding support.
* Performance tweaks.
* Added testnet DNS seeds.
Wallet compatibility/rescuing
-----------------------------
* Cases where wallets cannot be opened in another version/installation should be reduced.
* `-salvagewallet` now works for encrypted wallets.
- There have been frequent reports of users running out of virtual memory on 32-bit systems
during the initial sync.
Hence it is recommended to use a 64-bit executable if possible.
A 64-bit executable for Windows is planned for 0.9.

View File

@@ -31,7 +31,7 @@ Release Process
export SIGNER=(your gitian key, ie bluematt, sipa, etc)
export VERSION=0.8.0
cd ./gitian-builder
pushd ./gitian-builder
Fetch and build inputs: (first time, or when dependency versions change)
@@ -58,13 +58,14 @@ Release Process
./bin/gsign --signer $SIGNER --release ${VERSION} --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian.yml
pushd build/out
zip -r bitcoin-${VERSION}-linux-gitian.zip *
mv bitcoin-${VERSION}-linux-gitian.zip ../../
mv bitcoin-${VERSION}-linux-gitian.zip ../../../
popd
./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml
./bin/gsign --signer $SIGNER --release ${VERSION}-win32 --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml
pushd build/out
zip -r bitcoin-${VERSION}-win32-gitian.zip *
mv bitcoin-${VERSION}-win32-gitian.zip ../../
mv bitcoin-${VERSION}-win32-gitian.zip ../../../
popd
popd
Build output expected:
@@ -161,4 +162,4 @@ From a directory containing bitcoin source, gitian.sigs and gitian zips
popd
- Upload gitian zips to SourceForge
- Celebrate
- Celebrate

View File

@@ -5,7 +5,7 @@ SetCompressor /SOLID lzma
# General Symbol Definitions
!define REGKEY "SOFTWARE\$(^Name)"
!define VERSION 0.8.2
!define VERSION 0.8.6
!define COMPANY "Bitcoin project"
!define URL http://www.bitcoin.org/
@@ -45,13 +45,13 @@ Var StartMenuGroup
!insertmacro MUI_LANGUAGE English
# Installer attributes
OutFile bitcoin-0.8.2-win32-setup.exe
OutFile bitcoin-0.8.6-win32-setup.exe
InstallDir $PROGRAMFILES\Bitcoin
CRCCheck on
XPStyle on
BrandingText " "
ShowInstDetails show
VIProductVersion 0.8.2.2
VIProductVersion 0.8.6.0
VIAddVersionKey ProductName Bitcoin
VIAddVersionKey ProductVersion "${VERSION}"
VIAddVersionKey CompanyName "${COMPANY}"

View File

@@ -243,15 +243,7 @@ bool CAlert::ProcessAlert(bool fThread)
// be safe we first strip anything not in safeChars, then add single quotes around
// the whole string before passing it to the shell:
std::string singleQuote("'");
// safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything
// even possibly remotely dangerous like & or >
std::string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@");
std::string safeStatus;
for (std::string::size_type i = 0; i < strStatusBar.size(); i++)
{
if (safeChars.find(strStatusBar[i]) != std::string::npos)
safeStatus.push_back(strStatusBar[i]);
}
std::string safeStatus = SanitizeString(strStatusBar);
safeStatus = singleQuote+safeStatus+singleQuote;
boost::replace_all(strCmd, "%s", safeStatus);

View File

@@ -479,7 +479,7 @@ bool HTTPAuthorized(map<string, string>& mapHeaders)
return false;
string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
string strUserPass = DecodeBase64(strUserPass64);
return strUserPass == strRPCUserColonPass;
return TimingResistantEqual(strUserPass, strRPCUserColonPass);
}
//

View File

@@ -23,6 +23,8 @@ vData(min((unsigned int)(-1 / LN2SQUARED * nElements * log(nFPRate)), MAX_BLOOM
// The ideal number of hash functions is filter size * ln(2) / number of elements
// Again, we ignore filter parameters which will create a bloom filter with more hash functions than the protocol limits
// See http://en.wikipedia.org/wiki/Bloom_filter for an explanation of these formulas
isFull(false),
isEmpty(false),
nHashFuncs(min((unsigned int)(vData.size() * 8 / nElements * LN2), MAX_HASH_FUNCS)),
nTweak(nTweakIn),
nFlags(nFlagsIn)
@@ -37,7 +39,7 @@ inline unsigned int CBloomFilter::Hash(unsigned int nHashNum, const std::vector<
void CBloomFilter::insert(const vector<unsigned char>& vKey)
{
if (vData.size() == 1 && vData[0] == 0xff)
if (isFull)
return;
for (unsigned int i = 0; i < nHashFuncs; i++)
{
@@ -45,6 +47,7 @@ void CBloomFilter::insert(const vector<unsigned char>& vKey)
// Sets bit nIndex of vData
vData[nIndex >> 3] |= bit_mask[7 & nIndex];
}
isEmpty = false;
}
void CBloomFilter::insert(const COutPoint& outpoint)
@@ -63,8 +66,10 @@ void CBloomFilter::insert(const uint256& hash)
bool CBloomFilter::contains(const vector<unsigned char>& vKey) const
{
if (vData.size() == 1 && vData[0] == 0xff)
if (isFull)
return true;
if (isEmpty)
return false;
for (unsigned int i = 0; i < nHashFuncs; i++)
{
unsigned int nIndex = Hash(i, vKey);
@@ -99,6 +104,10 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx, const uint256& ha
bool fFound = false;
// Match if the filter contains the hash of tx
// for finding tx when they appear in a block
if (isFull)
return true;
if (isEmpty)
return false;
if (contains(hash))
fFound = true;
@@ -158,3 +167,16 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx, const uint256& ha
return false;
}
void CBloomFilter::UpdateEmptyFull()
{
bool full = true;
bool empty = true;
for (unsigned int i = 0; i < vData.size(); i++)
{
full &= vData[i] == 0xff;
empty &= vData[i] == 0;
}
isFull = full;
isEmpty = empty;
}

View File

@@ -42,6 +42,8 @@ class CBloomFilter
{
private:
std::vector<unsigned char> vData;
bool isFull;
bool isEmpty;
unsigned int nHashFuncs;
unsigned int nTweak;
unsigned char nFlags;
@@ -57,9 +59,7 @@ public:
// It should generally always be a random value (and is largely only exposed for unit testing)
// nFlags should be one of the BLOOM_UPDATE_* enums (not _MASK)
CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak, unsigned char nFlagsIn);
// Using a filter initialized with this results in undefined behavior
// Should only be used for deserialization
CBloomFilter() {}
CBloomFilter() : isFull(true) {}
IMPLEMENT_SERIALIZE
(
@@ -83,6 +83,9 @@ public:
// Also adds any outputs which match the filter to the filter (to match their spending txes)
bool IsRelevantAndUpdate(const CTransaction& tx, const uint256& hash);
// Checks for empty and full filters to avoid wasting cpu
void UpdateEmptyFull();
};
#endif /* BITCOIN_BLOOM_H */

View File

@@ -45,11 +45,12 @@ namespace Checkpoints
(210000, uint256("0x000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e"))
(216116, uint256("0x00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e"))
(225430, uint256("0x00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932"))
(250000, uint256("0x000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214"))
;
static const CCheckpointData data = {
&mapCheckpoints,
1363044259, // * UNIX timestamp of last checkpoint block
14264869, // * total number of transactions between genesis and last checkpoint
1375533383, // * UNIX timestamp of last checkpoint block
21491097, // * total number of transactions between genesis and last checkpoint
// (the tx=... number in the SetBestChain debug.log lines)
60000.0 // * estimated number of transactions per day after checkpoint
};

View File

@@ -8,8 +8,8 @@
// These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it
#define CLIENT_VERSION_MAJOR 0
#define CLIENT_VERSION_MINOR 8
#define CLIENT_VERSION_REVISION 2
#define CLIENT_VERSION_BUILD 2
#define CLIENT_VERSION_REVISION 6
#define CLIENT_VERSION_BUILD 0
// Set to true for release, false for prerelease or test build
#define CLIENT_VERSION_IS_RELEASE true

View File

@@ -6,7 +6,6 @@
#include "db.h"
#include "util.h"
#include "main.h"
#include <boost/version.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
@@ -541,6 +540,8 @@ bool CAddrDB::Read(CAddrMan& addr)
// use file size to size memory buffer
int fileSize = GetFilesize(filein);
int dataSize = fileSize - sizeof(uint256);
//Don't try to resize to a negative number if file is small
if ( dataSize < 0 ) dataSize = 0;
vector<unsigned char> vchData;
vchData.resize(dataSize);
uint256 hashIn;

View File

@@ -89,6 +89,7 @@ static CCoinsViewDB *pcoinsdbview;
void Shutdown()
{
printf("Shutdown : In progress...\n");
static CCriticalSection cs_Shutdown;
TRY_LOCK(cs_Shutdown, lockShutdown);
if (!lockShutdown) return;
@@ -114,6 +115,7 @@ void Shutdown()
boost::filesystem::remove(GetPidFile());
UnregisterWallet(pwalletMain);
delete pwalletMain;
printf("Shutdown : done\n");
}
//
@@ -333,7 +335,7 @@ std::string HelpMessage()
" -testnet " + _("Use the test network") + "\n" +
" -debug " + _("Output extra debugging information. Implies all other -debug* options") + "\n" +
" -debugnet " + _("Output extra network debugging information") + "\n" +
" -logtimestamps " + _("Prepend debug output with timestamp") + "\n" +
" -logtimestamps " + _("Prepend debug output with timestamp (default: 1)") + "\n" +
" -shrinkdebugfile " + _("Shrink debug.log file on client startup (default: 1 when no -debug)") + "\n" +
" -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n" +
#ifdef WIN32
@@ -531,7 +533,7 @@ bool AppInit2(boost::thread_group& threadGroup)
// Make sure enough file descriptors are available
int nBind = std::max((int)mapArgs.count("-bind"), 1);
nMaxConnections = GetArg("-maxconnections", 125);
nMaxConnections = std::max(std::min(nMaxConnections, FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS), 0);
nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0);
int nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
if (nFD < MIN_CORE_FILEDESCRIPTORS)
return InitError(_("Not enough file descriptors available."));
@@ -569,7 +571,7 @@ bool AppInit2(boost::thread_group& threadGroup)
#endif
fPrintToConsole = GetBoolArg("-printtoconsole");
fPrintToDebugger = GetBoolArg("-printtodebugger");
fLogTimestamps = GetBoolArg("-logtimestamps");
fLogTimestamps = GetBoolArg("-logtimestamps", true);
if (mapArgs.count("-timeout"))
{

View File

@@ -28,7 +28,8 @@ namespace json_spirit
template< class String_type >
String_type non_printable_to_string( unsigned int c )
{
typedef typename String_type::value_type Char_type;
// Silence the warning: typedef Char_type locally defined but not used [-Wunused-local-typedefs]
// typedef typename String_type::value_type Char_type;
String_type result( 6, '\\' );

View File

@@ -328,7 +328,10 @@ bool CKey::SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
}
if (nRecId == -1)
{
ECDSA_SIG_free(sig);
throw key_error("CKey::SignCompact() : unable to construct recoverable key");
}
vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
@@ -367,16 +370,40 @@ bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& v
ECDSA_SIG_free(sig);
return true;
}
ECDSA_SIG_free(sig);
return false;
}
bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
{
// -1 = error, 0 = bad sig, 1 = good
if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
if (vchSig.empty())
return false;
return true;
// New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first.
unsigned char *norm_der = NULL;
ECDSA_SIG *norm_sig = ECDSA_SIG_new();
const unsigned char* sigptr = &vchSig[0];
assert(norm_sig);
if (d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()) == NULL)
{
/* As of OpenSSL 1.0.0p d2i_ECDSA_SIG frees and nulls the pointer on
* error. But OpenSSL's own use of this function redundantly frees the
* result. As ECDSA_SIG_free(NULL) is a no-op, and in the absence of a
* clear contract for the function behaving the same way is more
* conservative.
*/
ECDSA_SIG_free(norm_sig);
return false;
}
int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der);
ECDSA_SIG_free(norm_sig);
if (derlen <= 0)
return false;
// -1 = error, 0 = bad sig, 1 = good
bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1;
OPENSSL_free(norm_der);
return ret;
}
bool CKey::VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)

View File

@@ -6,6 +6,7 @@ build_config.mk
*.so.*
*_test
db_bench
leveldbutil
Release
Debug
Benchmark

View File

@@ -6,3 +6,6 @@ Google Inc.
# Initial version authors:
Jeffrey Dean <jeff@google.com>
Sanjay Ghemawat <sanjay@google.com>
# Partial list of contributors:
Kevin Regan <kevin.d.regan@gmail.com>

View File

@@ -12,7 +12,7 @@ OPT ?= -O2 -DNDEBUG # (A) Production use (optimized mode)
#-----------------------------------------------
# detect what platform we're building on
$(shell CC=$(CC) CXX=$(CXX) TARGET_OS=$(TARGET_OS) \
$(shell CC="$(CC)" CXX="$(CXX)" TARGET_OS="$(TARGET_OS)" \
./build_detect_platform build_config.mk ./)
# this file is generated by the previous line to set build flags and sources
include build_config.mk
@@ -31,6 +31,7 @@ TESTHARNESS = ./util/testharness.o $(TESTUTIL)
TESTS = \
arena_test \
autocompact_test \
bloom_test \
c_test \
cache_test \
@@ -42,6 +43,7 @@ TESTS = \
env_test \
filename_test \
filter_block_test \
issue178_test \
log_test \
memenv_test \
skiplist_test \
@@ -69,7 +71,7 @@ SHARED = $(SHARED1)
else
# Update db.h if you change these.
SHARED_MAJOR = 1
SHARED_MINOR = 9
SHARED_MINOR = 13
SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT)
SHARED2 = $(SHARED1).$(SHARED_MAJOR)
SHARED3 = $(SHARED1).$(SHARED_MAJOR).$(SHARED_MINOR)
@@ -113,6 +115,9 @@ leveldbutil: db/leveldb_main.o $(LIBOBJECTS)
arena_test: util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(CXX) $(LDFLAGS) util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
autocompact_test: db/autocompact_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(CXX) $(LDFLAGS) db/autocompact_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
bloom_test: util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(CXX) $(LDFLAGS) util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
@@ -146,6 +151,9 @@ filename_test: db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS)
filter_block_test: table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(CXX) $(LDFLAGS) table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
issue178_test: issues/issue178_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(CXX) $(LDFLAGS) issues/issue178_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
log_test: db/log_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(CXX) $(LDFLAGS) db/log_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)

View File

@@ -44,6 +44,10 @@ if test -z "$CXX"; then
CXX=g++
fi
if test -z "$TMPDIR"; then
TMPDIR=/tmp
fi
# Detect OS
if test -z "$TARGET_OS"; then
TARGET_OS=`uname -s`
@@ -94,6 +98,12 @@ case "$TARGET_OS" in
PLATFORM_LIBS="-lpthread"
PORT_FILE=port/port_posix.cc
;;
GNU/kFreeBSD)
PLATFORM=OS_KFREEBSD
COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_KFREEBSD"
PLATFORM_LIBS="-lpthread"
PORT_FILE=port/port_posix.cc
;;
NetBSD)
PLATFORM=OS_NETBSD
COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_NETBSD"
@@ -163,8 +173,10 @@ if [ "$CROSS_COMPILE" = "true" ]; then
# Cross-compiling; do not try any compilation tests.
true
else
CXXOUTPUT="${TMPDIR}/leveldb_build_detect_platform-cxx.$$"
# If -std=c++0x works, use <cstdatomic>. Otherwise use port_posix.h.
$CXX $CXXFLAGS -std=c++0x -x c++ - -o /dev/null 2>/dev/null <<EOF
$CXX $CXXFLAGS -std=c++0x -x c++ - -o $CXXOUTPUT 2>/dev/null <<EOF
#include <cstdatomic>
int main() {}
EOF
@@ -176,12 +188,14 @@ EOF
fi
# Test whether tcmalloc is available
$CXX $CXXFLAGS -x c++ - -o /dev/null -ltcmalloc 2>/dev/null <<EOF
$CXX $CXXFLAGS -x c++ - -o $CXXOUTPUT -ltcmalloc 2>/dev/null <<EOF
int main() {}
EOF
if [ "$?" = 0 ]; then
PLATFORM_LIBS="$PLATFORM_LIBS -ltcmalloc"
fi
rm -f $CXXOUTPUT 2>/dev/null
fi
PLATFORM_CCFLAGS="$PLATFORM_CCFLAGS $COMMON_FLAGS"

View File

@@ -35,6 +35,7 @@ class CorruptionTest {
CorruptionTest() {
tiny_cache_ = NewLRUCache(100);
options_.env = &env_;
options_.block_cache = tiny_cache_;
dbname_ = test::TmpDir() + "/db_test";
DestroyDB(dbname_, options_);
@@ -50,17 +51,14 @@ class CorruptionTest {
delete tiny_cache_;
}
Status TryReopen(Options* options = NULL) {
Status TryReopen() {
delete db_;
db_ = NULL;
Options opt = (options ? *options : options_);
opt.env = &env_;
opt.block_cache = tiny_cache_;
return DB::Open(opt, dbname_, &db_);
return DB::Open(options_, dbname_, &db_);
}
void Reopen(Options* options = NULL) {
ASSERT_OK(TryReopen(options));
void Reopen() {
ASSERT_OK(TryReopen());
}
void RepairDB() {
@@ -92,6 +90,10 @@ class CorruptionTest {
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
uint64_t key;
Slice in(iter->key());
if (in == "" || in == "~") {
// Ignore boundary keys.
continue;
}
if (!ConsumeDecimalNumber(&in, &key) ||
!in.empty() ||
key < next_expected) {
@@ -233,7 +235,7 @@ TEST(CorruptionTest, TableFile) {
dbi->TEST_CompactRange(1, NULL, NULL);
Corrupt(kTableFile, 100, 1);
Check(99, 99);
Check(90, 99);
}
TEST(CorruptionTest, TableFileIndexData) {
@@ -299,7 +301,7 @@ TEST(CorruptionTest, CompactionInputError) {
ASSERT_EQ(1, Property("leveldb.num-files-at-level" + NumberToString(last)));
Corrupt(kTableFile, 100, 1);
Check(9, 9);
Check(5, 9);
// Force compactions by writing lots of values
Build(10000);
@@ -307,32 +309,23 @@ TEST(CorruptionTest, CompactionInputError) {
}
TEST(CorruptionTest, CompactionInputErrorParanoid) {
Options options;
options.paranoid_checks = true;
options.write_buffer_size = 1048576;
Reopen(&options);
options_.paranoid_checks = true;
options_.write_buffer_size = 512 << 10;
Reopen();
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
// Fill levels >= 1 so memtable compaction outputs to level 1
for (int level = 1; level < config::kNumLevels; level++) {
dbi->Put(WriteOptions(), "", "begin");
dbi->Put(WriteOptions(), "~", "end");
// Make multiple inputs so we need to compact.
for (int i = 0; i < 2; i++) {
Build(10);
dbi->TEST_CompactMemTable();
Corrupt(kTableFile, 100, 1);
env_.SleepForMicroseconds(100000);
}
dbi->CompactRange(NULL, NULL);
Build(10);
dbi->TEST_CompactMemTable();
ASSERT_EQ(1, Property("leveldb.num-files-at-level0"));
Corrupt(kTableFile, 100, 1);
Check(9, 9);
// Write must eventually fail because of corrupted table
Status s;
// Write must fail because of corrupted table
std::string tmp1, tmp2;
for (int i = 0; i < 10000 && s.ok(); i++) {
s = db_->Put(WriteOptions(), Key(i, &tmp1), Value(i, &tmp2));
}
Status s = db_->Put(WriteOptions(), Key(5, &tmp1), Value(5, &tmp2));
ASSERT_TRUE(!s.ok()) << "write did not fail in corrupted paranoid db";
}

View File

@@ -35,6 +35,8 @@
namespace leveldb {
const int kNumNonTableCacheFiles = 10;
// Information kept for every waiting writer
struct DBImpl::Writer {
Status status;
@@ -92,9 +94,9 @@ Options SanitizeOptions(const std::string& dbname,
Options result = src;
result.comparator = icmp;
result.filter_policy = (src.filter_policy != NULL) ? ipolicy : NULL;
ClipToRange(&result.max_open_files, 20, 50000);
ClipToRange(&result.write_buffer_size, 64<<10, 1<<30);
ClipToRange(&result.block_size, 1<<10, 4<<20);
ClipToRange(&result.max_open_files, 64 + kNumNonTableCacheFiles, 50000);
ClipToRange(&result.write_buffer_size, 64<<10, 1<<30);
ClipToRange(&result.block_size, 1<<10, 4<<20);
if (result.info_log == NULL) {
// Open a log file in the same directory as the db
src.env->CreateDir(dbname); // In case it does not exist
@@ -111,14 +113,14 @@ Options SanitizeOptions(const std::string& dbname,
return result;
}
DBImpl::DBImpl(const Options& options, const std::string& dbname)
: env_(options.env),
internal_comparator_(options.comparator),
internal_filter_policy_(options.filter_policy),
options_(SanitizeOptions(
dbname, &internal_comparator_, &internal_filter_policy_, options)),
owns_info_log_(options_.info_log != options.info_log),
owns_cache_(options_.block_cache != options.block_cache),
DBImpl::DBImpl(const Options& raw_options, const std::string& dbname)
: env_(raw_options.env),
internal_comparator_(raw_options.comparator),
internal_filter_policy_(raw_options.filter_policy),
options_(SanitizeOptions(dbname, &internal_comparator_,
&internal_filter_policy_, raw_options)),
owns_info_log_(options_.info_log != raw_options.info_log),
owns_cache_(options_.block_cache != raw_options.block_cache),
dbname_(dbname),
db_lock_(NULL),
shutting_down_(NULL),
@@ -128,14 +130,16 @@ DBImpl::DBImpl(const Options& options, const std::string& dbname)
logfile_(NULL),
logfile_number_(0),
log_(NULL),
seed_(0),
tmp_batch_(new WriteBatch),
bg_compaction_scheduled_(false),
manual_compaction_(NULL) {
manual_compaction_(NULL),
consecutive_compaction_errors_(0) {
mem_->Ref();
has_imm_.Release_Store(NULL);
// Reserve ten files or so for other uses and give the rest to TableCache.
const int table_cache_size = options.max_open_files - 10;
const int table_cache_size = options_.max_open_files - kNumNonTableCacheFiles;
table_cache_ = new TableCache(dbname_, &options_, table_cache_size);
versions_ = new VersionSet(dbname_, &options_, table_cache_,
@@ -310,16 +314,24 @@ Status DBImpl::Recover(VersionEdit* edit) {
if (!s.ok()) {
return s;
}
std::set<uint64_t> expected;
versions_->AddLiveFiles(&expected);
uint64_t number;
FileType type;
std::vector<uint64_t> logs;
for (size_t i = 0; i < filenames.size(); i++) {
if (ParseFileName(filenames[i], &number, &type)
&& type == kLogFile
&& ((number >= min_log) || (number == prev_log))) {
logs.push_back(number);
if (ParseFileName(filenames[i], &number, &type)) {
expected.erase(number);
if (type == kLogFile && ((number >= min_log) || (number == prev_log)))
logs.push_back(number);
}
}
if (!expected.empty()) {
char buf[50];
snprintf(buf, sizeof(buf), "%d missing files; e.g.",
static_cast<int>(expected.size()));
return Status::Corruption(buf, TableFileName(dbname_, *(expected.begin())));
}
// Recover in the order in which the logs were generated
std::sort(logs.begin(), logs.end());
@@ -611,6 +623,7 @@ void DBImpl::BackgroundCall() {
Status s = BackgroundCompaction();
if (s.ok()) {
// Success
consecutive_compaction_errors_ = 0;
} else if (shutting_down_.Acquire_Load()) {
// Error most likely due to shutdown; do not wait
} else {
@@ -622,7 +635,12 @@ void DBImpl::BackgroundCall() {
Log(options_.info_log, "Waiting after background compaction error: %s",
s.ToString().c_str());
mutex_.Unlock();
env_->SleepForMicroseconds(1000000);
++consecutive_compaction_errors_;
int seconds_to_sleep = 1;
for (int i = 0; i < 3 && i < consecutive_compaction_errors_ - 1; ++i) {
seconds_to_sleep *= 2;
}
env_->SleepForMicroseconds(seconds_to_sleep * 1000000);
mutex_.Lock();
}
}
@@ -1010,7 +1028,8 @@ static void CleanupIteratorState(void* arg1, void* arg2) {
} // namespace
Iterator* DBImpl::NewInternalIterator(const ReadOptions& options,
SequenceNumber* latest_snapshot) {
SequenceNumber* latest_snapshot,
uint32_t* seed) {
IterState* cleanup = new IterState;
mutex_.Lock();
*latest_snapshot = versions_->LastSequence();
@@ -1034,13 +1053,15 @@ Iterator* DBImpl::NewInternalIterator(const ReadOptions& options,
cleanup->version = versions_->current();
internal_iter->RegisterCleanup(CleanupIteratorState, cleanup, NULL);
*seed = ++seed_;
mutex_.Unlock();
return internal_iter;
}
Iterator* DBImpl::TEST_NewInternalIterator() {
SequenceNumber ignored;
return NewInternalIterator(ReadOptions(), &ignored);
uint32_t ignored_seed;
return NewInternalIterator(ReadOptions(), &ignored, &ignored_seed);
}
int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes() {
@@ -1097,12 +1118,21 @@ Status DBImpl::Get(const ReadOptions& options,
Iterator* DBImpl::NewIterator(const ReadOptions& options) {
SequenceNumber latest_snapshot;
Iterator* internal_iter = NewInternalIterator(options, &latest_snapshot);
uint32_t seed;
Iterator* iter = NewInternalIterator(options, &latest_snapshot, &seed);
return NewDBIterator(
&dbname_, env_, user_comparator(), internal_iter,
this, user_comparator(), iter,
(options.snapshot != NULL
? reinterpret_cast<const SnapshotImpl*>(options.snapshot)->number_
: latest_snapshot));
: latest_snapshot),
seed);
}
void DBImpl::RecordReadSample(Slice key) {
MutexLock l(&mutex_);
if (versions_->current()->RecordReadSample(key)) {
MaybeScheduleCompaction();
}
}
const Snapshot* DBImpl::GetSnapshot() {
@@ -1268,10 +1298,11 @@ Status DBImpl::MakeRoomForWrite(bool force) {
} else if (imm_ != NULL) {
// We have filled up the current memtable, but the previous
// one is still being compacted, so we wait.
Log(options_.info_log, "Current memtable full; waiting...\n");
bg_cv_.Wait();
} else if (versions_->NumLevelFiles(0) >= config::kL0_StopWritesTrigger) {
// There are too many level-0 files.
Log(options_.info_log, "waiting...\n");
Log(options_.info_log, "Too many L0 files; waiting...\n");
bg_cv_.Wait();
} else {
// Attempt to switch to a new memtable and trigger compaction of old

View File

@@ -59,13 +59,19 @@ class DBImpl : public DB {
// file at a level >= 1.
int64_t TEST_MaxNextLevelOverlappingBytes();
// Record a sample of bytes read at the specified internal key.
// Samples are taken approximately once every config::kReadBytesPeriod
// bytes.
void RecordReadSample(Slice key);
private:
friend class DB;
struct CompactionState;
struct Writer;
Iterator* NewInternalIterator(const ReadOptions&,
SequenceNumber* latest_snapshot);
SequenceNumber* latest_snapshot,
uint32_t* seed);
Status NewDB();
@@ -135,6 +141,7 @@ class DBImpl : public DB {
WritableFile* logfile_;
uint64_t logfile_number_;
log::Writer* log_;
uint32_t seed_; // For sampling.
// Queue of writers.
std::deque<Writer*> writers_;
@@ -163,6 +170,7 @@ class DBImpl : public DB {
// Have we encountered a background error in paranoid mode?
Status bg_error_;
int consecutive_compaction_errors_;
// Per level compaction stats. stats_[level] stores the stats for
// compactions that produced data for the specified "level".

View File

@@ -5,12 +5,14 @@
#include "db/db_iter.h"
#include "db/filename.h"
#include "db/db_impl.h"
#include "db/dbformat.h"
#include "leveldb/env.h"
#include "leveldb/iterator.h"
#include "port/port.h"
#include "util/logging.h"
#include "util/mutexlock.h"
#include "util/random.h"
namespace leveldb {
@@ -46,15 +48,16 @@ class DBIter: public Iterator {
kReverse
};
DBIter(const std::string* dbname, Env* env,
const Comparator* cmp, Iterator* iter, SequenceNumber s)
: dbname_(dbname),
env_(env),
DBIter(DBImpl* db, const Comparator* cmp, Iterator* iter, SequenceNumber s,
uint32_t seed)
: db_(db),
user_comparator_(cmp),
iter_(iter),
sequence_(s),
direction_(kForward),
valid_(false) {
valid_(false),
rnd_(seed),
bytes_counter_(RandomPeriod()) {
}
virtual ~DBIter() {
delete iter_;
@@ -100,8 +103,12 @@ class DBIter: public Iterator {
}
}
const std::string* const dbname_;
Env* const env_;
// Pick next gap with average value of config::kReadBytesPeriod.
ssize_t RandomPeriod() {
return rnd_.Uniform(2*config::kReadBytesPeriod);
}
DBImpl* db_;
const Comparator* const user_comparator_;
Iterator* const iter_;
SequenceNumber const sequence_;
@@ -112,13 +119,23 @@ class DBIter: public Iterator {
Direction direction_;
bool valid_;
Random rnd_;
ssize_t bytes_counter_;
// No copying allowed
DBIter(const DBIter&);
void operator=(const DBIter&);
};
inline bool DBIter::ParseKey(ParsedInternalKey* ikey) {
if (!ParseInternalKey(iter_->key(), ikey)) {
Slice k = iter_->key();
ssize_t n = k.size() + iter_->value().size();
bytes_counter_ -= n;
while (bytes_counter_ < 0) {
bytes_counter_ += RandomPeriod();
db_->RecordReadSample(k);
}
if (!ParseInternalKey(k, ikey)) {
status_ = Status::Corruption("corrupted internal key in DBIter");
return false;
} else {
@@ -288,12 +305,12 @@ void DBIter::SeekToLast() {
} // anonymous namespace
Iterator* NewDBIterator(
const std::string* dbname,
Env* env,
DBImpl* db,
const Comparator* user_key_comparator,
Iterator* internal_iter,
const SequenceNumber& sequence) {
return new DBIter(dbname, env, user_key_comparator, internal_iter, sequence);
SequenceNumber sequence,
uint32_t seed) {
return new DBIter(db, user_key_comparator, internal_iter, sequence, seed);
}
} // namespace leveldb

View File

@@ -11,15 +11,17 @@
namespace leveldb {
class DBImpl;
// Return a new iterator that converts internal keys (yielded by
// "*internal_iter") that were live at the specified "sequence" number
// into appropriate user keys.
extern Iterator* NewDBIterator(
const std::string* dbname,
Env* env,
DBImpl* db,
const Comparator* user_key_comparator,
Iterator* internal_iter,
const SequenceNumber& sequence);
SequenceNumber sequence,
uint32_t seed);
} // namespace leveldb

View File

@@ -33,8 +33,11 @@ class AtomicCounter {
public:
AtomicCounter() : count_(0) { }
void Increment() {
IncrementBy(1);
}
void IncrementBy(int count) {
MutexLock l(&mu_);
count_++;
count_ += count;
}
int Read() {
MutexLock l(&mu_);
@@ -45,6 +48,10 @@ class AtomicCounter {
count_ = 0;
}
};
void DelayMilliseconds(int millis) {
Env::Default()->SleepForMicroseconds(millis * 1000);
}
}
// Special Env used to delay background operations
@@ -69,6 +76,7 @@ class SpecialEnv : public EnvWrapper {
AtomicCounter random_read_counter_;
AtomicCounter sleep_counter_;
AtomicCounter sleep_time_counter_;
explicit SpecialEnv(Env* base) : EnvWrapper(base) {
delay_sstable_sync_.Release_Store(NULL);
@@ -103,7 +111,7 @@ class SpecialEnv : public EnvWrapper {
Status Flush() { return base_->Flush(); }
Status Sync() {
while (env_->delay_sstable_sync_.Acquire_Load() != NULL) {
env_->SleepForMicroseconds(100000);
DelayMilliseconds(100);
}
return base_->Sync();
}
@@ -174,8 +182,9 @@ class SpecialEnv : public EnvWrapper {
virtual void SleepForMicroseconds(int micros) {
sleep_counter_.Increment();
target()->SleepForMicroseconds(micros);
sleep_time_counter_.IncrementBy(micros);
}
};
class DBTest {
@@ -461,6 +470,20 @@ class DBTest {
}
return result;
}
bool DeleteAnSSTFile() {
std::vector<std::string> filenames;
ASSERT_OK(env_->GetChildren(dbname_, &filenames));
uint64_t number;
FileType type;
for (size_t i = 0; i < filenames.size(); i++) {
if (ParseFileName(filenames[i], &number, &type) && type == kTableFile) {
ASSERT_OK(env_->DeleteFile(TableFileName(dbname_, number)));
return true;
}
}
return false;
}
};
TEST(DBTest, Empty) {
@@ -611,7 +634,7 @@ TEST(DBTest, GetEncountersEmptyLevel) {
}
// Step 4: Wait for compaction to finish
env_->SleepForMicroseconds(1000000);
DelayMilliseconds(1000);
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
} while (ChangeOptions());
@@ -1295,7 +1318,7 @@ TEST(DBTest, L0_CompactionBug_Issue44_a) {
Reopen();
Reopen();
ASSERT_EQ("(a->v)", Contents());
env_->SleepForMicroseconds(1000000); // Wait for compaction to finish
DelayMilliseconds(1000); // Wait for compaction to finish
ASSERT_EQ("(a->v)", Contents());
}
@@ -1311,7 +1334,7 @@ TEST(DBTest, L0_CompactionBug_Issue44_b) {
Put("","");
Reopen();
Put("","");
env_->SleepForMicroseconds(1000000); // Wait for compaction to finish
DelayMilliseconds(1000); // Wait for compaction to finish
Reopen();
Put("d","dv");
Reopen();
@@ -1321,7 +1344,7 @@ TEST(DBTest, L0_CompactionBug_Issue44_b) {
Delete("b");
Reopen();
ASSERT_EQ("(->)(c->cv)", Contents());
env_->SleepForMicroseconds(1000000); // Wait for compaction to finish
DelayMilliseconds(1000); // Wait for compaction to finish
ASSERT_EQ("(->)(c->cv)", Contents());
}
@@ -1506,6 +1529,30 @@ TEST(DBTest, NoSpace) {
ASSERT_GE(env_->sleep_counter_.Read(), 5);
}
TEST(DBTest, ExponentialBackoff) {
Options options = CurrentOptions();
options.env = env_;
Reopen(&options);
ASSERT_OK(Put("foo", "v1"));
ASSERT_EQ("v1", Get("foo"));
Compact("a", "z");
env_->non_writable_.Release_Store(env_); // Force errors for new files
env_->sleep_counter_.Reset();
env_->sleep_time_counter_.Reset();
for (int i = 0; i < 5; i++) {
dbfull()->TEST_CompactRange(2, NULL, NULL);
}
env_->non_writable_.Release_Store(NULL);
// Wait for compaction to finish
DelayMilliseconds(1000);
ASSERT_GE(env_->sleep_counter_.Read(), 5);
ASSERT_LT(env_->sleep_counter_.Read(), 10);
ASSERT_GE(env_->sleep_time_counter_.Read(), 10e6);
}
TEST(DBTest, NonWritableFileSystem) {
Options options = CurrentOptions();
options.write_buffer_size = 1000;
@@ -1519,7 +1566,7 @@ TEST(DBTest, NonWritableFileSystem) {
fprintf(stderr, "iter %d; errors %d\n", i, errors);
if (!Put("foo", big).ok()) {
errors++;
env_->SleepForMicroseconds(100000);
DelayMilliseconds(100);
}
}
ASSERT_GT(errors, 0);
@@ -1567,6 +1614,24 @@ TEST(DBTest, ManifestWriteError) {
}
}
TEST(DBTest, MissingSSTFile) {
ASSERT_OK(Put("foo", "bar"));
ASSERT_EQ("bar", Get("foo"));
// Dump the memtable to disk.
dbfull()->TEST_CompactMemTable();
ASSERT_EQ("bar", Get("foo"));
Close();
ASSERT_TRUE(DeleteAnSSTFile());
Options options = CurrentOptions();
options.paranoid_checks = true;
Status s = TryReopen(&options);
ASSERT_TRUE(!s.ok());
ASSERT_TRUE(s.ToString().find("issing") != std::string::npos)
<< s.ToString();
}
TEST(DBTest, FilesDeletedAfterCompaction) {
ASSERT_OK(Put("foo", "v2"));
Compact("a", "z");
@@ -1711,13 +1776,13 @@ TEST(DBTest, MultiThreaded) {
}
// Let them run for a while
env_->SleepForMicroseconds(kTestSeconds * 1000000);
DelayMilliseconds(kTestSeconds * 1000);
// Stop the threads and wait for them to finish
mt.stop.Release_Store(&mt);
for (int id = 0; id < kNumThreads; id++) {
while (mt.thread_done[id].Acquire_Load() == NULL) {
env_->SleepForMicroseconds(100000);
DelayMilliseconds(100);
}
}
} while (ChangeOptions());

View File

@@ -26,7 +26,7 @@ std::string ParsedInternalKey::DebugString() const {
(unsigned long long) sequence,
int(type));
std::string result = "'";
result += user_key.ToString();
result += EscapeString(user_key.ToString());
result += buf;
return result;
}

View File

@@ -38,6 +38,9 @@ static const int kL0_StopWritesTrigger = 12;
// space if the same key space is being repeatedly overwritten.
static const int kMaxMemCompactLevel = 2;
// Approximate gap in bytes between samples of data read during iteration.
static const int kReadBytesPeriod = 1048576;
} // namespace config
class InternalKey;

View File

@@ -70,7 +70,7 @@ TEST(FileNameTest, Parse) {
for (int i = 0; i < sizeof(errors) / sizeof(errors[0]); i++) {
std::string f = errors[i];
ASSERT_TRUE(!ParseFileName(f, &number, &type)) << f;
};
}
}
TEST(FileNameTest, Construction) {

View File

@@ -289,6 +289,51 @@ static bool NewestFirst(FileMetaData* a, FileMetaData* b) {
return a->number > b->number;
}
void Version::ForEachOverlapping(Slice user_key, Slice internal_key,
void* arg,
bool (*func)(void*, int, FileMetaData*)) {
// TODO(sanjay): Change Version::Get() to use this function.
const Comparator* ucmp = vset_->icmp_.user_comparator();
// Search level-0 in order from newest to oldest.
std::vector<FileMetaData*> tmp;
tmp.reserve(files_[0].size());
for (uint32_t i = 0; i < files_[0].size(); i++) {
FileMetaData* f = files_[0][i];
if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 &&
ucmp->Compare(user_key, f->largest.user_key()) <= 0) {
tmp.push_back(f);
}
}
if (!tmp.empty()) {
std::sort(tmp.begin(), tmp.end(), NewestFirst);
for (uint32_t i = 0; i < tmp.size(); i++) {
if (!(*func)(arg, 0, tmp[i])) {
return;
}
}
}
// Search other levels.
for (int level = 1; level < config::kNumLevels; level++) {
size_t num_files = files_[level].size();
if (num_files == 0) continue;
// Binary search to find earliest index whose largest key >= internal_key.
uint32_t index = FindFile(vset_->icmp_, files_[level], internal_key);
if (index < num_files) {
FileMetaData* f = files_[level][index];
if (ucmp->Compare(user_key, f->smallest.user_key()) < 0) {
// All of "f" is past any data for user_key
} else {
if (!(*func)(arg, level, f)) {
return;
}
}
}
}
}
Status Version::Get(const ReadOptions& options,
const LookupKey& k,
std::string* value,
@@ -401,6 +446,44 @@ bool Version::UpdateStats(const GetStats& stats) {
return false;
}
bool Version::RecordReadSample(Slice internal_key) {
ParsedInternalKey ikey;
if (!ParseInternalKey(internal_key, &ikey)) {
return false;
}
struct State {
GetStats stats; // Holds first matching file
int matches;
static bool Match(void* arg, int level, FileMetaData* f) {
State* state = reinterpret_cast<State*>(arg);
state->matches++;
if (state->matches == 1) {
// Remember first match.
state->stats.seek_file = f;
state->stats.seek_file_level = level;
}
// We can stop iterating once we have a second match.
return state->matches < 2;
}
};
State state;
state.matches = 0;
ForEachOverlapping(ikey.user_key, internal_key, &state, &State::Match);
// Must have at least two matches since we want to merge across
// files. But what if we have a single file that contains many
// overwrites and deletions? Should we have another mechanism for
// finding such files?
if (state.matches >= 2) {
// 1MB cost is about 1 seek (see comment in Builder::Apply).
return UpdateStats(state.stats);
}
return false;
}
void Version::Ref() {
++refs_;
}
@@ -435,10 +518,13 @@ int Version::PickLevelForMemTableOutput(
if (OverlapInLevel(level + 1, &smallest_user_key, &largest_user_key)) {
break;
}
GetOverlappingInputs(level + 2, &start, &limit, &overlaps);
const int64_t sum = TotalFileSize(overlaps);
if (sum > kMaxGrandParentOverlapBytes) {
break;
if (level + 2 < config::kNumLevels) {
// Check that file does not overlap too many grandparent bytes.
GetOverlappingInputs(level + 2, &start, &limit, &overlaps);
const int64_t sum = TotalFileSize(overlaps);
if (sum > kMaxGrandParentOverlapBytes) {
break;
}
}
level++;
}
@@ -452,6 +538,8 @@ void Version::GetOverlappingInputs(
const InternalKey* begin,
const InternalKey* end,
std::vector<FileMetaData*>* inputs) {
assert(level >= 0);
assert(level < config::kNumLevels);
inputs->clear();
Slice user_begin, user_end;
if (begin != NULL) {
@@ -1331,14 +1419,19 @@ Compaction* VersionSet::CompactRange(
}
// Avoid compacting too much in one shot in case the range is large.
const uint64_t limit = MaxFileSizeForLevel(level);
uint64_t total = 0;
for (size_t i = 0; i < inputs.size(); i++) {
uint64_t s = inputs[i]->file_size;
total += s;
if (total >= limit) {
inputs.resize(i + 1);
break;
// But we cannot do this for level-0 since level-0 files can overlap
// and we must not pick one file and drop another older file if the
// two files overlap.
if (level > 0) {
const uint64_t limit = MaxFileSizeForLevel(level);
uint64_t total = 0;
for (size_t i = 0; i < inputs.size(); i++) {
uint64_t s = inputs[i]->file_size;
total += s;
if (total >= limit) {
inputs.resize(i + 1);
break;
}
}
}

View File

@@ -78,6 +78,12 @@ class Version {
// REQUIRES: lock is held
bool UpdateStats(const GetStats& stats);
// Record a sample of bytes read at the specified internal key.
// Samples are taken approximately once every config::kReadBytesPeriod
// bytes. Returns true if a new compaction may need to be triggered.
// REQUIRES: lock is held
bool RecordReadSample(Slice key);
// Reference count management (so Versions do not disappear out from
// under live iterators)
void Ref();
@@ -114,6 +120,15 @@ class Version {
class LevelFileNumIterator;
Iterator* NewConcatenatingIterator(const ReadOptions&, int level) const;
// Call func(arg, level, f) for every file that overlaps user_key in
// order from newest to oldest. If an invocation of func returns
// false, makes no more calls.
//
// REQUIRES: user portion of internal_key == user_key.
void ForEachOverlapping(Slice user_key, Slice internal_key,
void* arg,
bool (*func)(void*, int, FileMetaData*));
VersionSet* vset_; // VersionSet to which this Version belongs
Version* next_; // Next version in linked list
Version* prev_; // Previous version in linked list

View File

@@ -14,7 +14,7 @@ namespace leveldb {
// Update Makefile if you change these
static const int kMajorVersion = 1;
static const int kMinorVersion = 9;
static const int kMinorVersion = 13;
struct Options;
struct ReadOptions;

View File

@@ -0,0 +1,92 @@
// Copyright (c) 2013 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
// Test for issue 178: a manual compaction causes deleted data to reappear.
#include <iostream>
#include <sstream>
#include <cstdlib>
#include "leveldb/db.h"
#include "leveldb/write_batch.h"
#include "util/testharness.h"
namespace {
const int kNumKeys = 1100000;
std::string Key1(int i) {
char buf[100];
snprintf(buf, sizeof(buf), "my_key_%d", i);
return buf;
}
std::string Key2(int i) {
return Key1(i) + "_xxx";
}
class Issue178 { };
TEST(Issue178, Test) {
// Get rid of any state from an old run.
std::string dbpath = leveldb::test::TmpDir() + "/leveldb_cbug_test";
DestroyDB(dbpath, leveldb::Options());
// Open database. Disable compression since it affects the creation
// of layers and the code below is trying to test against a very
// specific scenario.
leveldb::DB* db;
leveldb::Options db_options;
db_options.create_if_missing = true;
db_options.compression = leveldb::kNoCompression;
ASSERT_OK(leveldb::DB::Open(db_options, dbpath, &db));
// create first key range
leveldb::WriteBatch batch;
for (size_t i = 0; i < kNumKeys; i++) {
batch.Put(Key1(i), "value for range 1 key");
}
ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
// create second key range
batch.Clear();
for (size_t i = 0; i < kNumKeys; i++) {
batch.Put(Key2(i), "value for range 2 key");
}
ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
// delete second key range
batch.Clear();
for (size_t i = 0; i < kNumKeys; i++) {
batch.Delete(Key2(i));
}
ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
// compact database
std::string start_key = Key1(0);
std::string end_key = Key1(kNumKeys - 1);
leveldb::Slice least(start_key.data(), start_key.size());
leveldb::Slice greatest(end_key.data(), end_key.size());
// commenting out the line below causes the example to work correctly
db->CompactRange(&least, &greatest);
// count the keys
leveldb::Iterator* iter = db->NewIterator(leveldb::ReadOptions());
size_t num_keys = 0;
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
num_keys++;
}
delete iter;
ASSERT_EQ(kNumKeys, num_keys) << "Bad number of keys";
// close database
delete db;
DestroyDB(dbpath, leveldb::Options());
}
} // anonymous namespace
int main(int argc, char** argv) {
return leveldb::test::RunAllTests();
}

View File

@@ -50,6 +50,13 @@ namespace port {
// http://msdn.microsoft.com/en-us/library/ms684208(v=vs.85).aspx
#define LEVELDB_HAVE_MEMORY_BARRIER
// Mac OS
#elif defined(OS_MACOSX)
inline void MemoryBarrier() {
OSMemoryBarrier();
}
#define LEVELDB_HAVE_MEMORY_BARRIER
// Gcc on x86
#elif defined(ARCH_CPU_X86_FAMILY) && defined(__GNUC__)
inline void MemoryBarrier() {
@@ -62,19 +69,12 @@ inline void MemoryBarrier() {
// Sun Studio
#elif defined(ARCH_CPU_X86_FAMILY) && defined(__SUNPRO_CC)
inline void MemoryBarrier() {
// See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on
// See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on
// this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering.
asm volatile("" : : : "memory");
}
#define LEVELDB_HAVE_MEMORY_BARRIER
// Mac OS
#elif defined(OS_MACOSX)
inline void MemoryBarrier() {
OSMemoryBarrier();
}
#define LEVELDB_HAVE_MEMORY_BARRIER
// ARM Linux
#elif defined(ARCH_CPU_ARM_FAMILY) && defined(__linux__)
typedef void (*LinuxKernelMemoryBarrierFunc)(void);

View File

@@ -62,12 +62,16 @@
#define fflush_unlocked fflush
#endif
#if defined(OS_MACOSX) || defined(OS_FREEBSD) ||\
#if defined(OS_FREEBSD) ||\
defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD)
// Use fsync() on platforms without fdatasync()
#define fdatasync fsync
#endif
#if defined(OS_MACOSX)
#define fdatasync(fd) fcntl(fd, F_FULLFSYNC, 0)
#endif
#if defined(OS_ANDROID) && __ANDROID_API__ < 9
// fdatasync() was only introduced in API level 9 on Android. Use fsync()
// when targetting older platforms.

View File

@@ -109,12 +109,10 @@ void CondVar::Signal() {
void CondVar::SignalAll() {
wait_mtx_.Lock();
for(long i = 0; i < waiting_; ++i) {
::ReleaseSemaphore(sem1_, 1, NULL);
while(waiting_ > 0) {
--waiting_;
::WaitForSingleObject(sem2_, INFINITE);
}
::ReleaseSemaphore(sem1_, waiting_, NULL);
while(waiting_ > 0) {
--waiting_;
::WaitForSingleObject(sem2_, INFINITE);
}
wait_mtx_.Unlock();
}

View File

@@ -16,7 +16,7 @@
namespace leveldb {
inline uint32_t Block::NumRestarts() const {
assert(size_ >= 2*sizeof(uint32_t));
assert(size_ >= sizeof(uint32_t));
return DecodeFixed32(data_ + size_ - sizeof(uint32_t));
}
@@ -27,11 +27,12 @@ Block::Block(const BlockContents& contents)
if (size_ < sizeof(uint32_t)) {
size_ = 0; // Error marker
} else {
restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t);
if (restart_offset_ > size_ - sizeof(uint32_t)) {
// The size is too small for NumRestarts() and therefore
// restart_offset_ wrapped around.
size_t max_restarts_allowed = (size_-sizeof(uint32_t)) / sizeof(uint32_t);
if (NumRestarts() > max_restarts_allowed) {
// The size is too small for NumRestarts()
size_ = 0;
} else {
restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t);
}
}
}
@@ -253,7 +254,7 @@ class Block::Iter : public Iterator {
};
Iterator* Block::NewIterator(const Comparator* cmp) {
if (size_ < 2*sizeof(uint32_t)) {
if (size_ < sizeof(uint32_t)) {
return NewErrorIterator(Status::Corruption("bad block contents"));
}
const uint32_t num_restarts = NumRestarts();

View File

@@ -228,7 +228,6 @@ Status Table::InternalGet(const ReadOptions& options, const Slice& k,
!filter->KeyMayMatch(handle.offset(), k)) {
// Not found
} else {
Slice handle = iiter->value();
Iterator* block_iter = BlockReader(this, options, iiter->value());
block_iter->Seek(k);
if (block_iter->Valid()) {

View File

@@ -644,6 +644,36 @@ class Harness {
Constructor* constructor_;
};
// Test empty table/block.
TEST(Harness, Empty) {
for (int i = 0; i < kNumTestArgs; i++) {
Init(kTestArgList[i]);
Random rnd(test::RandomSeed() + 1);
Test(&rnd);
}
}
// Special test for a block with no restart entries. The C++ leveldb
// code never generates such blocks, but the Java version of leveldb
// seems to.
TEST(Harness, ZeroRestartPointsInBlock) {
char data[sizeof(uint32_t)];
memset(data, 0, sizeof(data));
BlockContents contents;
contents.data = Slice(data, sizeof(data));
contents.cachable = false;
contents.heap_allocated = false;
Block block(contents);
Iterator* iter = block.NewIterator(BytewiseComparator());
iter->SeekToFirst();
ASSERT_TRUE(!iter->Valid());
iter->SeekToLast();
ASSERT_TRUE(!iter->Valid());
iter->Seek("foo");
ASSERT_TRUE(!iter->Valid());
delete iter;
}
// Test the empty key
TEST(Harness, SimpleEmptyKey) {
for (int i = 0; i < kNumTestArgs; i++) {

View File

@@ -116,7 +116,6 @@ class HandleTable {
LRUHandle* h = list_[i];
while (h != NULL) {
LRUHandle* next = h->next_hash;
Slice key = h->key();
uint32_t hash = h->hash;
LRUHandle** ptr = &new_list[hash & (new_length - 1)];
h->next_hash = *ptr;
@@ -160,7 +159,6 @@ class LRUCache {
// mutex_ protects the following state.
port::Mutex mutex_;
size_t usage_;
uint64_t last_id_;
// Dummy head of LRU list.
// lru.prev is newest entry, lru.next is oldest entry.
@@ -170,8 +168,7 @@ class LRUCache {
};
LRUCache::LRUCache()
: usage_(0),
last_id_(0) {
: usage_(0) {
// Make empty circular linked list
lru_.next = &lru_;
lru_.prev = &lru_;

View File

@@ -109,7 +109,7 @@ TEST(Coding, Varint64) {
values.push_back(power);
values.push_back(power-1);
values.push_back(power+1);
};
}
std::string s;
for (int i = 0; i < values.size(); i++) {

View File

@@ -320,8 +320,39 @@ class PosixMmapFile : public WritableFile {
return Status::OK();
}
virtual Status Sync() {
Status SyncDirIfManifest() {
const char* f = filename_.c_str();
const char* sep = strrchr(f, '/');
Slice basename;
std::string dir;
if (sep == NULL) {
dir = ".";
basename = f;
} else {
dir = std::string(f, sep - f);
basename = sep + 1;
}
Status s;
if (basename.starts_with("MANIFEST")) {
int fd = open(dir.c_str(), O_RDONLY);
if (fd < 0) {
s = IOError(dir, errno);
} else {
if (fsync(fd) < 0) {
s = IOError(dir, errno);
}
close(fd);
}
}
return s;
}
virtual Status Sync() {
// Ensure new files referred to by the manifest are in the filesystem.
Status s = SyncDirIfManifest();
if (!s.ok()) {
return s;
}
if (pending_sync_) {
// Some unmapped data was not synced
@@ -346,6 +377,93 @@ class PosixMmapFile : public WritableFile {
}
};
#if defined(OS_MACOSX)
class PosixWriteableFile : public WritableFile {
private:
std::string filename_;
int fd_;
public:
PosixWriteableFile(const std::string& fname, int fd)
: filename_(fname),
fd_(fd)
{ }
~PosixWriteableFile() {
if (fd_ >= 0) {
PosixWriteableFile::Close();
}
}
virtual Status Append(const Slice& data) {
Status s;
int ret;
ret = write(fd_, data.data(), data.size());
if (ret < 0) {
s = IOError(filename_, errno);
} else if (ret < data.size()) {
s = Status::IOError(filename_, "short write");
}
return s;
}
virtual Status Close() {
Status s;
if (close(fd_) < 0) {
s = IOError(filename_, errno);
}
fd_ = -1;
return s;
}
virtual Status Flush() {
return Status::OK();
}
Status SyncDirIfManifest() {
const char* f = filename_.c_str();
const char* sep = strrchr(f, '/');
Slice basename;
std::string dir;
if (sep == NULL) {
dir = ".";
basename = f;
} else {
dir = std::string(f, sep - f);
basename = sep + 1;
}
Status s;
if (basename.starts_with("MANIFEST")) {
int fd = open(dir.c_str(), O_RDONLY);
if (fd < 0) {
s = IOError(dir, errno);
} else {
if (fsync(fd) < 0) {
s = IOError(dir, errno);
}
close(fd);
}
}
return s;
}
virtual Status Sync() {
// Ensure new files referred to by the manifest are in the filesystem.
Status s = SyncDirIfManifest();
if (!s.ok()) {
return s;
}
if (fdatasync(fd_) < 0) {
s = IOError(filename_, errno);
}
return s;
}
};
#endif
static int LockOrUnlock(int fd, bool lock) {
errno = 0;
struct flock f;
@@ -386,7 +504,7 @@ class PosixEnv : public Env {
PosixEnv();
virtual ~PosixEnv() {
fprintf(stderr, "Destroying Env::Default()\n");
exit(1);
abort();
}
virtual Status NewSequentialFile(const std::string& fname,
@@ -408,6 +526,7 @@ class PosixEnv : public Env {
int fd = open(fname.c_str(), O_RDONLY);
if (fd < 0) {
s = IOError(fname, errno);
#if !defined(OS_MACOSX)
} else if (mmap_limit_.Acquire()) {
uint64_t size;
s = GetFileSize(fname, &size);
@@ -423,6 +542,7 @@ class PosixEnv : public Env {
if (!s.ok()) {
mmap_limit_.Release();
}
#endif
} else {
*result = new PosixRandomAccessFile(fname, fd);
}
@@ -437,7 +557,11 @@ class PosixEnv : public Env {
*result = NULL;
s = IOError(fname, errno);
} else {
#if defined(OS_MACOSX)
*result = new PosixWriteableFile(fname, fd);
#else
*result = new PosixMmapFile(fname, fd, page_size_);
#endif
}
return s;
}
@@ -467,7 +591,7 @@ class PosixEnv : public Env {
result = IOError(fname, errno);
}
return result;
};
}
virtual Status CreateDir(const std::string& name) {
Status result;
@@ -475,7 +599,7 @@ class PosixEnv : public Env {
result = IOError(name, errno);
}
return result;
};
}
virtual Status DeleteDir(const std::string& name) {
Status result;
@@ -483,7 +607,7 @@ class PosixEnv : public Env {
result = IOError(name, errno);
}
return result;
};
}
virtual Status GetFileSize(const std::string& fname, uint64_t* size) {
Status s;
@@ -589,7 +713,7 @@ class PosixEnv : public Env {
void PthreadCall(const char* label, int result) {
if (result != 0) {
fprintf(stderr, "pthread %s: %s\n", label, strerror(result));
exit(1);
abort();
}
}

View File

@@ -6,6 +6,13 @@
#include "util/coding.h"
#include "util/hash.h"
// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through
// between switch labels. The real definition should be provided externally.
// This one is a fallback version for unsupported compilers.
#ifndef FALLTHROUGH_INTENDED
#define FALLTHROUGH_INTENDED do { } while (0)
#endif
namespace leveldb {
uint32_t Hash(const char* data, size_t n, uint32_t seed) {
@@ -28,10 +35,10 @@ uint32_t Hash(const char* data, size_t n, uint32_t seed) {
switch (limit - data) {
case 3:
h += data[2] << 16;
// fall through
FALLTHROUGH_INTENDED;
case 2:
h += data[1] << 8;
// fall through
FALLTHROUGH_INTENDED;
case 1:
h += data[0];
h *= m;

View File

@@ -16,7 +16,12 @@ class Random {
private:
uint32_t seed_;
public:
explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) { }
explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) {
// Avoid bad seeds.
if (seed_ == 0 || seed_ == 2147483647L) {
seed_ = 1;
}
}
uint32_t Next() {
static const uint32_t M = 2147483647L; // 2^31-1
static const uint64_t A = 16807; // bits 14, 8, 7, 5, 2, 1, 0

View File

@@ -58,8 +58,8 @@ CMedianFilter<int> cPeerBlockCounts(8, 0); // Amount of blocks that other nodes
map<uint256, CBlock*> mapOrphanBlocks;
multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
map<uint256, CDataStream*> mapOrphanTransactions;
map<uint256, map<uint256, CDataStream*> > mapOrphanTransactionsByPrev;
map<uint256, CTransaction> mapOrphanTransactions;
map<uint256, set<uint256> > mapOrphanTransactionsByPrev;
// Constant stuff for coinbase transactions we create:
CScript COINBASE_FLAGS;
@@ -283,16 +283,12 @@ CBlockTreeDB *pblocktree = NULL;
// mapOrphanTransactions
//
bool AddOrphanTx(const CDataStream& vMsg)
bool AddOrphanTx(const CTransaction& tx)
{
CTransaction tx;
CDataStream(vMsg) >> tx;
uint256 hash = tx.GetHash();
if (mapOrphanTransactions.count(hash))
return false;
CDataStream* pvMsg = new CDataStream(vMsg);
// Ignore big transactions, to avoid a
// send-big-orphans memory exhaustion attack. If a peer has a legitimate
// large transaction with a missing parent then we assume
@@ -300,16 +296,16 @@ bool AddOrphanTx(const CDataStream& vMsg)
// have been mined or received.
// 10,000 orphans, each of which is at most 5,000 bytes big is
// at most 500 megabytes of orphans:
if (pvMsg->size() > 5000)
unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
if (sz > 5000)
{
printf("ignoring large orphan tx (size: %"PRIszu", hash: %s)\n", pvMsg->size(), hash.ToString().c_str());
delete pvMsg;
printf("ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString().c_str());
return false;
}
mapOrphanTransactions[hash] = pvMsg;
mapOrphanTransactions[hash] = tx;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
mapOrphanTransactionsByPrev[txin.prevout.hash].insert(make_pair(hash, pvMsg));
mapOrphanTransactionsByPrev[txin.prevout.hash].insert(hash);
printf("stored orphan tx %s (mapsz %"PRIszu")\n", hash.ToString().c_str(),
mapOrphanTransactions.size());
@@ -320,16 +316,13 @@ void static EraseOrphanTx(uint256 hash)
{
if (!mapOrphanTransactions.count(hash))
return;
const CDataStream* pvMsg = mapOrphanTransactions[hash];
CTransaction tx;
CDataStream(*pvMsg) >> tx;
const CTransaction& tx = mapOrphanTransactions[hash];
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
mapOrphanTransactionsByPrev[txin.prevout.hash].erase(hash);
if (mapOrphanTransactionsByPrev[txin.prevout.hash].empty())
mapOrphanTransactionsByPrev.erase(txin.prevout.hash);
}
delete pvMsg;
mapOrphanTransactions.erase(hash);
}
@@ -340,7 +333,7 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
{
// Evict a random orphan:
uint256 randomhash = GetRandHash();
map<uint256, CDataStream*>::iterator it = mapOrphanTransactions.lower_bound(randomhash);
map<uint256, CTransaction>::iterator it = mapOrphanTransactions.lower_bound(randomhash);
if (it == mapOrphanTransactions.end())
it = mapOrphanTransactions.begin();
EraseOrphanTx(it->first);
@@ -366,44 +359,58 @@ bool CTxOut::IsDust() const
// which has units satoshis-per-kilobyte.
// If you'd pay more than 1/3 in fees
// to spend something, then we consider it dust.
// A typical txout is 33 bytes big, and will
// A typical txout is 34 bytes big, and will
// need a CTxIn of at least 148 bytes to spend,
// so dust is a txout less than 54 uBTC
// (5430 satoshis) with default nMinRelayTxFee
// (5460 satoshis) with default nMinRelayTxFee
return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0)+148)) < CTransaction::nMinRelayTxFee);
}
bool CTransaction::IsStandard() const
bool CTransaction::IsStandard(string& strReason) const
{
if (nVersion > CTransaction::CURRENT_VERSION)
if (nVersion > CTransaction::CURRENT_VERSION || nVersion < 1) {
strReason = "version";
return false;
}
if (!IsFinal())
if (!IsFinal()) {
strReason = "not-final";
return false;
}
// Extremely large transactions with lots of inputs can cost the network
// almost as much to process as they cost the sender in fees, because
// computing signature hashes is O(ninputs*txsize). Limiting transactions
// to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
unsigned int sz = this->GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
if (sz >= MAX_STANDARD_TX_SIZE)
if (sz >= MAX_STANDARD_TX_SIZE) {
strReason = "tx-size";
return false;
}
BOOST_FOREACH(const CTxIn& txin, vin)
{
// Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
// pay-to-script-hash, which is 3 ~80-byte signatures, 3
// ~65-byte public keys, plus a few script ops.
if (txin.scriptSig.size() > 500)
if (txin.scriptSig.size() > 500) {
strReason = "scriptsig-size";
return false;
if (!txin.scriptSig.IsPushOnly())
}
if (!txin.scriptSig.IsPushOnly()) {
strReason = "scriptsig-not-pushonly";
return false;
}
}
BOOST_FOREACH(const CTxOut& txout, vout) {
if (!::IsStandard(txout.scriptPubKey))
if (!::IsStandard(txout.scriptPubKey)) {
strReason = "scriptpubkey";
return false;
if (txout.IsDust())
}
if (txout.IsDust()) {
strReason = "dust";
return false;
}
}
return true;
}
@@ -601,23 +608,20 @@ int64 CTransaction::GetMinFee(unsigned int nBlockSize, bool fAllowFree,
if (fAllowFree)
{
if (nBlockSize == 1)
{
// Transactions under 10K are free
// (about 4500 BTC if made of 50 BTC inputs)
if (nBytes < 10000)
nMinFee = 0;
}
else
{
// Free transaction area
if (nNewBlockSize < 27000)
nMinFee = 0;
}
// There is a free transaction area in blocks created by most miners,
// * If we are relaying we allow transactions up to DEFAULT_BLOCK_PRIORITY_SIZE - 1000
// to be considered to fall into this category. We don't want to encourage sending
// multiple transactions instead of one big transaction to avoid fees.
// * If we are creating a transaction we allow transactions up to 1,000 bytes
// to be considered safe and assume they can likely make it into this section.
if (nBytes < (mode == GMF_SEND ? 1000 : (DEFAULT_BLOCK_PRIORITY_SIZE - 1000)))
nMinFee = 0;
}
// To limit dust spam, require base fee if any output is less than 0.01
if (nMinFee < nBaseFee)
// This code can be removed after enough miners have upgraded to version 0.9.
// Until then, be safe when sending and require a fee if any output
// is less than CENT:
if (nMinFee < nBaseFee && mode == GMF_SEND)
{
BOOST_FOREACH(const CTxOut& txout, vout)
if (txout.nValue < CENT)
@@ -668,8 +672,10 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
return error("CTxMemPool::accept() : not accepting nLockTime beyond 2038 yet");
// Rather not work on nonstandard transactions (unless -testnet)
if (!fTestNet && !tx.IsStandard())
return error("CTxMemPool::accept() : nonstandard transaction type");
string strNonStd;
if (!fTestNet && !tx.IsStandard(strNonStd))
return error("CTxMemPool::accept() : nonstandard transaction (%s)",
strNonStd.c_str());
// is it already in the memory pool?
uint256 hash = tx.GetHash();
@@ -786,7 +792,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
if (!tx.CheckInputs(state, view, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC))
if (!tx.CheckInputs(state, view, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC | SCRIPT_VERIFY_DERSIG))
{
return error("CTxMemPool::accept() : ConnectInputs failed %s", hash.ToString().c_str());
}
@@ -809,9 +815,6 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
EraseFromWallets(ptxOld->GetHash());
SyncWithWallets(hash, tx, NULL, true);
printf("CTxMemPool::accept() : accepted %s (poolsz %"PRIszu")\n",
hash.ToString().c_str(),
mapTx.size());
return true;
}
@@ -824,7 +827,7 @@ bool CTransaction::AcceptToMemoryPool(CValidationState &state, bool fCheckInputs
}
}
bool CTxMemPool::addUnchecked(const uint256& hash, CTransaction &tx)
bool CTxMemPool::addUnchecked(const uint256& hash, const CTransaction &tx)
{
// Add to memory pool without checking anything. Don't call this directly,
// call CTxMemPool::accept to properly check the transaction first.
@@ -844,15 +847,15 @@ bool CTxMemPool::remove(const CTransaction &tx, bool fRecursive)
{
LOCK(cs);
uint256 hash = tx.GetHash();
if (fRecursive) {
for (unsigned int i = 0; i < tx.vout.size(); i++) {
std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(hash, i));
if (it != mapNextTx.end())
remove(*it->second.ptx, true);
}
}
if (mapTx.count(hash))
{
if (fRecursive) {
for (unsigned int i = 0; i < tx.vout.size(); i++) {
std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(hash, i));
if (it != mapNextTx.end())
remove(*it->second.ptx, true);
}
}
BOOST_FOREACH(const CTxIn& txin, tx.vin)
mapNextTx.erase(txin.prevout);
mapTx.erase(hash);
@@ -1506,6 +1509,11 @@ bool CBlock::DisconnectBlock(CValidationState &state, CBlockIndex *pindex, CCoin
CCoins &outs = view.GetCoins(hash);
CCoins outsBlock = CCoins(tx, pindex->nHeight);
// The CCoins serialization does not serialize negative numbers.
// No network rules currently depend on the version here, so an inconsistency is harmless
// but it must be corrected before txout nversion ever influences a network rule.
if (outsBlock.nVersion < 0)
outs.nVersion = outsBlock.nVersion;
if (outs != outsBlock)
fClean = fClean && error("DisconnectBlock() : added transaction mismatch? database corrupted");
@@ -1637,6 +1645,12 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
unsigned int flags = SCRIPT_VERIFY_NOCACHE |
(fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE);
if (nVersion >= 3 &&
((!fTestNet && CBlockIndex::IsSuperMajority(3, pindex->pprev, 750, 1000)) ||
(fTestNet && CBlockIndex::IsSuperMajority(3, pindex->pprev, 51, 100)))) {
flags |= SCRIPT_VERIFY_DERSIG;
}
CBlockUndo blockundo;
CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
@@ -1778,7 +1792,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
}
// Disconnect shorter branch
vector<CTransaction> vResurrect;
list<CTransaction> vResurrect;
BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) {
CBlock block;
if (!block.ReadFromDisk(pindex))
@@ -1792,9 +1806,9 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
// Queue memory transactions to resurrect.
// We only do this for blocks after the last checkpoint (reorganisation before that
// point should only happen with -reindex/-loadblock, or a misbehaving peer.
BOOST_FOREACH(const CTransaction& tx, block.vtx)
BOOST_REVERSE_FOREACH(const CTransaction& tx, block.vtx)
if (!tx.IsCoinBase() && pindex->nHeight > Checkpoints::GetTotalBlocksEstimate())
vResurrect.push_back(tx);
vResurrect.push_front(tx);
}
// Connect longer branch
@@ -1860,7 +1874,8 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
BOOST_FOREACH(CTransaction& tx, vResurrect) {
// ignore validation errors in resurrected transactions
CValidationState stateDummy;
tx.AcceptToMemoryPool(stateDummy, true, false);
if (!tx.AcceptToMemoryPool(stateDummy, true, false))
mempool.remove(tx, true);
}
// Delete redundant memory transactions that are in the connected branch
@@ -2124,7 +2139,7 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
uniqueTx.insert(GetTxHash(i));
}
if (uniqueTx.size() != vtx.size())
return state.DoS(100, error("CheckBlock() : duplicate transaction"));
return state.DoS(100, error("CheckBlock() : duplicate transaction"), true);
unsigned int nSigOps = 0;
BOOST_FOREACH(const CTransaction& tx, vtx)
@@ -2184,6 +2199,15 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"));
}
}
// Reject block.nVersion=2 blocks when 95% (75% on testnet) of the network has upgraded:
if (nVersion < 3)
{
if ((!fTestNet && CBlockIndex::IsSuperMajority(3, pindexPrev, 950, 1000)) ||
(fTestNet && CBlockIndex::IsSuperMajority(3, pindexPrev, 75, 100)))
{
return state.Invalid(error("AcceptBlock() : rejected nVersion=2 block"));
}
}
// Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
if (nVersion >= 2)
{
@@ -2192,7 +2216,8 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
(fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 51, 100)))
{
CScript expect = CScript() << nHeight;
if (!std::equal(expect.begin(), expect.end(), vtx[0].vin[0].scriptSig.begin()))
if (vtx[0].vin[0].scriptSig.size() < expect.size() ||
!std::equal(expect.begin(), expect.end(), vtx[0].vin[0].scriptSig.begin()))
return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"));
}
}
@@ -2714,7 +2739,7 @@ bool LoadBlockIndex()
pchMessageStart[1] = 0x11;
pchMessageStart[2] = 0x09;
pchMessageStart[3] = 0x07;
hashGenesisBlock = uint256("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943");
hashGenesisBlock = uint256("0x000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943");
}
//
@@ -3141,6 +3166,9 @@ void static ProcessGetData(CNode* pfrom)
// Track requests for our stuff.
Inventory(inv.hash);
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
break;
}
}
@@ -3200,8 +3228,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->nVersion = 300;
if (!vRecv.empty())
vRecv >> addrFrom >> nNonce;
if (!vRecv.empty())
if (!vRecv.empty()) {
vRecv >> pfrom->strSubVer;
pfrom->cleanSubVer = SanitizeString(pfrom->strSubVer);
}
if (!vRecv.empty())
vRecv >> pfrom->nStartingHeight;
if (!vRecv.empty())
@@ -3269,7 +3299,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->fSuccessfullyConnected = true;
printf("receive version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString().c_str(), addrFrom.ToString().c_str(), pfrom->addr.ToString().c_str());
printf("receive version message: %s: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", pfrom->cleanSubVer.c_str(), pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString().c_str(), addrFrom.ToString().c_str(), pfrom->addr.ToString().c_str());
cPeerBlockCounts.input(pfrom->nStartingHeight);
}
@@ -3512,40 +3542,45 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CValidationState state;
if (tx.AcceptToMemoryPool(state, true, true, &fMissingInputs))
{
RelayTransaction(tx, inv.hash, vMsg);
RelayTransaction(tx, inv.hash);
mapAlreadyAskedFor.erase(inv);
vWorkQueue.push_back(inv.hash);
vEraseQueue.push_back(inv.hash);
printf("AcceptToMemoryPool: %s %s : accepted %s (poolsz %"PRIszu")\n",
pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
tx.GetHash().ToString().c_str(),
mempool.mapTx.size());
// Recursively process any orphan transactions that depended on this one
for (unsigned int i = 0; i < vWorkQueue.size(); i++)
{
uint256 hashPrev = vWorkQueue[i];
for (map<uint256, CDataStream*>::iterator mi = mapOrphanTransactionsByPrev[hashPrev].begin();
for (set<uint256>::iterator mi = mapOrphanTransactionsByPrev[hashPrev].begin();
mi != mapOrphanTransactionsByPrev[hashPrev].end();
++mi)
{
const CDataStream& vMsg = *((*mi).second);
CTransaction tx;
CDataStream(vMsg) >> tx;
CInv inv(MSG_TX, tx.GetHash());
const uint256& orphanHash = *mi;
const CTransaction& orphanTx = mapOrphanTransactions[orphanHash];
bool fMissingInputs2 = false;
// Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan resolution (that is, feeding people an invalid transaction based on LegitTxX in order to get anyone relaying LegitTxX banned)
// Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan
// resolution (that is, feeding people an invalid transaction based on LegitTxX in order to get
// anyone relaying LegitTxX banned)
CValidationState stateDummy;
if (tx.AcceptToMemoryPool(stateDummy, true, true, &fMissingInputs2))
{
printf(" accepted orphan tx %s\n", inv.hash.ToString().c_str());
RelayTransaction(tx, inv.hash, vMsg);
mapAlreadyAskedFor.erase(inv);
vWorkQueue.push_back(inv.hash);
vEraseQueue.push_back(inv.hash);
printf(" accepted orphan tx %s\n", orphanHash.ToString().c_str());
RelayTransaction(orphanTx, orphanHash);
mapAlreadyAskedFor.erase(CInv(MSG_TX, orphanHash));
vWorkQueue.push_back(orphanHash);
vEraseQueue.push_back(orphanHash);
}
else if (!fMissingInputs2)
{
// invalid or too-little-fee orphan
vEraseQueue.push_back(inv.hash);
printf(" removed orphan tx %s\n", inv.hash.ToString().c_str());
vEraseQueue.push_back(orphanHash);
printf(" removed orphan tx %s\n", orphanHash.ToString().c_str());
}
}
}
@@ -3555,16 +3590,21 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
}
else if (fMissingInputs)
{
AddOrphanTx(vMsg);
AddOrphanTx(tx);
// DoS prevention: do not allow mapOrphanTransactions to grow unbounded
unsigned int nEvicted = LimitOrphanTxSize(MAX_ORPHAN_TRANSACTIONS);
if (nEvicted > 0)
printf("mapOrphan overflow, removed %u tx\n", nEvicted);
}
int nDoS;
int nDoS = 0;
if (state.IsInvalid(nDoS))
pfrom->Misbehaving(nDoS);
{
printf("%s from %s %s was not accepted into the memory pool\n", tx.GetHash().ToString().c_str(),
pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str());
if (nDoS > 0)
pfrom->Misbehaving(nDoS);
}
}
@@ -3580,11 +3620,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->AddInventoryKnown(inv);
CValidationState state;
if (ProcessBlock(state, pfrom, &block))
if (ProcessBlock(state, pfrom, &block) || state.CorruptionPossible())
mapAlreadyAskedFor.erase(inv);
int nDoS;
int nDoS = 0;
if (state.IsInvalid(nDoS))
pfrom->Misbehaving(nDoS);
if (nDoS > 0)
pfrom->Misbehaving(nDoS);
}
@@ -3682,6 +3723,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
LOCK(pfrom->cs_filter);
delete pfrom->pfilter;
pfrom->pfilter = new CBloomFilter(filter);
pfrom->pfilter->UpdateEmptyFull();
}
pfrom->fRelayTxes = true;
}
@@ -3711,7 +3753,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
LOCK(pfrom->cs_filter);
delete pfrom->pfilter;
pfrom->pfilter = NULL;
pfrom->pfilter = new CBloomFilter();
pfrom->fRelayTxes = true;
}
@@ -3750,6 +3792,9 @@ bool ProcessMessages(CNode* pfrom)
if (!pfrom->vRecvGetData.empty())
ProcessGetData(pfrom);
// this maintains the order of responses
if (!pfrom->vRecvGetData.empty()) return fOk;
std::deque<CNetMessage>::iterator it = pfrom->vRecvMsg.begin();
while (!pfrom->fDisconnect && it != pfrom->vRecvMsg.end()) {
// Don't bother if send buffer is too full to respond anyway
@@ -3840,6 +3885,8 @@ bool ProcessMessages(CNode* pfrom)
if (!fRet)
printf("ProcessMessage(%s, %u bytes) FAILED\n", strCommand.c_str(), nMessageSize);
break;
}
// In case the connection got shut down, its receive buffer was wiped
@@ -4184,7 +4231,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
pblocktemplate->vTxSigOps.push_back(-1); // updated at end
// Largest block you're willing to create:
unsigned int nBlockMaxSize = GetArg("-blockmaxsize", MAX_BLOCK_SIZE_GEN/2);
unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
// Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
@@ -4194,7 +4241,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
// How much of the block should be dedicated to high-priority transactions,
// included regardless of the fees they pay
unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", 27000);
unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE);
nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
// Minimum block size you want to create; block will be filled with free transactions
@@ -4741,9 +4788,6 @@ public:
mapOrphanBlocks.clear();
// orphan transactions
std::map<uint256, CDataStream*>::iterator it3 = mapOrphanTransactions.begin();
for (; it3 != mapOrphanTransactions.end(); it3++)
delete (*it3).second;
mapOrphanTransactions.clear();
}
} instance_of_cmaincleanup;

View File

@@ -26,10 +26,14 @@ struct CBlockIndexWorkComparator;
/** The maximum allowed size for a serialized block, in bytes (network rule) */
static const unsigned int MAX_BLOCK_SIZE = 1000000;
/** The maximum size for mined blocks */
/** Obsolete: maximum size for mined blocks */
static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
/** Default for -blockmaxsize, maximum size for mined blocks **/
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 350000;
/** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/
static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 30000;
/** The maximum size for transactions we're willing to relay/mine */
static const unsigned int MAX_STANDARD_TX_SIZE = MAX_BLOCK_SIZE_GEN/5;
static const unsigned int MAX_STANDARD_TX_SIZE = 100000;
/** The maximum allowed number of signature check operations in a block (network rule) */
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
/** The maximum number of orphan transactions kept in memory */
@@ -559,7 +563,12 @@ public:
/** Check for standard transaction types
@return True if all outputs (scriptPubKeys) use only standard transaction forms
*/
bool IsStandard() const;
bool IsStandard(std::string& strReason) const;
bool IsStandard() const
{
std::string strReason;
return IsStandard(strReason);
}
/** Check for standard transaction types
@param[in] mapInputs Map of previous transactions that have outputs we're spending
@@ -1259,7 +1268,7 @@ class CBlockHeader
{
public:
// header
static const int CURRENT_VERSION=2;
static const int CURRENT_VERSION=3;
int nVersion;
uint256 hashPrevBlock;
uint256 hashMerkleRoot;
@@ -1881,13 +1890,15 @@ private:
MODE_ERROR, // run-time error
} mode;
int nDoS;
bool corruptionPossible;
public:
CValidationState() : mode(MODE_VALID), nDoS(0) {}
bool DoS(int level, bool ret = false) {
CValidationState() : mode(MODE_VALID), nDoS(0), corruptionPossible(false) {}
bool DoS(int level, bool ret = false, bool corruptionIn = false) {
if (mode == MODE_ERROR)
return ret;
nDoS += level;
mode = MODE_INVALID;
corruptionPossible = corruptionIn;
return ret;
}
bool Invalid(bool ret = false) {
@@ -1917,6 +1928,9 @@ public:
}
return false;
}
bool CorruptionPossible() {
return corruptionPossible;
}
};
@@ -2067,7 +2081,7 @@ public:
std::map<COutPoint, CInPoint> mapNextTx;
bool accept(CValidationState &state, CTransaction &tx, bool fCheckInputs, bool fLimitFree, bool* pfMissingInputs);
bool addUnchecked(const uint256& hash, CTransaction &tx);
bool addUnchecked(const uint256& hash, const CTransaction &tx);
bool remove(const CTransaction &tx, bool fRecursive = false);
bool removeConflicts(const CTransaction &tx);
void clear();

View File

@@ -43,7 +43,7 @@ LIBS= \
-l ssl \
-l crypto
DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE
DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE
DEBUGFLAGS=-g
CFLAGS=-mthreads -O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
# enable: ASLR, DEP and large address aware
@@ -63,7 +63,7 @@ ifneq (${USE_IPV6}, -)
DEFS += -DUSE_IPV6=$(USE_IPV6)
endif
LIBS += -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi
LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi
# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are
HEADERS = $(wildcard *.h)

View File

@@ -21,6 +21,9 @@
#include <miniupnpc/upnperrors.h>
#endif
// Dump addresses to peers.dat every 15 minutes (900s)
#define DUMP_ADDRESSES_INTERVAL 900
using namespace std;
using namespace boost;
@@ -609,7 +612,7 @@ void CNode::copyStats(CNodeStats &stats)
X(nTimeConnected);
X(addrName);
X(nVersion);
X(strSubVer);
X(cleanSubVer);
X(fInbound);
X(nStartingHeight);
X(nMisbehavior);
@@ -1626,6 +1629,9 @@ void ThreadMessageHandler()
CNode* pnodeTrickle = NULL;
if (!vNodesCopy.empty())
pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
bool fSleep = true;
BOOST_FOREACH(CNode* pnode, vNodesCopy)
{
if (pnode->fDisconnect)
@@ -1635,8 +1641,18 @@ void ThreadMessageHandler()
{
TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
if (lockRecv)
{
if (!ProcessMessages(pnode))
pnode->CloseSocketDisconnect();
if (pnode->nSendSize < SendBufferSize())
{
if (!pnode->vRecvGetData.empty() || (!pnode->vRecvMsg.empty() && pnode->vRecvMsg[0].complete()))
{
fSleep = false;
}
}
}
}
boost::this_thread::interruption_point();
@@ -1655,7 +1671,8 @@ void ThreadMessageHandler()
pnode->Release();
}
MilliSleep(100);
if (fSleep)
MilliSleep(100);
}
}
@@ -1720,8 +1737,12 @@ bool BindListenPort(const CService &addrBind, string& strError)
// and enable it by default or not. Try to enable it, if possible.
if (addrBind.IsIPv6()) {
#ifdef IPV6_V6ONLY
#ifdef WIN32
setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
#else
setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
#endif
#endif
#ifdef WIN32
int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
@@ -1855,7 +1876,7 @@ void StartNode(boost::thread_group& threadGroup)
threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "msghand", &ThreadMessageHandler));
// Dump network addresses
threadGroup.create_thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 10000));
threadGroup.create_thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, DUMP_ADDRESSES_INTERVAL * 1000));
}
bool StopNode()

View File

@@ -98,7 +98,7 @@ public:
int64 nTimeConnected;
std::string addrName;
int nVersion;
std::string strSubVer;
std::string cleanSubVer;
bool fInbound;
int nStartingHeight;
int nMisbehavior;
@@ -177,7 +177,11 @@ public:
std::string addrName;
CService addrLocal;
int nVersion;
std::string strSubVer;
// strSubVer is whatever byte array we read from the wire. However, this field is intended
// to be printed out, displayed to humans in various forms and so on. So we sanitize it and
// store the sanitized version in cleanSubVer. The original should be used when dealing with
// the network or wire types and the cleaned string used when displayed or logged.
std::string strSubVer, cleanSubVer;
bool fOneShot;
bool fClient;
bool fInbound;
@@ -253,7 +257,7 @@ public:
nMisbehavior = 0;
fRelayTxes = false;
setInventoryKnown.max_size(SendBufferSize() / 1000);
pfilter = NULL;
pfilter = new CBloomFilter();
// Be shy and don't send version until we hear
if (hSocket != INVALID_SOCKET && !fInbound)

View File

@@ -860,7 +860,7 @@ std::vector<unsigned char> CNetAddr::GetGroup() const
nBits = 4;
}
// for he.net, use /36 groups
else if (GetByte(15) == 0x20 && GetByte(14) == 0x11 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
nBits = 36;
// for the rest of the IPv6 network, use /32 groups
else

View File

@@ -3,8 +3,8 @@
#include <QValidator>
/** Base48 entry widget validator.
Corrects near-miss characters and refuses characters that are no part of base48.
/** Base58 entry widget validator.
Corrects near-miss characters and refuses characters that are not part of base58.
*/
class BitcoinAddressValidator : public QValidator
{

View File

@@ -52,6 +52,8 @@ MacDockIconHandler::MacDockIconHandler() : QObject()
this->m_dummyWidget = new QWidget();
this->m_dockMenu = new QMenu(this->m_dummyWidget);
qt_mac_set_dock_menu(this->m_dockMenu);
this->setMainWindow(NULL);
[pool release];
}
@@ -100,8 +102,11 @@ MacDockIconHandler *MacDockIconHandler::instance()
void MacDockIconHandler::handleDockIconClickEvent()
{
this->mainWindow->activateWindow();
this->mainWindow->show();
if (this->mainWindow)
{
this->mainWindow->activateWindow();
this->mainWindow->show();
}
emit this->dockIconClicked();
}

View File

@@ -170,7 +170,7 @@ void SendCoinsDialog::clear()
// Remove entries until only one left
while(ui->entries->count())
{
delete ui->entries->takeAt(0)->widget();
ui->entries->takeAt(0)->widget()->deleteLater();
}
addEntry();
@@ -226,7 +226,7 @@ void SendCoinsDialog::updateRemoveEnabled()
void SendCoinsDialog::removeEntry(SendCoinsEntry* entry)
{
delete entry;
entry->deleteLater();
updateRemoveEnabled();
}

View File

@@ -13,6 +13,7 @@
WalletStack::WalletStack(QWidget *parent) :
QStackedWidget(parent),
gui(0),
clientModel(0),
bOutOfSync(true)
{
@@ -35,6 +36,10 @@ bool WalletStack::addWallet(const QString& name, WalletModel *walletModel)
walletView->showOutOfSyncWarning(bOutOfSync);
addWidget(walletView);
mapWalletViews[name] = walletView;
// Ensure a walletView is able to show the main window
connect(walletView, SIGNAL(showNormalIfMinimized()), gui, SLOT(showNormalIfMinimized()));
return true;
}

View File

@@ -203,6 +203,7 @@ bool WalletView::handleURI(const QString& strURI)
if (sendCoinsPage->handleURI(strURI))
{
gotoSendCoinsPage();
emit showNormalIfMinimized();
return true;
}
else

View File

@@ -99,6 +99,10 @@ public slots:
void unlockWallet();
void setEncryptionStatus();
signals:
/** Signal that we want to show the main window */
void showNormalIfMinimized();
};
#endif // WALLETVIEW_H

View File

@@ -55,7 +55,10 @@ Value getpeerinfo(const Array& params, bool fHelp)
obj.push_back(Pair("bytesrecv", (boost::int64_t)stats.nRecvBytes));
obj.push_back(Pair("conntime", (boost::int64_t)stats.nTimeConnected));
obj.push_back(Pair("version", stats.nVersion));
obj.push_back(Pair("subver", stats.strSubVer));
// Use the sanitized form of subver here, to avoid tricksy remote peers from
// corrupting or modifiying the JSON output by putting special characters in
// their ver message.
obj.push_back(Pair("subver", stats.cleanSubVer));
obj.push_back(Pair("inbound", stats.fInbound));
obj.push_back(Pair("startingheight", stats.nStartingHeight));
obj.push_back(Pair("banscore", stats.nMisbehavior));

View File

@@ -289,6 +289,86 @@ bool IsCanonicalSignature(const valtype &vchSig) {
return true;
}
// BIP 66 defined signature encoding check. This largely overlaps with
// IsCanonicalSignature above, but lacks hashtype constraints, and uses the
// exact implementation code from BIP 66.
bool static IsValidSignatureEncoding(const std::vector<unsigned char> &sig) {
// Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] [sighash]
// * total-length: 1-byte length descriptor of everything that follows,
// excluding the sighash byte.
// * R-length: 1-byte length descriptor of the R value that follows.
// * R: arbitrary-length big-endian encoded R value. It must use the shortest
// possible encoding for a positive integers (which means no null bytes at
// the start, except a single one when the next byte has its highest bit set).
// * S-length: 1-byte length descriptor of the S value that follows.
// * S: arbitrary-length big-endian encoded S value. The same rules apply.
// * sighash: 1-byte value indicating what data is hashed (not part of the DER
// signature)
// Minimum and maximum size constraints.
if (sig.size() < 9) return false;
if (sig.size() > 73) return false;
// A signature is of type 0x30 (compound).
if (sig[0] != 0x30) return false;
// Make sure the length covers the entire signature.
if (sig[1] != sig.size() - 3) return false;
// Extract the length of the R element.
unsigned int lenR = sig[3];
// Make sure the length of the S element is still inside the signature.
if (5 + lenR >= sig.size()) return false;
// Extract the length of the S element.
unsigned int lenS = sig[5 + lenR];
// Verify that the length of the signature matches the sum of the length
// of the elements.
if ((size_t)(lenR + lenS + 7) != sig.size()) return false;
// Check whether the R element is an integer.
if (sig[2] != 0x02) return false;
// Zero-length integers are not allowed for R.
if (lenR == 0) return false;
// Negative numbers are not allowed for R.
if (sig[4] & 0x80) return false;
// Null bytes at the start of R are not allowed, unless R would
// otherwise be interpreted as a negative number.
if (lenR > 1 && (sig[4] == 0x00) && !(sig[5] & 0x80)) return false;
// Check whether the S element is an integer.
if (sig[lenR + 4] != 0x02) return false;
// Zero-length integers are not allowed for S.
if (lenS == 0) return false;
// Negative numbers are not allowed for S.
if (sig[lenR + 6] & 0x80) return false;
// Null bytes at the start of S are not allowed, unless S would otherwise be
// interpreted as a negative number.
if (lenS > 1 && (sig[lenR + 6] == 0x00) && !(sig[lenR + 7] & 0x80)) return false;
return true;
}
bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags) {
// Empty signature. Not strictly DER encoded, but allowed to provide a
// compact way to provide an invalid signature for use with CHECK(MULTI)SIG
if (vchSig.size() == 0) {
return true;
}
if ((flags & SCRIPT_VERIFY_DERSIG) != 0 && !IsValidSignatureEncoding(vchSig)) {
return false;
}
return true;
}
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType)
{
CAutoBN_CTX pctx;
@@ -841,6 +921,10 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
// Drop the signature, since there's no way for a signature to sign itself
scriptCode.FindAndDelete(CScript(vchSig));
if (!CheckSignatureEncoding(vchSig, flags)) {
return false;
}
bool fSuccess = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey)));
if (fSuccess)
fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags);
@@ -902,6 +986,10 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
valtype& vchSig = stacktop(-isig);
valtype& vchPubKey = stacktop(-ikey);
if (!CheckSignatureEncoding(vchSig, flags)) {
return false;
}
// Check signature
bool fOk = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey)));
if (fOk)

View File

@@ -35,6 +35,7 @@ enum
SCRIPT_VERIFY_P2SH = (1U << 0),
SCRIPT_VERIFY_STRICTENC = (1U << 1),
SCRIPT_VERIFY_NOCACHE = (1U << 2),
SCRIPT_VERIFY_DERSIG = (1U << 3), // enforce signature encodings as defined by BIP 66 (which is a softfork, while STRICTENC is not)
};
enum txnouttype

View File

@@ -16,10 +16,10 @@
#include <stdint.h>
// Tests this internal-to-main.cpp method:
extern bool AddOrphanTx(const CDataStream& vMsg);
extern bool AddOrphanTx(const CTransaction& tx);
extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans);
extern std::map<uint256, CDataStream*> mapOrphanTransactions;
extern std::map<uint256, std::map<uint256, CDataStream*> > mapOrphanTransactionsByPrev;
extern std::map<uint256, CTransaction> mapOrphanTransactions;
extern std::map<uint256, std::set<uint256> > mapOrphanTransactionsByPrev;
CService ip(uint32_t i)
{
@@ -133,14 +133,11 @@ BOOST_AUTO_TEST_CASE(DoS_checknbits)
CTransaction RandomOrphan()
{
std::map<uint256, CDataStream*>::iterator it;
std::map<uint256, CTransaction>::iterator it;
it = mapOrphanTransactions.lower_bound(GetRandHash());
if (it == mapOrphanTransactions.end())
it = mapOrphanTransactions.begin();
const CDataStream* pvMsg = it->second;
CTransaction tx;
CDataStream(*pvMsg) >> tx;
return tx;
return it->second;
}
BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
@@ -162,9 +159,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
tx.vout[0].nValue = 1*CENT;
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
CDataStream ds(SER_DISK, CLIENT_VERSION);
ds << tx;
AddOrphanTx(ds);
AddOrphanTx(tx);
}
// ... and 50 that depend on other orphans:
@@ -181,9 +176,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
SignSignature(keystore, txPrev, tx, 0);
CDataStream ds(SER_DISK, CLIENT_VERSION);
ds << tx;
AddOrphanTx(ds);
AddOrphanTx(tx);
}
// This really-big orphan should be ignored:
@@ -207,9 +200,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
for (unsigned int j = 1; j < tx.vin.size(); j++)
tx.vin[j].scriptSig = tx.vin[0].scriptSig;
CDataStream ds(SER_DISK, CLIENT_VERSION);
ds << tx;
BOOST_CHECK(!AddOrphanTx(ds));
BOOST_CHECK(!AddOrphanTx(tx));
}
// Test LimitOrphanTxSize() function:
@@ -246,9 +237,7 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig)
tx.vout[0].nValue = 1*CENT;
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
CDataStream ds(SER_DISK, CLIENT_VERSION);
ds << tx;
AddOrphanTx(ds);
AddOrphanTx(tx);
}
// Create a transaction that depends on orphans:

View File

@@ -310,5 +310,45 @@
["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"],
["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "OP_RESERVED in P2SH should fail"],
["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "OP_VER in P2SH should fail"]
["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "OP_VER in P2SH should fail"],
["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "Overly long signature is incorrectly encoded for DERSIG"],
["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "Missing S is incorrectly encoded for DERSIG"],
["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "S with invalid S length is incorrectly encoded for DERSIG"],
["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Non-integer R is incorrectly encoded for DERSIG"],
["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Non-integer S is incorrectly encoded for DERSIG"],
["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Zero-length R is incorrectly encoded for DERSIG"],
["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "Zero-length S is incorrectly encoded for DERSIG"],
["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Negative S is incorrectly encoded for DERSIG"],
[
"0x47 0x30440220003040725f724b0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"DERSIG",
"P2PK NOT with bad sig with too much R padding"
],
[
"0x47 0x30440220003040725f724a0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"DERSIG",
"P2PK NOT with too much R padding"
],
[
"0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
"DERSIG",
"BIP66 example 2, with DERSIG"
],
[
"1",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
"DERSIG",
"BIP66 example 6, with DERSIG"
],
[
"0 0 0x47 0x30440220afa76a8f60622f813b05711f051c6c3407e32d1b1b70b0576c1f01b54e4c05c702200d58e9df044fd1845cabfbeef6e624ba0401daf7d7e084736f9ff601c3783bf501",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
"DERSIG",
"BIP66 example 10, with DERSIG"
]
]

View File

@@ -375,5 +375,65 @@
["NOP", "NOP10 1"],
["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Very basic P2SH"],
["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"]
["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"],
["0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242",
"0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL",
"Basic PUSH signedness check"],
["0x4c 0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242",
"0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL",
"Basic PUSHDATA1 signedness check"],
["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "Overly long signature is correctly encoded"],
["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "Missing S is correctly encoded"],
["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "", "S with invalid S length is correctly encoded"],
["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Non-integer R is correctly encoded"],
["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Non-integer S is correctly encoded"],
["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Zero-length R is correctly encoded"],
["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "Zero-length S is correctly encoded"],
["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Negative S is correctly encoded"],
[
"0x47 0x30440220003040725f724b0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"",
"P2PK NOT with bad sig with too much R padding but no DERSIG"
],
[
"0",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
"",
"BIP66 example 4, without DERSIG"
],
[
"0",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
"DERSIG",
"BIP66 example 4, with DERSIG"
],
[
"1",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
"",
"BIP66 example 6, without DERSIG"
],
[
"0 0 0x47 0x30440220afa76a8f60622f813b05711f051c6c3407e32d1b1b70b0576c1f01b54e4c05c702200d58e9df044fd1845cabfbeef6e624ba0401daf7d7e084736f9ff601c3783bf501",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
"",
"BIP66 example 10, without DERSIG"
],
[
"0 0x47 0x30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737db22601 0",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
"",
"BIP66 example 12, without DERSIG"
],
[
"0 0x47 0x30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737db22601 0",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
"DERSIG",
"BIP66 example 12, with DERSIG"
]
]

View File

@@ -142,8 +142,13 @@ BOOST_AUTO_TEST_CASE(script_valid)
string scriptPubKeyString = test[1].get_str();
CScript scriptPubKey = ParseScript(scriptPubKeyString);
int flagsNow = flags;
if (test.size() > 3 && ("," + test[2].get_str() + ",").find(",DERSIG,") != string::npos) {
flagsNow |= SCRIPT_VERIFY_DERSIG;
}
CTransaction tx;
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, tx, 0, flags, SIGHASH_NONE), strTest);
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, tx, 0, flagsNow, SIGHASH_NONE), strTest);
}
}
@@ -166,8 +171,13 @@ BOOST_AUTO_TEST_CASE(script_invalid)
string scriptPubKeyString = test[1].get_str();
CScript scriptPubKey = ParseScript(scriptPubKeyString);
int flagsNow = flags;
if (test.size() > 3 && ("," + test[2].get_str() + ",").find(",DERSIG,") != string::npos) {
flagsNow |= SCRIPT_VERIFY_DERSIG;
}
CTransaction tx;
BOOST_CHECK_MESSAGE(!VerifyScript(scriptSig, scriptPubKey, tx, 0, flags, SIGHASH_NONE), strTest);
BOOST_CHECK_MESSAGE(!VerifyScript(scriptSig, scriptPubKey, tx, 0, flagsNow, SIGHASH_NONE), strTest);
}
}

View File

@@ -263,28 +263,10 @@ BOOST_AUTO_TEST_CASE(util_IsHex)
BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
{
// Expected results for the determinstic seed.
const uint32_t exp_vals[11] = { 91632771U,1889679809U,3842137544U,3256031132U,
1761911779U, 489223532U,2692793790U,2737472863U,
2796262275U,1309899767U,840571781U};
// Expected 0s in rand()%(idx+2) for the determinstic seed.
const int exp_count[9] = {5013,3346,2415,1972,1644,1386,1176,1096,1009};
int i;
int count=0;
seed_insecure_rand();
//Does the non-determistic rand give us results that look too like the determinstic one?
for (i=0;i<10;i++)
{
int match = 0;
uint32_t rval = insecure_rand();
for (int j=0;j<11;j++)match |= rval==exp_vals[j];
count += match;
}
// sum(binomial(10,i)*(11/(2^32))^i*(1-(11/(2^32)))^(10-i),i,0,4) ~= 1-1/2^134.73
// So _very_ unlikely to throw a false failure here.
BOOST_CHECK(count<=4);
seed_insecure_rand(true);
for (int mod=2;mod<11;mod++)
{
@@ -307,20 +289,17 @@ BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
BOOST_CHECK(count<=10000/mod+err);
BOOST_CHECK(count>=10000/mod-err);
}
}
seed_insecure_rand(true);
for (i=0;i<11;i++)
{
BOOST_CHECK_EQUAL(insecure_rand(),exp_vals[i]);
}
for (int mod=2;mod<11;mod++)
{
count = 0;
for (i=0;i<10000;i++) count += insecure_rand()%mod==0;
BOOST_CHECK_EQUAL(count,exp_count[mod-2]);
}
BOOST_AUTO_TEST_CASE(util_TimingResistantEqual)
{
BOOST_CHECK(TimingResistantEqual(std::string(""), std::string("")));
BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("")));
BOOST_CHECK(!TimingResistantEqual(std::string(""), std::string("abc")));
BOOST_CHECK(!TimingResistantEqual(std::string("a"), std::string("aa")));
BOOST_CHECK(!TimingResistantEqual(std::string("aa"), std::string("a")));
BOOST_CHECK(TimingResistantEqual(std::string("abc"), std::string("abc")));
BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("aba")));
}
BOOST_AUTO_TEST_SUITE_END()

View File

@@ -454,6 +454,19 @@ bool ParseMoney(const char* pszIn, int64& nRet)
return true;
}
// safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything
// even possibly remotely dangerous like & or >
static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@");
string SanitizeString(const string& str)
{
string strResult;
for (std::string::size_type i = 0; i < str.size(); i++)
{
if (safeChars.find(str[i]) != std::string::npos)
strResult.push_back(str[i]);
}
return strResult;
}
static const signed char phexdigit[256] =
{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
@@ -1071,7 +1084,7 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific)
if (fNetSpecific && GetBoolArg("-testnet", false))
path /= "testnet3";
fs::create_directory(path);
fs::create_directories(path);
fCachedPath[fNetSpecific] = true;
return path;
@@ -1118,6 +1131,7 @@ boost::filesystem::path GetPidFile()
return pathPidFile;
}
#ifndef WIN32
void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
{
FILE* file = fopen(path.string().c_str(), "w");
@@ -1127,6 +1141,7 @@ void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
fclose(file);
}
}
#endif
bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
{
@@ -1147,6 +1162,8 @@ void FileCommit(FILE *fileout)
#else
#if defined(__linux__) || defined(__NetBSD__)
fdatasync(fileno(fileout));
#elif defined(__APPLE__) && defined(F_FULLFSYNC)
fcntl(fileno(fileout), F_FULLFSYNC, 0);
#else
fsync(fileno(fileout));
#endif

View File

@@ -22,6 +22,7 @@ typedef int pid_t; /* define for Windows compatibility */
#include <vector>
#include <string>
#include <boost/version.hpp>
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>
@@ -106,7 +107,11 @@ T* alignup(T* p)
inline void MilliSleep(int64 n)
{
#if BOOST_VERSION >= 105000
// Boost's sleep_for was uninterruptable when backed by nanosleep from 1.50
// until fixed in 1.52. Use the deprecated sleep method for the broken case.
// See: https://svn.boost.org/trac/boost/ticket/7238
#if BOOST_VERSION >= 105000 && (!defined(BOOST_HAS_NANOSLEEP) || BOOST_VERSION >= 105200)
boost::this_thread::sleep_for(boost::chrono::milliseconds(n));
#else
boost::this_thread::sleep(boost::posix_time::milliseconds(n));
@@ -182,6 +187,7 @@ void ParseString(const std::string& str, char c, std::vector<std::string>& v);
std::string FormatMoney(int64 n, bool fPlus=false);
bool ParseMoney(const std::string& str, int64& nRet);
bool ParseMoney(const char* pszIn, int64& nRet);
std::string SanitizeString(const std::string& str);
std::vector<unsigned char> ParseHex(const char* psz);
std::vector<unsigned char> ParseHex(const std::string& str);
bool IsHex(const std::string& str);
@@ -206,7 +212,9 @@ boost::filesystem::path GetDefaultDataDir();
const boost::filesystem::path &GetDataDir(bool fNetSpecific = true);
boost::filesystem::path GetConfigFile();
boost::filesystem::path GetPidFile();
#ifndef WIN32
void CreatePidFile(const boost::filesystem::path &path, pid_t pid);
#endif
void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet);
#ifdef WIN32
boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
@@ -433,6 +441,21 @@ static inline uint32_t insecure_rand(void)
*/
void seed_insecure_rand(bool fDeterministic=false);
/**
* Timing-attack-resistant comparison.
* Takes time proportional to length
* of first argument.
*/
template <typename T>
bool TimingResistantEqual(const T& a, const T& b)
{
if (b.size() == 0) return a.size() == 0;
size_t accumulator = a.size() ^ b.size();
for (size_t i = 0; i < a.size(); i++)
accumulator |= a[i] ^ b[i%b.size()];
return accumulator == 0;
}
/** Median filter over a stream of values.
* Returns the median of the last N numbers
*/
@@ -531,7 +554,7 @@ inline uint32_t ByteReverse(uint32_t value)
// Standard wrapper for do-something-forever thread functions.
// "Forever" really means until the thread is interrupted.
// Use it like:
// new boost::thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 10000));
// new boost::thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 900000));
// or maybe:
// boost::function<void()> f = boost::bind(&FunctionWithArg, argument);
// threadGroup.create_thread(boost::bind(&LoopForever<boost::function<void()> >, "nothing", f, milliseconds));
@@ -544,8 +567,8 @@ template <typename Callable> void LoopForever(const char* name, Callable func,
{
while (1)
{
func();
MilliSleep(msecs);
func();
}
}
catch (boost::thread_interrupted)

View File

@@ -36,7 +36,7 @@ const std::string CLIENT_NAME("Satoshi");
// git will put "#define GIT_ARCHIVE 1" on the next line inside archives. $Format:%n#define GIT_ARCHIVE 1$
#ifdef GIT_ARCHIVE
# define GIT_COMMIT_ID "$Format:%h$"
# define GIT_COMMIT_DATE "$Format:%cD"
# define GIT_COMMIT_DATE "$Format:%cD$"
#endif
#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \

View File

@@ -740,6 +740,10 @@ void CWalletTx::AddSupportingTransactions()
{
tx = *mapWalletPrev[hash];
}
else
{
continue;
}
int nDepth = tx.SetMerkleBranch();
vtxPrev.push_back(tx);
@@ -844,7 +848,10 @@ void CWalletTx::RelayWalletTransaction()
{
BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
{
if (!tx.IsCoinBase())
// Important: versions of bitcoin before 0.8.6 had a bug that inserted
// empty transactions into the vtxPrev, which will cause the node to be
// banned when retransmitted, hence the check for !tx.vin.empty()
if (!tx.IsCoinBase() && !tx.vin.empty())
if (tx.GetDepthInMainChain() == 0)
RelayTransaction((CTransaction)tx, tx.GetHash());
}
@@ -1204,9 +1211,10 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
}
int64 nChange = nValueIn - nValue - nFeeRet;
// if sub-cent change is required, the fee must be raised to at least nMinTxFee
// or until nChange becomes zero
// NOTE: this depends on the exact behaviour of GetMinFee
// The following if statement should be removed once enough miners
// have upgraded to the 0.9 GetMinFee() rules. Until then, this avoids
// creating free transactions that have change outputs less than
// CENT bitcoins.
if (nFeeRet < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT)
{
int64 nMoveToFee = min(nChange, CTransaction::nMinTxFee - nFeeRet);

View File

@@ -5,6 +5,7 @@
#include "walletdb.h"
#include "wallet.h"
#include <boost/version.hpp>
#include <boost/filesystem.hpp>
using namespace std;