Xjail/Spartancoin Project

Check-in [9b449dc447]
Login
Overview
Comment:[upgrade mutex, lock and condition_variable from boost to std; upgrade to c++17 (std::auto_ptr was removed in c++17, use std::unique_ptr; std::random_shuffle to xjail::random_shuffle (have no enough test of std::shuffle))]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | boost-1.66.0
Files: files | file ages | folders
SHA3-256:9b449dc447e6cc0758e59e3fa3d8462b5dda9c405b14c5f29cd464551e8cb50c
User & Date: xjail 2018-04-01 23:54:11
Context
2018-04-06
14:58
merge check-in: 3f22b893bf user: xjail tags: boost-1.66.0
2018-04-01
23:54
[upgrade mutex, lock and condition_variable from boost to std; upgrade to c++17 (std::auto_ptr was removed in c++17, use std::unique_ptr; std::random_shuffle to xjail::random_shuffle (have no enough test of std::shuffle))] check-in: 9b449dc447 user: xjail tags: boost-1.66.0
2018-03-17
12:15
modify copyright year check-in: 8ca3912a49 user: xjail tags: boost-1.66.0
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to spartancoin-qt.pro.

5
6
7
8
9
10
11

12
13
14
15
16
17
18
INCLUDEPATH += src src/json src/qt
QT += core gui network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE
CONFIG += no_include_pwd
CONFIG += thread
CONFIG += static


# for boost 1.37, add -mt to the boost libraries
# use: qmake BOOST_LIB_SUFFIX=-mt
# for boost thread win32 with _win32 sufix
# use: BOOST_THREAD_LIB_SUFFIX=_win32-...
# or when linking against a specific BerkelyDB version: BDB_LIB_SUFFIX=-5.3








>







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
INCLUDEPATH += src src/json src/qt
QT += core gui network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE
CONFIG += no_include_pwd
CONFIG += thread
CONFIG += static
QMAKE_CXXFLAGS += -std=c++17

# for boost 1.37, add -mt to the boost libraries
# use: qmake BOOST_LIB_SUFFIX=-mt
# for boost thread win32 with _win32 sufix
# use: BOOST_THREAD_LIB_SUFFIX=_win32-...
# or when linking against a specific BerkelyDB version: BDB_LIB_SUFFIX=-5.3

Changes to src/allocators.h.

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
..
52
53
54
55
56
57
58

59
60
61
62
63
64
65
66
..
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89
..
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-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 BITCOIN_ALLOCATORS_H
#define BITCOIN_ALLOCATORS_H

#include <string.h>
#include <string>
#include <boost/thread/mutex.hpp>
#include <map>
#include <openssl/crypto.h> // for OPENSSL_cleanse()

#ifdef WIN32
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
................................................................................
        assert(!(page_size & (page_size-1))); // size must be power of two
        page_mask = ~(page_size - 1);
    }

    // For all pages in affected range, increase lock count
    void LockRange(void *p, size_t size)
    {

        boost::mutex::scoped_lock lock(mutex);
        if(!size) return;
        const size_t base_addr = reinterpret_cast<size_t>(p);
        const size_t start_page = base_addr & page_mask;
        const size_t end_page = (base_addr + size - 1) & page_mask;
        for(size_t page = start_page; page <= end_page; page += page_size)
        {
            Histogram::iterator it = histogram.find(page);
................................................................................
            }
        }
    }

    // For all pages in affected range, decrease lock count
    void UnlockRange(void *p, size_t size)
    {

        boost::mutex::scoped_lock lock(mutex);
        if(!size) return;
        const size_t base_addr = reinterpret_cast<size_t>(p);
        const size_t start_page = base_addr & page_mask;
        const size_t end_page = (base_addr + size - 1) & page_mask;
        for(size_t page = start_page; page <= end_page; page += page_size)
        {
            Histogram::iterator it = histogram.find(page);
................................................................................
            }
        }
    }

    // Get number of locked pages for diagnostics
    int GetLockedPageCount()
    {

        boost::mutex::scoped_lock lock(mutex);
        return histogram.size();
    }

