diff --git a/src/Makefile.am b/src/Makefile.am
index 72d79619b..5349e18fc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,425 +1,427 @@
 DIST_SUBDIRS = secp256k1
 AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS)
 
 
 if EMBEDDED_LEVELDB
 LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include
 LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv
 LIBLEVELDB += $(builddir)/leveldb/libleveldb.a
 LIBMEMENV  += $(builddir)/leveldb/libmemenv.a
 
 # NOTE: This dependency is not strictly necessary, but without it make may try to build both in parallel, which breaks the LevelDB build system in a race
 $(LIBLEVELDB): $(LIBMEMENV)
 
 $(LIBLEVELDB) $(LIBMEMENV):
 	@echo "Building LevelDB ..." && $(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \
 	  CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \
           OPT="$(CXXFLAGS) $(CPPFLAGS)"
 endif
 
 BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config
 BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS)
 
 BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include
 
 LIBBITCOIN_SERVER=libbitcoin_server.a
 LIBBITCOIN_WALLET=libbitcoin_wallet.a
 LIBBITCOIN_COMMON=libbitcoin_common.a
 LIBBITCOIN_CLI=libbitcoin_cli.a
 LIBBITCOIN_UTIL=libbitcoin_util.a
 LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a
 LIBBITCOIN_UNIVALUE=univalue/libbitcoin_univalue.a
 LIBBITCOINQT=qt/libbitcoinqt.a
 LIBSECP256K1=secp256k1/libsecp256k1.la
 
 $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
 	$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F)
 
 # Make is not made aware of per-object dependencies to avoid limiting building parallelization
 # But to build the less dependent modules first, we manually select their order here:
 EXTRA_LIBRARIES = \
   crypto/libbitcoin_crypto.a \
   libbitcoin_util.a \
   libbitcoin_common.a \
   univalue/libbitcoin_univalue.a \
   libbitcoin_server.a \
   libbitcoin_cli.a
 if ENABLE_WALLET
 BITCOIN_INCLUDES += $(BDB_CPPFLAGS)
 EXTRA_LIBRARIES += libbitcoin_wallet.a
 endif
 
 if BUILD_BITCOIN_LIBS
 lib_LTLIBRARIES = libbitcoinconsensus.la
 LIBBITCOIN_CONSENSUS=libbitcoinconsensus.la
 else
 LIBBITCOIN_CONSENSUS=
 endif
 
 bin_PROGRAMS =
 TESTS =
 
 if BUILD_BITCOIND
   bin_PROGRAMS += bitcoind
 endif
 
 if BUILD_BITCOIN_UTILS
   bin_PROGRAMS += bitcoin-cli bitcoin-tx
 endif
 
 .PHONY: FORCE
 # bitcoin core #
 BITCOIN_CORE_H = \
   addrman.h \
   alert.h \
   amount.h \
   arith_uint256.h \
   base58.h \
   bloom.h \
   chain.h \
   chainparamsbase.h \
   chainparams.h \
   chainparamsseeds.h \
   checkpoints.h \
   checkqueue.h \
   clientversion.h \
   coincontrol.h \
   coins.h \
   compat.h \
   compressor.h \
   consensus/consensus.h \
   consensus/params.h \
   core_io.h \
   wallet/db.h \
   eccryptoverify.h \
   ecwrapper.h \
   hash.h \
   init.h \
   key.h \
   keystore.h \
   leveldbwrapper.h \
   limitedmap.h \
   main.h \
   merkleblock.h \
   miner.h \
   mruset.h \
   netbase.h \
   net.h \
   noui.h \
   pow.h \
   primitives/block.h \
   primitives/transaction.h \
   protocol.h \
   pubkey.h \
   random.h \
   rpcclient.h \
   rpcprotocol.h \
   rpcserver.h \
