forked from skalenetwork/skale-consensus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SkaleCommon.h
438 lines (307 loc) · 16.4 KB
/
SkaleCommon.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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
141
142
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
/*
Copyright (C) 2018-2019 SKALE Labs
This file is part of skale-consensus.
skale-consensus is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
skale-consensus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with skale-consensus. If not, see <https://www.gnu.org/licenses/>.
@file SkaleCommon.h
@author Stan Kladko
@date 2018
*/
#ifndef _SKALE_COMMON_H
#define _SKALE_COMMON_H
#include <array>
#include <cstdint>
#include <iostream>
#include <map>
#include <memory>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <sstream>
#include <thread>
#include <mutex>
#include <shared_mutex>
#include "assert.h"
#include <condition_variable>
#include "stdlib.h"
#include <unistd.h>
#include <string>
#include <cstring>
#include <queue>
#include <vector>
#include <array>
#include <set>
#include <signal.h>
#include <atomic>
#include <exception>
#include <files.h>
#include <arpa/inet.h>
#include <cassert>
#include <boost/assert.hpp>
#include <sys/socket.h>
#include <sys/types.h>
#include <chrono>
#include <array>
#include <algorithm>
#include <iterator>
#include "cryptlib.h"
#include "sha3.h"
#include "sha.h"
#include <fstream>
#include <netinet/in.h>
#include <netdb.h>
#include <iostream>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-copy"
#pragma GCC diagnostic ignored "-Wpessimizing-move"
#pragma GCC diagnostic ignored "-Wsign-compare"
#include <boost/exception/exception.hpp>
#include <boost/exception/info.hpp>
#include <boost/exception/info_tuple.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/throw_exception.hpp>
#include "boost/filesystem.hpp"
#include <boost/filesystem/operations.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/detail/assert.hpp>
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/crc.hpp>
#include "boost/lexical_cast.hpp"
#include <boost/tokenizer.hpp>
#pragma GCC diagnostic pop
class ConsensusEngine;
class SkaleLog;
#define BOOST_STRONG_TYPEDEF( T, D ) \
struct D : boost::totally_ordered1< D, \
boost::totally_ordered2< D, T, \
boost::multipliable2< D, T, \
boost::addable2< D, T, boost::subtractable2< D, T > > > > > { \
T t; \
D( const T& t_ ) : t( t_ ){}; \
D( T&& t_ ) : t( std::move( t_ ) ){}; \
D() = default; \
D( const D& t_ ) = default; \
D( D&& ) = default; \
D& operator=( const D& rhs ) = default; \
D& operator=( D&& ) = default; \
explicit operator T&() { return t; } \
explicit operator const T&() const { return t; } \
bool operator==( const D& rhs ) const { return t == rhs.t; } \
bool operator<( const D& rhs ) const { return t < rhs.t; } \
\
D& operator+=( const T& rhs ) { \
t += rhs; \
return *this; \
} \
D& operator-=( const T& rhs ) { \
t -= rhs; \
return *this; \
} \
D& operator*=( const T& rhs ) { \
t *= rhs; \
return *this; \
} \
\
explicit operator bool() const { return t != 0; } \
\
friend const char* operator+( const char* s, const D& d ) { return s + d.t; } \
operator std::string() const { return to_string( t ); } \
friend std::string to_string( const D& d ) { return to_string( d.t ); } \
friend std::istream& operator>>( std::istream& s, D& d ) { \
s >> d.t; \
return s; \
} \
friend std::ostream& operator<<( std::ostream& s, const D& d ) { \
s << d.t; \
return s; \
} \
}
using namespace std;
static const uint64_t LEVELDB_SHARDS = 4;
static const uint64_t MAX_ACTIVE_CONSENSUSES = 5;
static const uint64_t MAX_CONSENSUS_HISTORY = 2 * MAX_ACTIVE_CONSENSUSES;
static const uint64_t SESSION_KEY_CACHE_SIZE = 2;
static const uint64_t SESSION_PUBLIC_KEY_CACHE_SIZE = 16;
// catchup happens in chunks of 32 MB MAX
static constexpr uint64_t MAX_CATCHUP_DOWNLOAD_BYTES = 64 * 1024 * 1024;
static constexpr uint64_t MAX_TRANSACTIONS_PER_BLOCK = 8 * 1024;
static constexpr int64_t EMPTY_BLOCK_INTERVAL_MS = 3000;
static constexpr int64_t EMPTY_BLOCK_INTERVAL_AFTER_CATCHUP_MS = 100;
static constexpr uint64_t MIN_BLOCK_INTERVAL_MS = 1;
static constexpr uint64_t PROPOSAL_RETRY_INTERVAL_MS = 500;
static constexpr uint64_t CATCHUP_INTERVAL_MS = 5000;
static constexpr uint64_t MONITORING_INTERVAL_MS = 1000;
static constexpr uint64_t STUCK_MONITORING_INTERVAL_MS = 3000;
static constexpr uint64_t STUCK_RESTART_INTERVAL_MS = 3 * 60 * 60 * 1000; // three hours
static constexpr uint64_t WAIT_AFTER_NETWORK_ERROR_MS = 3000;
static constexpr uint64_t CONNECTION_REFUSED_LOG_INTERVAL_MS = 10 * 60 * 1000;
// Non-tunable params
static constexpr uint32_t SOCKET_BACKLOG = 64;
static constexpr size_t HASH_LEN = 32;
static constexpr size_t PARTIAL_HASH_LEN = 8;
static constexpr uint32_t SLOW_TEST_INITIAL_GENERATE = 0;
// static constexpr uint32_t SLOW_TEST_INITIAL_GENERATE = 10000;
static constexpr uint64_t SLOW_TEST_MESSAGE_INTERVAL = 10000;
static constexpr size_t MAX_HEADER_SIZE = 8 * MAX_TRANSACTIONS_PER_BLOCK;
static const int MODERN_TIME = 1547640182;
static const int MAX_BUFFER_SIZE = 8 * 1024 * 1024;
static constexpr uint64_t MAGIC_NUMBER = 0x1396A22050B30;
static constexpr uint64_t TEST_MAGIC_NUMBER = 0x2456032650150;
static constexpr uint64_t MAX_DEFERRED_QUEUE_SIZE_FOR_BLOCK = 1024;
static const uint64_t KNOWN_TRANSACTIONS_HISTORY = 2 * MAX_TRANSACTIONS_PER_BLOCK;
static const uint64_t MAX_KNOWN_TRANSACTIONS_TOTAL_SIZE = 256 * 1024 * 1024; // 256 MBYTE FOR NOW
static const uint64_t KNOWN_MSG_HASHES_SIZE = 1024;
static const uint64_t LEVELDB_STATS_HISTORY = 8;
static const int ZMQ_TIMEOUT = 1000;
static const int CONSENSUS_ZMQ_HWM = 32;
static const int NODE_DEATH_INTERVAL_MS = 30000;
static const string VERSION_STRING( "2.1" );
static constexpr uint64_t MAX_CONSENSUS_MESSAGE_LEN = 4096;
static constexpr uint64_t MAX_ORACLE_SPEC_LEN = 1024;
static constexpr uint64_t MAX_ORACLE_RESULT_LEN = 1024 * 3;
enum port_type {
PROPOSAL = 0,
CATCHUP = 1,
RETRIEVE = 2,
HTTP_JSON = 3,
BINARY_CONSENSUS = 4,
ZMQ_BROADCAST = 5,
MTA = 6,
STATUS = 10
};
template < typename T >
using ptr = typename std::shared_ptr< T >; // #define ptr shared_ptr
template < typename T >
static inline std::string tstr( T x ) {
return std::to_string( x );
} // #define tstr(x) to_string(x)
using fs_path = boost::filesystem::path; // #define fs_path boost::filesystem::path
typedef array< uint8_t, PARTIAL_HASH_LEN > partial_sha_hash;
class SkaleCommon {
public:
static constexpr const char* NODE_FILE_NAME = "Node.json";
static constexpr const char* SCHAIN_DIR_NAME = "schains";
};
enum BinaryDecision { DECISION_UNDECIDED, DECISION_TRUE, DECISION_FALSE };
BOOST_STRONG_TYPEDEF( uint64_t, block_id );
BOOST_STRONG_TYPEDEF( uint64_t, node_count );
BOOST_STRONG_TYPEDEF( uint64_t, msg_id );
BOOST_STRONG_TYPEDEF( uint64_t, node_id );
BOOST_STRONG_TYPEDEF( uint64_t, schain_id );
BOOST_STRONG_TYPEDEF( unsigned int, tcp_connection );
BOOST_STRONG_TYPEDEF( uint64_t, instance_id );
BOOST_STRONG_TYPEDEF( uint64_t, schain_index );
BOOST_STRONG_TYPEDEF( uint64_t, bulk_data_len );
BOOST_STRONG_TYPEDEF( uint64_t, bin_consensus_round );
BOOST_STRONG_TYPEDEF( uint8_t, bin_consensus_value );
BOOST_STRONG_TYPEDEF( uint64_t, transaction_count );
BOOST_STRONG_TYPEDEF( uint16_t, network_port );
BOOST_STRONG_TYPEDEF( uint64_t, msg_len );
BOOST_STRONG_TYPEDEF( uint64_t, msg_nonce );
BOOST_STRONG_TYPEDEF( uint64_t, num_threads );
BOOST_STRONG_TYPEDEF( uint64_t, fragment_index );
BOOST_STRONG_TYPEDEF( int, file_descriptor );
BOOST_STRONG_TYPEDEF( char, out_buffer );
BOOST_STRONG_TYPEDEF( char, in_buffer );
using u256 = boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256,
boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > >;
inline std::string className( const std::string& prettyFunction ) {
size_t colons = prettyFunction.find( "::" );
if ( colons == std::string::npos )
return "::";
size_t begin = prettyFunction.substr( 0, colons ).rfind( " " ) + 1;
size_t end = colons - begin;
return prettyFunction.substr( begin, end );
}
static const num_threads NUM_SCHAIN_THREADS = num_threads( 1 );
static const num_threads NUM_DISPATCH_THREADS = num_threads( 1 );
static const num_threads NUM_ORACLE_THREADS = num_threads( 1 );
static const uint64_t ORACLE_QUEUE_TIMEOUT_MS = 1000;
static const uint64_t ORACLE_TIMEOUT_MS = 30000;
static const uint64_t ORACLE_REQUEST_AGE_ON_RECEIPT_MS = 10000;
static const uint64_t DEFAULT_DB_STORAGE_LIMIT = 5000000000; // 5Gbyte
static const uint64_t MAX_DELAYED_MESSAGE_SENDS = 128;
static const uint64_t MAX_PROPOSAL_QUEUE_SIZE = 4;
static const uint64_t SGX_SSL_PORT = 1026;
static const uint64_t BLOCK_PROPOSAL_RECEIVE_TIMEOUT_MS = 30000;
static const uint64_t REBROADCAST_TIMEOUT_MS = 120000;
static const uint64_t ZMQ_RECEIVE_RETRY_MS = 10;
static const uint64_t DEFAULT_MIN_PRICE = 100000;
static const uint64_t COMMON_COIN_ROUND = 4;
static const uint64_t ORACLE_RECEIPTS_MAP_SIZE = 100000;
static const uint64_t ORACLE_REQUEST_FUTURE_JITTER_MS = 1000;
static const uint64_t SGX_REQUEST_TIMEOUT_MS = 10000;
static const uint64_t HEALTHCHECK_ON_START_RETRY_TIME_SEC = 1500;
static const uint64_t HEALTHCHECK_ON_START_TIME_BETWEEN_WARNINGS_SEC = 5 * 60;
static const uint64_t TIME_BETWEEN_STARTUP_HEALTHCHECK_RETRIES_SEC = 1;
static const uint64_t HEALTH_CHECK_TIME_TO_WAIT_FOR_ALL_NODES_SEC = 5;
static const uint64_t CONSENSUS_WAIT_TIME_BEFORE_HARD_EXIT_MS = 30000;
extern void setThreadName( std::string const& _n, ConsensusEngine* _engine );
extern std::string getThreadName();
#define CHECK_ARGUMENT( _EXPRESSION_ ) \
if ( !( _EXPRESSION_ ) ) { \
auto __msg__ = string( "Argument Check failed:" ) + #_EXPRESSION_ + "\n" + \
__CLASS_NAME__ + ":" + __FUNCTION__ + +" " + string( __FILE__ ) + ":" + \
to_string( __LINE__ ); \
throw InvalidArgumentException( __msg__, __CLASS_NAME__ ); \
}
#define CHECK_STATE( _EXPRESSION_ ) \
if ( !( _EXPRESSION_ ) ) { \
auto __msg__ = string( "State check failed::" ) + #_EXPRESSION_ + " " + \
string( __FILE__ ) + ":" + to_string( __LINE__ ); \
throw InvalidStateException( __msg__, __CLASS_NAME__ ); \
}
#define ORACLE_CHECK_STATE( _EXPRESSION_ ) \
if ( !( _EXPRESSION_ ) ) { \
auto __msg__ = string( "Oracle check failed: " ) + #_EXPRESSION_; \
throw InvalidStateException( __msg__, "" ); \
}
#define CHECK_SIGNATURE_STATE( _EXPRESSION_ ) \
if ( !( _EXPRESSION_ ) ) { \
auto __msg__ = string( "Signature check failed::" ) + #_EXPRESSION_ + " " + \
string( __FILE__ ) + ":" + to_string( __LINE__ ); \
throw InvalidSignatureException( __msg__, __CLASS_NAME__ ); \
}
#define CHECK_ARGUMENT2( _EXPRESSION_, _MSG_ ) \
if ( !( _EXPRESSION_ ) ) { \
auto __msg__ = string( "Check failed::" ) + #_EXPRESSION_ + " " + string( __FILE__ ) + \
":" + to_string( __LINE__ ); \
throw InvalidArgumentException( __msg__ + ":" + _MSG_, __CLASS_NAME__ ); \
}
#define CHECK_STATE2( _EXPRESSION_, _MSG_ ) \
if ( !( _EXPRESSION_ ) ) { \
auto __msg__ = string( "Check failed::" ) + #_EXPRESSION_ + " " + string( __FILE__ ) + \
":" + to_string( __LINE__ ); \
throw InvalidStateException( __msg__ + ":" + _MSG_, __CLASS_NAME__ ); \
}
#define ORACLE_CHECK_STATE3( _EXPRESSION_, _MSG_, _ERROR_ ) \
if ( !( _EXPRESSION_ ) ) { \
auto __msg__ = string( "Oracle check failed: " ) + _MSG_; \
throw OracleException( __msg__, "", _ERROR_ ); \
}
#define INJECT_TEST( __TEST_NAME__, __TEST_CODE__ ) \
{ \
static bool __TEST_NAME__ = ( getenv( #__TEST_NAME__ ) != nullptr ); \
if ( __TEST_NAME__ ) { \
__TEST_CODE__; \
} \
};
#define LOCK( _M_ ) lock_guard< recursive_mutex > _lock_( _M_ );
#define READ_LOCK( _M_ ) shared_lock< shared_mutex > _read_lock_( _M_ );
#define WRITE_LOCK( _M_ ) unique_lock< shared_mutex > _write_lock_( _M_ );
#define RETURN_IF_PREVIOUSLY_CALLED( __BOOL__ ) \
auto __previouslyCalled = __BOOL__.exchange( true ); \
if ( __previouslyCalled ) { \
return; \
}
#endif // SKALE_COMMON_H