private:
    Locker locker;
    boost::mutex mutex;
    size_t page_size, page_mask;
    // map of page base address to lock count
    typedef std::map<size_t,int> Histogram;
    Histogram histogram;
};

/** Determine system page size in bytes */


>







|







 







>
|







 







>
|







 







>
|





|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
..
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
..
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Copyright (c) 2017-2018 xjail.tiv.cc developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_ALLOCATORS_H
#define BITCOIN_ALLOCATORS_H

#include <string.h>
#include <string>
#include <mutex>
#include <map>
#include <openssl/crypto.h> // for OPENSSL_cleanse()

#ifdef WIN32
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
................................................................................
        assert(!(page_size & (page_size-1))); // size must be power of two
        page_mask = ~(page_size - 1);
    }

    // For all pages in affected range, increase lock count
    void LockRange(void *p, size_t size)
    {
		// std::scoped_lock and use it without template parameters: c++17 required
        std::scoped_lock lock(mutex);
        if(!size) return;
        const size_t base_addr = reinterpret_cast<size_t>(p);
        const size_t start_page = base_addr & page_mask;
        const size_t end_page = (base_addr + size - 1) & page_mask;
        for(size_t page = start_page; page <= end_page; page += page_size)
        {
            Histogram::iterator it = histogram.find(page);
................................................................................
            }
        }
    }

    // For all pages in affected range, decrease lock count
    void UnlockRange(void *p, size_t size)
    {
		// std::scoped_lock and use it without template parameters: c++17 required
        std::scoped_lock lock(mutex);
        if(!size) return;
        const size_t base_addr = reinterpret_cast<size_t>(p);
        const size_t start_page = base_addr & page_mask;
        const size_t end_page = (base_addr + size - 1) & page_mask;
        for(size_t page = start_page; page <= end_page; page += page_size)
        {
            Histogram::iterator it = histogram.find(page);
................................................................................
            }
        }
    }

    // Get number of locked pages for diagnostics
    int GetLockedPageCount()
    {
		// std::scoped_lock and use it without template parameters: c++17 required
        std::scoped_lock lock(mutex);
        return histogram.size();
    }

private:
    Locker locker;
    std::mutex mutex;
    size_t page_size, page_mask;
    // map of page base address to lock count
    typedef std::map<size_t,int> Histogram;
    Histogram histogram;
};

/** Determine system page size in bytes */

Changes to src/checkqueue.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
..
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright (c) 2012 The Bitcoin developers
// Copyright (c) 2017-2018 xjail.tiv.cc 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 <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/condition_variable.hpp>

#include <vector>
#include <algorithm>

template<typename T> class CCheckQueueControl;