+  scheduler.h \
   script/interpreter.h \
   script/script_error.h \
   script/script.h \
   script/sigcache.h \
   script/sign.h \
   script/standard.h \
   serialize.h \
   streams.h \
   support/allocators/secure.h \
   support/allocators/zeroafterfree.h \
   support/cleanse.h \
   support/pagelocker.h \
   sync.h \
   threadsafety.h \
   timedata.h \
   tinyformat.h \
   txdb.h \
   txmempool.h \
   ui_interface.h \
   uint256.h \
   undo.h \
   util.h \
   utilmoneystr.h \
   utilstrencodings.h \
   utiltime.h \
   validationinterface.h \
   version.h \
   wallet/crypter.h \
   wallet/walletdb.h \
   wallet/wallet.h \
   wallet/wallet_ismine.h \
   compat/byteswap.h \
   compat/endian.h \
   compat/sanity.h
 
 JSON_H = \
   json/json_spirit.h \
   json/json_spirit_error_position.h \
   json/json_spirit_reader.h \
   json/json_spirit_reader_template.h \
   json/json_spirit_stream_reader.h \
   json/json_spirit_utils.h \
   json/json_spirit_value.h \
   json/json_spirit_writer.h \
   json/json_spirit_writer_template.h
 
 obj/build.h: FORCE
 	@$(MKDIR_P) $(builddir)/obj
 	@$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \
 	  $(abs_top_srcdir)
 libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
 
 # server: shared between bitcoind and bitcoin-qt
 libbitcoin_server_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS)
 libbitcoin_server_a_SOURCES = \
   addrman.cpp \
   alert.cpp \
   bloom.cpp \
   chain.cpp \
   checkpoints.cpp \
   init.cpp \
   leveldbwrapper.cpp \
   main.cpp \
   merkleblock.cpp \
   miner.cpp \
   net.cpp \
   noui.cpp \
   pow.cpp \
   rest.cpp \
   rpcblockchain.cpp \
   rpcmining.cpp \
   rpcmisc.cpp \
   rpcnet.cpp \
   rpcrawtransaction.cpp \
   rpcserver.cpp \
   script/sigcache.cpp \
   timedata.cpp \
   txdb.cpp \
   txmempool.cpp \
   validationinterface.cpp \
   $(JSON_H) \
   $(BITCOIN_CORE_H)
 
 # wallet: shared between bitcoind and bitcoin-qt, but only linked
 # when wallet enabled
 libbitcoin_wallet_a_CPPFLAGS = $(BITCOIN_INCLUDES)
 libbitcoin_wallet_a_SOURCES = \
   wallet/crypter.cpp \
   wallet/db.cpp \
   wallet/rpcdump.cpp \
   wallet/rpcwallet.cpp \
   wallet/wallet.cpp \
   wallet/wallet_ismine.cpp \
   wallet/walletdb.cpp \
   $(BITCOIN_CORE_H)
 
 # crypto primitives library
 crypto_libbitcoin_crypto_a_CPPFLAGS = $(BITCOIN_CONFIG_INCLUDES)
 crypto_libbitcoin_crypto_a_SOURCES = \
   crypto/sha1.cpp \
   crypto/sha256.cpp \
   crypto/sha512.cpp \
   crypto/hmac_sha256.cpp \
   crypto/hmac_sha512.cpp \
   crypto/ripemd160.cpp \
   crypto/common.h \
   crypto/sha256.h \
   crypto/sha512.h \
   crypto/hmac_sha256.h \
   crypto/hmac_sha512.h \
   crypto/sha1.h \
   crypto/ripemd160.h
 
 # univalue JSON library
 univalue_libbitcoin_univalue_a_SOURCES = \
   univalue/univalue.cpp \
   univalue/univalue_read.cpp \
   univalue/univalue_write.cpp \
   univalue/univalue_escapes.h \
   univalue/univalue.h
 
 # common: shared between bitcoind, and bitcoin-qt and non-server tools
 libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES)
 libbitcoin_common_a_SOURCES = \
   arith_uint256.cpp \
   amount.cpp \
   base58.cpp \
   chainparams.cpp \
   coins.cpp \
   compressor.cpp \
   primitives/block.cpp \
   primitives/transaction.cpp \
   core_read.cpp \
   core_write.cpp \
   eccryptoverify.cpp \
   ecwrapper.cpp \
   hash.cpp \
   key.cpp \
   keystore.cpp \
   netbase.cpp \
   protocol.cpp \
   pubkey.cpp \
