Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recent updates #21

Merged
merged 27 commits into from Jul 24, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
96929d2
Split off hash.h from util.h
CryptoManiac Feb 19, 2014
451d6e7
Fix hash.h dependency
CryptoManiac Jul 12, 2014
810bdc9
Merge remote-tracking branch 'remotes/origin_project/master'
CryptoManiac Jul 13, 2014
74f0602
Generate only signatures with even S values
CryptoManiac Jul 15, 2014
9a452ad
Remove enforcecanonical option, it's always active from now.
CryptoManiac Jul 15, 2014
1cb6116
Implement additional script verification flags
CryptoManiac Jul 15, 2014
7a25517
Move VerifySignature to main
CryptoManiac Jul 15, 2014
3c32419
Script verification fixes
CryptoManiac Jul 15, 2014
09e87ff
Use nBestHeight instead of index height.
CryptoManiac Jul 15, 2014
6a4bd80
Replace VerifyScript with CScriptCheck
CryptoManiac Jul 15, 2014
273cead
Multi-threaded signatures checking support, rename threads.
CryptoManiac Jul 16, 2014
9cb7756
Turn the signature cache lock into a shared mutex
CryptoManiac Jul 16, 2014
dc51de0
Fix segmentation fault during shutdown.
CryptoManiac Jul 18, 2014
c6bb650
Use low S values instead of even values.
CryptoManiac Jul 18, 2014
07bc41c
Use low S to break signatures malleability issue
CryptoManiac Jul 18, 2014
a5240a0
Extended signature format checkings.
CryptoManiac Jul 18, 2014
b73a456
Add redeemScript to listunspent output and signrawtransaction input
CryptoManiac Jul 18, 2014
5b80623
Fix coin control change field behavior.
CryptoManiac Jul 19, 2014
077c5c2
Fix order comparison.
CryptoManiac Jul 19, 2014
580fa13
Merge support for watch-only addresses
CryptoManiac Jul 19, 2014
b0368da
Handle unspendable inputs correctly.
CryptoManiac Jul 19, 2014
ae640f0
Prevent import keys for watch-only addresses and vice versa.
CryptoManiac Jul 19, 2014
086e4fa
RPC: return raw transactions instead of parsed representation.
CryptoManiac Jul 19, 2014
a45c599
RPC: Add parsed and raw checkpoint message data in gectcheckpoint out…
CryptoManiac Jul 20, 2014
5249b8a
Rename fields
CryptoManiac Jul 20, 2014
d017277
Add SIG_SWITCH_TIME at Sat, 20 Sep 2014
CryptoManiac Jul 22, 2014
4e7a581
Use STRICT_FLAGS for signatures validation
CryptoManiac Jul 22, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions novacoin-qt.pro
Expand Up @@ -163,6 +163,7 @@ HEADERS += src/qt/bitcoingui.h \
src/sync.h \
src/util.h \
src/timestamps.h \
src/hash.h \
src/uint256.h \
src/kernel.h \
src/scrypt.h \
Expand Down
1 change: 1 addition & 0 deletions src/addrman.cpp
Expand Up @@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "addrman.h"
#include "hash.h"

using namespace std;