/** Queue for verifications that have to be performed.
................................................................................
  * 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;

    // 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;
................................................................................
    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();
................................................................................
    // 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);
        for(T &check: vChecks) {
            queue.push_back(T());
            check.swap(queue.back());
        }
        nTodo += vChecks.size();
        if (vChecks.size() == 1)
            condWorker.notify_one();







|
<
|







 







|


|


|







 







|






|







 







|







1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
..
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Copyright (c) 2012 The Bitcoin developers
// Copyright (c) 2017-2018 xjail.tiv.cc 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 <mutex>

#include <condition_variable>

#include <vector>
#include <algorithm>

template<typename T> class CCheckQueueControl;

/** Queue for verifications that have to be performed.
................................................................................
  * 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
    std::mutex mutex;

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

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

    // 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;
................................................................................
    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) {
        std::condition_variable & cond = fMaster ? condMaster : condWorker;
        std::vector<T> vChecks;
        vChecks.reserve(nBatchSize);
        unsigned int nNow = 0;
        bool fOk = true;
        do {
            {
                std::unique_lock<std::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();
................................................................................
    // 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) {
        std::unique_lock<std::mutex> lock(mutex);
        for(T &check: vChecks) {
            queue.push_back(T());
            check.swap(queue.back());
        }
        nTodo += vChecks.size();
        if (vChecks.size() == 1)
            condWorker.notify_one();

Changes to src/leveldb.cpp.

8
9
10
11
12
13
14
15


16
17
18
19
20
21
22
..
66
67
68
69
70
71
72
73


74
75
76
77
78
79
80
81
#include <leveldb/env.h>
#include <leveldb/cache.h>
#include <leveldb/filter_policy.h>
#include <memenv/memenv.h>

#include <boost/filesystem.hpp>

void HandleError(const leveldb::Status &status) throw(leveldb_error) {


    if (status.ok())
        return;
    if (status.IsCorruption())
        throw leveldb_error("Database corrupted");
    if (status.IsIOError())
        throw leveldb_error("Database I/O error");
    if (status.IsNotFound())
................................................................................
    options.filter_policy = NULL;
    delete options.block_cache;
    options.block_cache = NULL;
    delete penv;
    options.env = NULL;
}

bool CLevelDB::WriteBatch(CLevelDBBatch &batch, bool fSync) throw(leveldb_error) {


    leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
    if (!status.ok()) {
        printf("LevelDB write failure: %s\n", status.ToString().c_str());
        HandleError(status);
        return false;
    }
    return true;
}







|
>
>







 







|
>
>








8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <leveldb/env.h>
#include <leveldb/cache.h>
#include <leveldb/filter_policy.h>
#include <memenv/memenv.h>

#include <boost/filesystem.hpp>

// void HandleError(const leveldb::Status &status) throw(leveldb_error) {
// c++17 specification.
void HandleError(const leveldb::Status &status) noexcept(false) {
    if (status.ok())
        return;
    if (status.IsCorruption())
        throw leveldb_error("Database corrupted");
    if (status.IsIOError())
        throw leveldb_error("Database I/O error");
    if (status.IsNotFound())
................................................................................
    options.filter_policy = NULL;
    delete options.block_cache;
    options.block_cache = NULL;
    delete penv;
    options.env = NULL;
}

//bool CLevelDB::WriteBatch(CLevelDBBatch &batch, bool fSync) throw(leveldb_error) {
// c++17 specification.
bool CLevelDB::WriteBatch(CLevelDBBatch &batch, bool fSync) noexcept(false) {
    leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
    if (!status.ok()) {
        printf("LevelDB write failure: %s\n", status.ToString().c_str());
        HandleError(status);
        return false;
    }
    return true;
}

Changes to src/leveldb.h.

1

2
3
4
5
6
7
8
..
13
14
15
16
17
18
19

20




21
22
23
24
25
26
27
..
76
77
78
79
80
81
82

83




84
85
86
87
88
89
90
..
99
100
101
102
103
104
105

106




107
108
109
110
111

112




113
114
115
116
117
118
119
...
122
123
124
125
126
127
128

129




130
131
132
133
134

135




136
137
138
139
140
141

142




143
144
145
146
147
148
149
150
151
152
153
// 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 BITCOIN_LEVELDB_H
#define BITCOIN_LEVELDB_H

#include "serialize.h"

................................................................................

class leveldb_error : public std::runtime_error
{
public:
    leveldb_error(const std::string &msg) : std::runtime_error(msg) {}
};


void HandleError(const leveldb::Status &status) throw(leveldb_error);





// Batch of changes queued to be written to a CLevelDB
class CLevelDBBatch
{
    friend class CLevelDB;

private:
................................................................................
    // the database itself
    leveldb::DB *pdb;

public:
    CLevelDB(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory = false, bool fWipe = false);
    ~CLevelDB();


    template<typename K, typename V> bool Read(const K& key, V& value) throw(leveldb_error) {




        CDataStream ssKey(SER_DISK, CLIENT_VERSION);
        ssKey.reserve(ssKey.GetSerializeSize(key));
        ssKey << key;
        leveldb::Slice slKey(&ssKey[0], ssKey.size());

        std::string strValue;
        leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
................................................................................
            ssValue >> value;
        } catch(std::exception &e) {
            return false;
        }
        return true;
    }


    template<typename K, typename V> bool Write(const K& key, const V& value, bool fSync = false) throw(leveldb_error) {




        CLevelDBBatch batch;
        batch.Write(key, value);
        return WriteBatch(batch, fSync);
    }


    template<typename K> bool Exists(const K& key) throw(leveldb_error) {




        CDataStream ssKey(SER_DISK, CLIENT_VERSION);
        ssKey.reserve(ssKey.GetSerializeSize(key));
        ssKey << key;
        leveldb::Slice slKey(&ssKey[0], ssKey.size());

        std::string strValue;
        leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
................................................................................
                return false;
            printf("LevelDB read failure: %s\n", status.ToString().c_str());
            HandleError(status);
        }
        return true;
    }


    template<typename K> bool Erase(const K& key, bool fSync = false) throw(leveldb_error) {




        CLevelDBBatch batch;
        batch.Erase(key);
        return WriteBatch(batch, fSync);
    }


    bool WriteBatch(CLevelDBBatch &batch, bool fSync = false) throw(leveldb_error);





    // not available for LevelDB; provide for compatibility with BDB
    bool Flush() {
        return true;
    }


    bool Sync() throw(leveldb_error) {




        CLevelDBBatch batch;
        return WriteBatch(batch, true);
    }

    // not exactly clean encapsulation, but it's easiest for now
    leveldb::Iterator *NewIterator() {
        return pdb->NewIterator(iteroptions);
    }
};

#endif // BITCOIN_LEVELDB_H

>







 







>
|
>
>
>
>







 







>
|
>
>
>
>







 







>
|
>
>
>
>





>
|
>
>
>
>







 







>
|
>
>
>
>





>
|
>
>
>
>






>
|
>
>
>
>











1
2
3
4
5
6
7
8
9
..
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// Copyright (c) 2012 The Bitcoin developers
// Copyright (c) 2017-2018 xjail.tiv.cc developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_LEVELDB_H
#define BITCOIN_LEVELDB_H

#include "serialize.h"

................................................................................

class leveldb_error : public std::runtime_error
{
public:
    leveldb_error(const std::string &msg) : std::runtime_error(msg) {}
};

// old
// void HandleError(const leveldb::Status &status) throw(leveldb_error);

// new: 
// c++17 exception specifications. Replaced by xjail.tiv.cc developers
void HandleError(const leveldb::Status & status) noexcept(false);

// Batch of changes queued to be written to a CLevelDB
class CLevelDBBatch
{
    friend class CLevelDB;

private:
................................................................................
    // the database itself
    leveldb::DB *pdb;

public:
    CLevelDB(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory = false, bool fWipe = false);
    ~CLevelDB();

	// old
    // template<typename K, typename V> bool Read(const K& key, V& value) throw(leveldb_error) {

	// new:
	// c++17 exception specifications. Replaced by xjail.tiv.cc developers
    template<typename K, typename V> bool Read(const K& key, V& value) noexcept(false) {
        CDataStream ssKey(SER_DISK, CLIENT_VERSION);
        ssKey.reserve(ssKey.GetSerializeSize(key));
        ssKey << key;
        leveldb::Slice slKey(&ssKey[0], ssKey.size());

        std::string strValue;
        leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
................................................................................
            ssValue >> value;
        } catch(std::exception &e) {
            return false;
        }
        return true;
    }

	// old
    // template<typename K, typename V> bool Write(const K& key, const V& value, bool fSync = false) throw(leveldb_error) {

	// new:
	// c++17 exception specifications. Replaced by xjail.tiv.cc developers
    template<typename K, typename V> bool Write(const K& key, const V& value, bool fSync = false) noexcept(false) {
        CLevelDBBatch batch;
        batch.Write(key, value);
        return WriteBatch(batch, fSync);
    }

	// old
    // template<typename K> bool Exists(const K& key) throw(leveldb_error) {

	// new:
	// c++17 exception specifications. Replaced by xjail.tiv.cc developers
    template<typename K> bool Exists(const K& key) noexcept(false) {
        CDataStream ssKey(SER_DISK, CLIENT_VERSION);
        ssKey.reserve(ssKey.GetSerializeSize(key));
        ssKey << key;
        leveldb::Slice slKey(&ssKey[0], ssKey.size());

        std::string strValue;
        leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
................................................................................
                return false;
            printf("LevelDB read failure: %s\n", status.ToString().c_str());
            HandleError(status);
        }
        return true;
    }

	// old
    // template<typename K> bool Erase(const K& key, bool fSync = false) throw(leveldb_error) {

	// new:
	// c++17 exception specifications. Replaced by xjail.tiv.cc developers
    template<typename K> bool Erase(const K& key, bool fSync = false) noexcept(false) {
        CLevelDBBatch batch;
        batch.Erase(key);
        return WriteBatch(batch, fSync);
    }

	// old
    //bool WriteBatch(CLevelDBBatch &batch, bool fSync = false) throw(leveldb_error);

	// new:
	// c++17 exception specifications. Replaced by xjail.tiv.cc developers
    bool WriteBatch(CLevelDBBatch &batch, bool fSync = false) noexcept(false);

    // not available for LevelDB; provide for compatibility with BDB
    bool Flush() {
        return true;
    }

    // old
	// bool Sync() throw(leveldb_error) {

	// new:
	// c++17 exception specifications. Replaced by xjail.tiv.cc developers
    bool Sync() noexcept(false) {
        CLevelDBBatch batch;
        return WriteBatch(batch, true);
    }

    // not exactly clean encapsulation, but it's easiest for now
    leveldb::Iterator *NewIterator() {
        return pdb->NewIterator(iteroptions);
    }
};

#endif // BITCOIN_LEVELDB_H

Changes to src/main.cpp.

4346
4347
4348
4349
4350
4351
4352

4353
4354
4355
4356
4357
4358
4359
4360
....
4714
4715
4716
4717
4718
4719
4720

4721
4722
4723
4724
4725
4726
4727
4728
        }
    }
};

CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
{
    // Create new block

    auto_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
    if(!pblocktemplate.get())
        return NULL;
    CBlock *pblock = &pblocktemplate->block; // pointer for convenience

    // Create coinbase tx
    CTransaction txNew;
    txNew.vin.resize(1);
................................................................................

        //
        // Create new block
        //
        unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
        CBlockIndex* pindexPrev = pindexBest;


        auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
        if (!pblocktemplate.get())
            return;
        CBlock *pblock = &pblocktemplate->block;
        IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);

        printf("Running SpartancoinMiner with %s transactions in block (%u bytes)\n", 
		std::to_string(pblock->vtx.size()).c_str(),







>
|







 







>
|







4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
....
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
        }
    }
};

CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
{
    // Create new block
	// auto_ptr => unique_ptr: auto_ptr was removed in c++17
    std::unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
    if(!pblocktemplate.get())
        return NULL;
    CBlock *pblock = &pblocktemplate->block; // pointer for convenience

    // Create coinbase tx
    CTransaction txNew;
    txNew.vin.resize(1);
................................................................................

        //
        // Create new block
        //
        unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
        CBlockIndex* pindexPrev = pindexBest;

		// auto_ptr => unique_ptr: auto_ptr was removed in c++17
        std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
        if (!pblocktemplate.get())
            return;
        CBlock *pblock = &pblocktemplate->block;
        IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);

        printf("Running SpartancoinMiner with %s transactions in block (%u bytes)\n", 
		std::to_string(pblock->vtx.size()).c_str(),

Changes to src/makefile.freebsd.

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

DEBUGFLAGS=-g

# CXXFLAGS can be specified on the make command line, so we use xCXXFLAGS that only
# adds some defaults in front. Unfortunately, CXXFLAGS=... $(CXXFLAGS) does not work.
xCXXFLAGS=-O2 -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \
    $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)
xCXXFLAGS += -stdlib=libc++ -std=c++14

# LDFLAGS can be specified on the make command line, so we use xLDFLAGS that only
# adds some defaults in front. Unfortunately, LDFLAGS=... $(LDFLAGS) does not work.
xLDFLAGS=$(LDHARDENING) $(LDFLAGS)
xLDFLAGS += -lthr

OBJS= \







|







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

DEBUGFLAGS=-g

# CXXFLAGS can be specified on the make command line, so we use xCXXFLAGS that only
# adds some defaults in front. Unfortunately, CXXFLAGS=... $(CXXFLAGS) does not work.
xCXXFLAGS=-O2 -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \
    $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)
xCXXFLAGS += -stdlib=libc++ -std=c++17

# LDFLAGS can be specified on the make command line, so we use xLDFLAGS that only
# adds some defaults in front. Unfortunately, LDFLAGS=... $(LDFLAGS) does not work.
xLDFLAGS=$(LDHARDENING) $(LDFLAGS)
xLDFLAGS += -lthr

OBJS= \

Changes to src/makefile.unix.

1

2
3
4
5
6
7
8
...
108
109
110
111
112
113
114

115
116
117
118
119
120
121
# Copyright (c) 2009-2010 Satoshi Nakamoto

# Distributed under the MIT/X11 software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

# :=0 --> UPnP support turned off by default at runtime
# :=1 --> UPnP support turned on by default at runtime
# :=- --> No UPnP support - miniupnp not required
USE_UPNP:=0
................................................................................

DEBUGFLAGS=-g

# CXXFLAGS can be specified on the make command line, so we use xCXXFLAGS that only
# adds some defaults in front. Unfortunately, CXXFLAGS=... $(CXXFLAGS) does not work.
xCXXFLAGS=-O2 -pthread -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \
    $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)


# LDFLAGS can be specified on the make command line, so we use xLDFLAGS that only
# adds some defaults in front. Unfortunately, LDFLAGS=... $(LDFLAGS) does not work.
xLDFLAGS=$(LDHARDENING) $(LDFLAGS)

OBJS= \
    leveldb/libleveldb.a \

>







 







>







1
2
3
4
5
6
7
8
9
...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# Copyright (c) 2009-2010 Satoshi Nakamoto
# Copyright (c) 2017-2018 xjail.tiv.cc developers
# Distributed under the MIT/X11 software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

# :=0 --> UPnP support turned off by default at runtime
# :=1 --> UPnP support turned on by default at runtime
# :=- --> No UPnP support - miniupnp not required
USE_UPNP:=0
................................................................................

DEBUGFLAGS=-g

# CXXFLAGS can be specified on the make command line, so we use xCXXFLAGS that only
# adds some defaults in front. Unfortunately, CXXFLAGS=... $(CXXFLAGS) does not work.
xCXXFLAGS=-O2 -pthread -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \
    $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)
xCXXFLAGS += -std=c++17

# LDFLAGS can be specified on the make command line, so we use xLDFLAGS that only
# adds some defaults in front. Unfortunately, LDFLAGS=... $(LDFLAGS) does not work.
xLDFLAGS=$(LDHARDENING) $(LDFLAGS)

OBJS= \
    leveldb/libleveldb.a \

Changes to src/sync.cpp.

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    std::string mutexName;
    std::string sourceFile;
    int sourceLine;
};

typedef std::vector< std::pair<void*, CLockLocation> > LockStack;

static boost::mutex dd_mutex;
static std::map<std::pair<void*, void*>, LockStack> lockorders;
static boost::thread_specific_ptr<LockStack> lockstack;


static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
{
    printf("POTENTIAL DEADLOCK DETECTED\n");







|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    std::string mutexName;
    std::string sourceFile;
    int sourceLine;
};

typedef std::vector< std::pair<void*, CLockLocation> > LockStack;

static std::mutex dd_mutex;
static std::map<std::pair<void*, void*>, LockStack> lockorders;
static boost::thread_specific_ptr<LockStack> lockstack;


static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
{
    printf("POTENTIAL DEADLOCK DETECTED\n");

Changes to src/sync.h.

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
..
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
..
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
..
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-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 BITCOIN_SYNC_H
#define BITCOIN_SYNC_H

#include <boost/thread/mutex.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/condition_variable.hpp>
#include "threadsafety.h"

// Template mixin that adds -Wthread-safety locking annotations to a
// subset of the mutex API.
template <typename PARENT>
class LOCKABLE AnnotatedMixin : public PARENT
{
................................................................................

    bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
    {
      return PARENT::try_lock();
    }
};

/** Wrapped boost mutex: supports recursive locking, but no waiting  */
// TODO: We should move away from using the recursive lock by default.
typedef AnnotatedMixin<boost::recursive_mutex> CCriticalSection;