+  scheduler.cpp \
   script/interpreter.cpp \
   script/script.cpp \
   script/sign.cpp \
   script/standard.cpp \
   script/script_error.cpp \
   $(BITCOIN_CORE_H)
 
 # util: shared between all executables.
 # This library *must* be included to make sure that the glibc
 # backward-compatibility objects and their sanity checks are linked.
 libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES)
 libbitcoin_util_a_SOURCES = \
   support/pagelocker.cpp \
   chainparamsbase.cpp \
   clientversion.cpp \
   compat/glibc_sanity.cpp \
   compat/glibcxx_sanity.cpp \
   compat/strnlen.cpp \
   random.cpp \
   rpcprotocol.cpp \
   support/cleanse.cpp \
   sync.cpp \
   uint256.cpp \
   util.cpp \
   utilmoneystr.cpp \
   utilstrencodings.cpp \
   utiltime.cpp \
   $(BITCOIN_CORE_H)
 
 if GLIBC_BACK_COMPAT
 libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp
 endif
 
 # cli: shared between bitcoin-cli and bitcoin-qt
 libbitcoin_cli_a_CPPFLAGS = $(BITCOIN_INCLUDES)
 libbitcoin_cli_a_SOURCES = \
   rpcclient.cpp \
   $(BITCOIN_CORE_H)
 
 nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h
 #
 
 # bitcoind binary #
 bitcoind_SOURCES = bitcoind.cpp
 bitcoind_CPPFLAGS = $(BITCOIN_INCLUDES)
 bitcoind_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
 
 if TARGET_WINDOWS
 bitcoind_SOURCES += bitcoind-res.rc
 endif
 
 bitcoind_LDADD = \
   $(LIBBITCOIN_SERVER) \
   $(LIBBITCOIN_COMMON) \
   $(LIBBITCOIN_UNIVALUE) \
   $(LIBBITCOIN_UTIL) \
   $(LIBBITCOIN_CRYPTO) \
   $(LIBLEVELDB) \
   $(LIBMEMENV) \
   $(LIBSECP256K1)
 
 if ENABLE_WALLET
 bitcoind_LDADD += libbitcoin_wallet.a
 endif
 
 bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
 #
 
 # bitcoin-cli binary #
 bitcoin_cli_SOURCES = bitcoin-cli.cpp
 bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES)
 bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
 
 if TARGET_WINDOWS
 bitcoin_cli_SOURCES += bitcoin-cli-res.rc
 endif
 
 bitcoin_cli_LDADD = \
   $(LIBBITCOIN_CLI) \
   $(LIBBITCOIN_UTIL) \
   $(LIBSECP256K1)
 
 bitcoin_cli_LDADD += $(BOOST_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS)
 #
 
 # bitcoin-tx binary #
 bitcoin_tx_SOURCES = bitcoin-tx.cpp
 bitcoin_tx_CPPFLAGS = $(BITCOIN_INCLUDES)
 bitcoin_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
 
 bitcoin_tx_LDADD = \
   $(LIBBITCOIN_UNIVALUE) \
   $(LIBBITCOIN_COMMON) \
   $(LIBBITCOIN_UTIL) \
   $(LIBBITCOIN_CRYPTO) \
   $(LIBSECP256K1)
 
 bitcoin_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
 #
 
 # bitcoinconsensus library #
 if BUILD_BITCOIN_LIBS
 include_HEADERS = script/bitcoinconsensus.h
 libbitcoinconsensus_la_SOURCES = \
   crypto/hmac_sha512.cpp \
   crypto/ripemd160.cpp \
   crypto/sha1.cpp \
   crypto/sha256.cpp \
   crypto/sha512.cpp \
   eccryptoverify.cpp \
   ecwrapper.cpp \
   hash.cpp \
   primitives/transaction.cpp \
   pubkey.cpp \
   script/bitcoinconsensus.cpp \
   script/interpreter.cpp \
   script/script.cpp \
   uint256.cpp \
   utilstrencodings.cpp
 
 if GLIBC_BACK_COMPAT
   libbitcoinconsensus_la_SOURCES += compat/glibc_compat.cpp
 endif
 
 libbitcoinconsensus_la_LDFLAGS = -no-undefined $(RELDFLAGS)
 libbitcoinconsensus_la_LIBADD = $(CRYPTO_LIBS)
 libbitcoinconsensus_la_CPPFLAGS = $(CRYPTO_CFLAGS) -I$(builddir)/obj -DBUILD_BITCOIN_INTERNAL
 
 endif
 #
 
 CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno
 
 DISTCLEANFILES = obj/build.h
 
 EXTRA_DIST = leveldb
 
 clean-local:
 	-$(MAKE) -C leveldb clean
 	-$(MAKE) -C secp256k1 clean
 	rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno
 	-rm -f config.h
 
 .rc.o:
 	@test -f $(WINDRES)
 	$(AM_V_GEN) $(WINDRES) -DWINDRES_PREPROC -i $< -o $@
 
 .mm.o:
 	$(AM_V_CXX) $(OBJCXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
 	  $(CPPFLAGS) $(AM_CXXFLAGS) $(QT_INCLUDES) $(CXXFLAGS)  -c -o $@ $<
 
 %.pb.cc %.pb.h: %.proto
 	@test -f $(PROTOC)
 	$(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $(<D) $<)
 
 if ENABLE_TESTS
 include Makefile.test.include
 endif
 
 if ENABLE_QT
 include Makefile.qt.include
 endif
 
 if ENABLE_QT_TESTS
 include Makefile.qttest.include
 endif
diff --git a/src/scheduler.cpp b/src/scheduler.cpp
new file mode 100644
index 000000000..ff223c231
--- /dev/null
+++ b/src/scheduler.cpp
@@ -0,0 +1,102 @@
+// Copyright (c) 2015 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "scheduler.h"
+
+#include <assert.h>
+#include <boost/bind.hpp>
+#include <utility>
+
+CScheduler::CScheduler() : nThreadsServicingQueue(0)
+{
+}
+
+CScheduler::~CScheduler()
+{
+    assert(nThreadsServicingQueue == 0);
+}
+
+
+#if BOOST_VERSION < 105000
+static boost::system_time toPosixTime(const boost::chrono::system_clock::time_point& t)
+{
+    boost::chrono::system_clock::duration d = t.time_since_epoch();
+    boost::chrono::microseconds usecs = boost::chrono::duration_cast<boost::chrono::microseconds>(d);
+    boost::system_time result = boost::posix_time::from_time_t(0) +
+                                boost::posix_time::microseconds(usecs.count());
+    return result;
+}
+#endif
+
+void CScheduler::serviceQueue()
+{
+    boost::unique_lock<boost::mutex> lock(newTaskMutex);
+    ++nThreadsServicingQueue;
+
+    // newTaskMutex is locked throughout this loop EXCEPT
+    // when the thread is waiting or when the user's function
+    // is called.
+    while (1) {
+        try {
+            while (taskQueue.empty()) {
+                // Wait until there is something to do.
+                newTaskScheduled.wait(lock);
+            }
+// Wait until either there is a new task, or until
+// the time of the first item on the queue:
+
+// wait_until needs boost 1.50 or later; older versions have timed_wait:
+#if BOOST_VERSION < 105000
+            while (!taskQueue.empty() && newTaskScheduled.timed_wait(lock, toPosixTime(taskQueue.begin()->first))) {
+                // Keep waiting until timeout
+            }
+#else
+            while (!taskQueue.empty() && newTaskScheduled.wait_until(lock, taskQueue.begin()->first) != boost::cv_status::timeout) {
+                // Keep waiting until timeout
+            }
+#endif
+            // If there are multiple threads, the queue can empty while we're waiting (another
+            // thread may service the task we were waiting on).
+            if (taskQueue.empty())
+                continue;
+
+            Function f = taskQueue.begin()->second;
+            taskQueue.erase(taskQueue.begin());
+
+            // Unlock before calling f, so it can reschedule itself or another task
+            // without deadlocking:
+            lock.unlock();
+            f();
+            lock.lock();
+        } catch (...) {
+            --nThreadsServicingQueue;
+            throw;
+        }
+    }
+}
+
+void CScheduler::schedule(CScheduler::Function f, boost::chrono::system_clock::time_point t)
+{
+    {
+        boost::unique_lock<boost::mutex> lock(newTaskMutex);
+        taskQueue.insert(std::make_pair(t, f));
+    }
+    newTaskScheduled.notify_one();
+}
+
+void CScheduler::scheduleFromNow(CScheduler::Function f, int64_t deltaSeconds)
+{
+    schedule(f, boost::chrono::system_clock::now() + boost::chrono::seconds(deltaSeconds));
+}
+
+static void Repeat(CScheduler* s, CScheduler::Function f, int64_t deltaSeconds)
+{
+    f();
+    s->scheduleFromNow(boost::bind(&Repeat, s, f, deltaSeconds), deltaSeconds);
+}
+
+void CScheduler::scheduleEvery(CScheduler::Function f, int64_t deltaSeconds)
+{
+    scheduleFromNow(boost::bind(&Repeat, this, f, deltaSeconds), deltaSeconds);
+}
diff --git a/src/scheduler.h b/src/scheduler.h
new file mode 100644
index 000000000..bb383ab9f
--- /dev/null
+++ b/src/scheduler.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2015 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_SCHEDULER_H
+#define BITCOIN_SCHEDULER_H
+
+//
+// NOTE:
+// boost::thread / boost::function / boost::chrono should be ported to
+// std::thread / std::function / std::chrono when we support C++11.
+//
+#include <boost/function.hpp>
+#include <boost/chrono/chrono.hpp>
+#include <boost/thread.hpp>
+#include <map>
+
+//
+// Simple class for background tasks that should be run
+// periodically or once "after a while"
+//
+// Usage:
+//
+// CScheduler* s = new CScheduler();
+// s->scheduleFromNow(doSomething, 11); // Assuming a: void doSomething() { }
+// s->scheduleFromNow(boost::bind(Class::func, this, argument), 3);
+// boost::thread* t = new boost::thread(boost::bind(CScheduler::serviceQueue, s));
+//
+// ... then at program shutdown, clean up the thread running serviceQueue:
+// t->interrupt();
+// t->join();
+// delete t;
+// delete s; // Must be done after thread is interrupted/joined.
+//
+
+class CScheduler
+{
+public:
+    CScheduler();
+    ~CScheduler();
+
+    typedef boost::function<void(void)> Function;
+
+    // Call func at/after time t
+    void schedule(Function f, boost::chrono::system_clock::time_point t);
+
+    // Convenience method: call f once deltaSeconds from now
+    void scheduleFromNow(Function f, int64_t deltaSeconds);
+
+    // Another convenience method: call f approximately
+    // every deltaSeconds forever, starting deltaSeconds from now.
+    // To be more precise: every time f is finished, it
+    // is rescheduled to run deltaSeconds later. If you
+    // need more accurate scheduling, don't use this method.
+    void scheduleEvery(Function f, int64_t deltaSeconds);
+
+    // To keep things as simple as possible, there is no unschedule.
+
+    // Services the queue 'forever'. Should be run in a thread,
+    // and interrupted using boost::interrupt_thread
+    void serviceQueue();
+
+private:
+    std::multimap<boost::chrono::system_clock::time_point, Function> taskQueue;
+    boost::condition_variable newTaskScheduled;
+    boost::mutex newTaskMutex;
+    int nThreadsServicingQueue;
+};
+
+#endif