Expand Down
8 changes: 4 additions & 4 deletions src/bitcoinrpc.cpp
Expand Up @@ -248,7 +248,6 @@ static const CRPCCommand vRPCCommands[] =
{ "getsubsidy", &getsubsidy, true, false },
{ "getmininginfo", &getmininginfo, true, false },
{ "getnewaddress", &getnewaddress, true, false },
{ "getnewpubkey", &getnewpubkey, true, false },
{ "getaccountaddress", &getaccountaddress, true, false },
{ "setaccount", &setaccount, true, false },
{ "getaccount", &getaccount, false, false },
Expand All @@ -265,7 +264,6 @@ static const CRPCCommand vRPCCommands[] =
{ "walletlock", &walletlock, true, false },
{ "encryptwallet", &encryptwallet, false, false },
{ "validateaddress", &validateaddress, true, false },
{ "validatepubkey", &validatepubkey, true, false },
{ "getbalance", &getbalance, false, false },
{ "move", &movecmd, false, false },
{ "sendfrom", &sendfrom, false, false },
Expand All @@ -292,6 +290,7 @@ static const CRPCCommand vRPCCommands[] =
{ "dumpwallet", &dumpwallet, true, false },
{ "importwallet", &importwallet, false, false },
{ "importprivkey", &importprivkey, false, false },
{ "importaddress", &importaddress, false, true },
{ "listunspent", &listunspent, false, false },
{ "getrawtransaction", &getrawtransaction, false, false },
{ "createrawtransaction", &createrawtransaction, false, false },
Expand Down Expand Up @@ -668,7 +667,7 @@ class AcceptedConnectionImpl : public AcceptedConnection
void ThreadRPCServer(void* parg)
{
// Make this thread recognisable as the RPC listener
RenameThread("bitcoin-rpclist");
RenameThread("novacoin-rpclist");

try
{
Expand Down Expand Up @@ -968,7 +967,7 @@ static CCriticalSection cs_THREAD_RPCHANDLER;
void ThreadRPCServer3(void* parg)
{
// Make this thread recognisable as the RPC handler
RenameThread("bitcoin-rpchand");
RenameThread("novacoin-rpchand");

{
LOCK(cs_THREAD_RPCHANDLER);
Expand Down Expand Up @@ -1229,6 +1228,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
if (strMethod == "signrawtransaction" && n > 1) ConvertTo<Array>(params[1], true);
if (strMethod == "signrawtransaction" && n > 2) ConvertTo<Array>(params[2], true);
if (strMethod == "keypoolrefill" && n > 0) ConvertTo<boost::int64_t>(params[0]);
if (strMethod == "importaddress" && n > 2) ConvertTo<bool>(params[2]);

return params;
}
Expand Down
3 changes: 1 addition & 2 deletions src/bitcoinrpc.h
Expand Up @@ -150,6 +150,7 @@ extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHel
extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp
extern json_spirit::Value importprivkey(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value importaddress(const json_spirit::Array& params, bool fHelp);

extern json_spirit::Value sendalert(const json_spirit::Array& params, bool fHelp);

Expand Down Expand Up @@ -196,8 +197,6 @@ extern json_spirit::Value checkwallet(const json_spirit::Array& params, bool fHe
extern json_spirit::Value repairwallet(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value resendtx(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value makekeypair(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value validatepubkey(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getnewpubkey(const json_spirit::Array& params, bool fHelp);

extern json_spirit::Value getrawtransaction(const json_spirit::Array& params, bool fHelp); // in rcprawtransaction.cpp
extern json_spirit::Value listunspent(const json_spirit::Array& params, bool fHelp);
Expand Down
208 changes: 208 additions & 0 deletions src/checkqueue.h
@@ -0,0 +1,208 @@
// Copyright (c) 2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef CHECKQUEUE_H
#define CHECKQUEUE_H

#include <algorithm>
#include <vector>

#include <boost/foreach.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/mutex.hpp>

template<typename T> class CCheckQueueControl;

/** Queue for verifications that have to be performed.
* The verifications are represented by a type T, which must provide an
* operator(), returning a bool.
*
* One thread (the master) is assumed to push batches of verifications
* onto the queue, where they are processed by N-1 worker threads. When
* the master is done adding work, it temporarily joins the worker pool
* as an N'th worker, until all jobs are done.
*/
template<typename T> class CCheckQueue {
private:
// Mutex to protect the inner state
boost::mutex mutex;

// Worker threads block on this when out of work
boost::condition_variable condWorker;

// Master thread blocks on this when out of work
boost::condition_variable condMaster;

// Quit method blocks on this until all workers are gone
boost::condition_variable condQuit;

// The queue of elements to be processed.
// As the order of booleans doesn't matter, it is used as a LIFO (stack)
std::vector<T> queue;

// The number of workers (including the master) that are idle.
int nIdle;

// The total number of workers (including the master).
int nTotal;

// The temporary evaluation result.
bool fAllOk;

// Number of verifications that haven't completed yet.
// This includes elements that are not anymore in queue, but still in
// worker's own batches.
unsigned int nTodo;

// Whether we're shutting down.
bool fQuit;

// The maximum number of elements to be processed in one batch
unsigned int nBatchSize;

// Internal function that does bulk of the verification work.
bool Loop(bool fMaster = false) {
boost::condition_variable &cond = fMaster ? condMaster : condWorker;
std::vector<T> vChecks;
vChecks.reserve(nBatchSize);
unsigned int nNow = 0;
bool fOk = true;
do {
{
boost::unique_lock<boost::mutex> lock(mutex);
// first do the clean-up of the previous loop run (allowing us to do it in the same critsect)
if (nNow) {
fAllOk &= fOk;
nTodo -= nNow;
if (nTodo == 0 && !fMaster)
// We processed the last element; inform the master he can exit and return the result
condMaster.notify_one();
} else {
// first iteration
nTotal++;
}
// logically, the do loop starts here
while (queue.empty()) {
if ((fMaster || fQuit) && nTodo == 0) {
nTotal--;
if (nTotal==0)
condQuit.notify_one();
bool fRet = fAllOk;
// reset the status for new work later
if (fMaster)
fAllOk = true;
// return the current status
return fRet;
}
nIdle++;
cond.wait(lock); // wait
nIdle--;
}
// Decide how many work units to process now.
// * Do not try to do everything at once, but aim for increasingly smaller batches so
// all workers finish approximately simultaneously.
// * Try to account for idle jobs which will instantly start helping.
// * Don't do batches smaller than 1 (duh), or larger than nBatchSize.
nNow = std::max(1U, std::min(nBatchSize, (unsigned int)queue.size() / (nTotal + nIdle + 1)));
vChecks.resize(nNow);
for (unsigned int i = 0; i < nNow; i++) {
// We want the lock on the mutex to be as short as possible, so swap jobs from the global
// queue to the local batch vector instead of copying.
vChecks[i].swap(queue.back());
queue.pop_back();
}
// Check whether we need to do work at all
fOk = fAllOk;
}
// execute work
BOOST_FOREACH(T &check, vChecks)
if (fOk)
fOk = check();
vChecks.clear();
} while(true);
}

public:
// Create a new check queue
CCheckQueue(unsigned int nBatchSizeIn) :
nIdle(0), nTotal(0), fAllOk(true), nTodo(0), fQuit(false), nBatchSize(nBatchSizeIn) {}

// Worker thread
void Thread() {
Loop();
}

// Wait until execution finishes, and return whether all evaluations where succesful.
bool Wait() {
return Loop(true);
}

// Add a batch of checks to the queue
void Add(std::vector<T> &vChecks) {
boost::unique_lock<boost::mutex> lock(mutex);
BOOST_FOREACH(T &check, vChecks) {
queue.push_back(T());
check.swap(queue.back());
}
nTodo += vChecks.size();
if (vChecks.size() == 1)
condWorker.notify_one();
else if (vChecks.size() > 1)
condWorker.notify_all();
}

// Shut the queue down
void Quit() {
boost::unique_lock<boost::mutex> lock(mutex);
fQuit = true;
// No need to wake the master, as he will quit automatically when all jobs are
// done.
condWorker.notify_all();

while (nTotal > 0)
condQuit.wait(lock);
}

friend class CCheckQueueControl<T>;
};

/** RAII-style controller object for a CCheckQueue that guarantees the passed
* queue is finished before continuing.
*/
template<typename T> class CCheckQueueControl {
private:
CCheckQueue<T> *pqueue;
bool fDone;

public:
CCheckQueueControl(CCheckQueue<T> *pqueueIn) : pqueue(pqueueIn), fDone(false) {
// passed queue is supposed to be unused, or NULL
if (pqueue != NULL) {
assert(pqueue->nTotal == pqueue->nIdle);
assert(pqueue->nTodo == 0);
assert(pqueue->fAllOk == true);
}
}

bool Wait() {
if (pqueue == NULL)
return true;
bool fRet = pqueue->Wait();
fDone = true;
return fRet;
}

void Add(std::vector<T> &vChecks) {
if (pqueue != NULL)
pqueue->Add(vChecks);
}

~CCheckQueueControl() {
if (!fDone)
Wait();
}
};

#endif