/** Wrapped boost mutex: supports waiting but not recursive locking */
typedef AnnotatedMixin<boost::mutex> CWaitableCriticalSection;

#ifdef DEBUG_LOCKORDER
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
void LeaveCritical();
#else
void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
void static inline LeaveCritical() {}
................................................................................
#endif

/** Wrapper around boost::unique_lock<Mutex> */
template<typename Mutex>
class CMutexLock
{
private:
    boost::unique_lock<Mutex> lock;

    void Enter(const char* pszName, const char* pszFile, int nLine)
    {
        EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
#ifdef DEBUG_LOCKCONTENTION
        if (!lock.try_lock())
        {
................................................................................
        lock.try_lock();
        if (!lock.owns_lock())
            LeaveCritical();
        return lock.owns_lock();
    }

public:
    CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::defer_lock)
    {
        if (fTry)
            TryEnter(pszName, pszFile, nLine);
        else
            Enter(pszName, pszFile, nLine);
    }

................................................................................
        (cs).unlock(); \
        LeaveCritical(); \
    }

class CSemaphore
{
private:
    boost::condition_variable condition;
    boost::mutex mutex;
    int value;

public:
    CSemaphore(int init) : value(init) {}

    void wait() {
        boost::unique_lock<boost::mutex> lock(mutex);
        while (value < 1) {
            condition.wait(lock);
        }
        value--;
    }

    bool try_wait() {
        boost::unique_lock<boost::mutex> lock(mutex);
        if (value < 1)
            return false;
        value--;
        return true;
    }

    void post() {
        {
            boost::unique_lock<boost::mutex> lock(mutex);
            value++;
        }
        condition.notify_one();
    }
};

/** RAII-style semaphore lock */


>





|
<
<
|







 







|

|


|







 







|







 







|







 







|
|






|







|








|







1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
17
..
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
..
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Copyright (c) 2017-2018 xjail.tiv.cc developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_SYNC_H
#define BITCOIN_SYNC_H

#include <mutex>


#include <condition_variable>
#include "threadsafety.h"

// Template mixin that adds -Wthread-safety locking annotations to a
// subset of the mutex API.
template <typename PARENT>
class LOCKABLE AnnotatedMixin : public PARENT
{
................................................................................

    bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
    {
      return PARENT::try_lock();
    }
};

/** Wrapped mutex: supports recursive locking, but no waiting  */
// TODO: We should move away from using the recursive lock by default.
typedef AnnotatedMixin<std::recursive_mutex> CCriticalSection;

/** Wrapped boost mutex: supports waiting but not recursive locking */
typedef AnnotatedMixin<std::mutex> CWaitableCriticalSection;

#ifdef DEBUG_LOCKORDER
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
void LeaveCritical();
#else
void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
void static inline LeaveCritical() {}
................................................................................
#endif

/** Wrapper around boost::unique_lock<Mutex> */
template<typename Mutex>
class CMutexLock
{
private:
    std::unique_lock<Mutex> lock;

    void Enter(const char* pszName, const char* pszFile, int nLine)
    {
        EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
#ifdef DEBUG_LOCKCONTENTION
        if (!lock.try_lock())
        {
................................................................................
        lock.try_lock();
        if (!lock.owns_lock())
            LeaveCritical();
        return lock.owns_lock();
    }

public:
    CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, std::defer_lock)
    {
        if (fTry)
            TryEnter(pszName, pszFile, nLine);
        else
            Enter(pszName, pszFile, nLine);
    }

................................................................................
        (cs).unlock(); \
        LeaveCritical(); \
    }

class CSemaphore
{
private:
    std::condition_variable condition;
    std::mutex mutex;
    int value;

public:
    CSemaphore(int init) : value(init) {}

    void wait() {
        std::unique_lock<std::mutex> lock(mutex);
        while (value < 1) {
            condition.wait(lock);
        }
        value--;
    }

    bool try_wait() {
        std::unique_lock<std::mutex> lock(mutex);
        if (value < 1)
            return false;
        value--;
        return true;
    }

    void post() {
        {
            std::unique_lock<std::mutex> lock(mutex);
            value++;
        }
        condition.notify_one();
    }
};

/** RAII-style semaphore lock */

Changes to src/wallet.cpp.

1037
1038
1039
1040
1041
1042
1043


























1044
1045
1046
1047
1048
1049
1050
....
1051
1052
1053
1054
1055
1056
1057


1058
1059
1060
1061
1062
1063
1064
1065
                        vfIncluded[i] = false;
                    }
                }
            }
        }
    }
}



























bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
                                 set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
{
    setCoinsRet.clear();
    nValueRet = 0;

................................................................................
    // List of values less than target
    pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
    coinLowestLarger.first = std::numeric_limits<int64>::max();
    coinLowestLarger.second.first = NULL;
    vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
    int64 nTotalLower = 0;



    random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);

    for(COutput output: vCoins)
    {
        const CWalletTx *pcoin = output.tx;

        if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
            continue;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
|







1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
....
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
                        vfIncluded[i] = false;
                    }
                }
            }
        }
    }
}

/////////////////////////////////////////////////////////
// ====> Temporary Code <====
// Custom Random Shuffle. The std::random_shuffle was removed
// in c++17. This random_shuffle is a modification of 
// std::random_shuffle in LLVM c++/v1/algorithm from 
// FreeBSD System Headers.
// The best solution is using std::shuffle, which will be 
// implemented in the future to write a custom URBG class.
// Copyright (c) xjail.tiv.cc developers.
namespace xjail {
	template <typename RandomIter, typename RandomFunc>
	void random_shuffle(RandomIter first, RandomIter last, 
					RandomFunc && rand_fn) {
		using DiffType = typename std::iterator_traits<RandomIter>
						::difference_type;
		DiffType max_setting = last - first;
		if (max_setting > 1) {
			for (--last; first < last; ++first, --max_setting) {
				DiffType rand_i = rand_fn(max_setting);
				std::swap(*first, *(first + rand_i));
			}
		}
	}
}
/////////////////////////////////////////////////////////

bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
                                 set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
{
    setCoinsRet.clear();
    nValueRet = 0;

................................................................................
    // List of values less than target
    pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
    coinLowestLarger.first = std::numeric_limits<int64>::max();
    coinLowestLarger.second.first = NULL;
    vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
    int64 nTotalLower = 0;

	// std::random_shuffle => xjail::random_shuffle (temporary use)
	// xjail::random_shuffle was defined above.
    xjail::random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);

    for(COutput output: vCoins)
    {
        const CWalletTx *pcoin = output.tx;

        if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
            continue;