Skip to content
This repository was archived by the owner on Apr 11, 2020. It is now read-only.

Commit 9b13e07

Browse files
committed
Update v4
1 parent 2c4107f commit 9b13e07

12 files changed

+249
-71
lines changed

src/Common/int-util.h

+23
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <stdint.h>
2323
#include <string.h>
2424
#include <sys/param.h>
25+
#include <math.h>
2526

2627
#if defined(_MSC_VER)
2728
#include <stdlib.h>
@@ -177,6 +178,28 @@ static inline void memcpy_swap64(void *dst, const void *src, size_t n) {
177178
}
178179
}
179180

181+
// Calculate ln(p) of Poisson distribution
182+
// https://github.com/ryo-currency/ryo-writeups/blob/master/poisson-writeup.md
183+
// Original idea : https://stackoverflow.com/questions/30156803/implementing-poisson-distribution-in-c
184+
// Using logarithms avoids dealing with very large (k!) and very small (p < 10^-44) numbers
185+
// lam - lambda parameter - in our case, how many blocks, on average, you would expect to see in the interval
186+
// k - k parameter - in our case, how many blocks we have actually seen
187+
// !!! k must not be zero
188+
// return - ln(p)
189+
190+
191+
static inline double calc_poisson_ln(double lam, uint64_t k)
192+
{
193+
double logx = -lam + k * log(lam);
194+
do
195+
{
196+
logx -= log((double)k); // This can be tabulated
197+
} while (--k > 0);
198+
return logx;
199+
}
200+
201+
202+
180203
#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN)
181204
static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled");
182205
#endif

src/CryptoNoteConfig.h

+53-10
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,14 @@ const uint64_t MONEY_SUPPLY = ((uint64_t)(-1));
4444
const size_t CRYPTONOTE_COIN_VERSION = 1;
4545

4646
const uint32_t ZAWY_LWMA2_DIFFICULTY_BLOCK_INDEX = 145000;
47+
const uint32_t ZAWY_LWMA3_DIFFICULTY_BLOCK_INDEX = 941000;
4748
const size_t DIFFICULTY_WINDOW_V2 = 60;
4849
const size_t ZAWY_LWMA2_DIFFICULTY_N = DIFFICULTY_WINDOW_V2;
4950
const uint64_t DIFFICULTY_BLOCKS_COUNT_V2 = DIFFICULTY_WINDOW_V2 + 1;
5051

5152
const uint16_t GOVERNANCE_PERCENT = 20; // 20 percent of block reward
52-
const uint32_t GOVERNANCE_HEIGHT = 196000;
53+
const uint32_t GOVERNANCE_HEIGHT_START = 196000;
54+
const uint32_t GOVERNANCE_HEIGHT_END = 941000;
5355

5456
const unsigned EMISSION_SPEED_FACTOR = 18;
5557
static_assert(EMISSION_SPEED_FACTOR <= 8 * sizeof(uint64_t), "Bad EMISSION_SPEED_FACTOR");
@@ -77,6 +79,10 @@ const size_t DIFFICULTY_LAG_V1 = 15;
7779
const size_t DIFFICULTY_LAG_V2 = 15;
7880
static_assert(2 * DIFFICULTY_CUT <= DIFFICULTY_WINDOW - 2, "Bad DIFFICULTY_WINDOW or DIFFICULTY_CUT");
7981

82+
const uint64_t POISSON_CHECK_TRIGGER = 10; // Reorg size that triggers poisson timestamp check
83+
const uint64_t POISSON_CHECK_DEPTH = 60; // Main-chain depth of the poisson check. The attacker will have to tamper 50% of those blocks
84+
const double POISSON_LOG_P_REJECT = -75.0; // Reject reorg if the probablity that the timestamps are genuine is below e^x, -75 = 10^-33
85+
8086
const size_t MAX_BLOCK_SIZE_INITIAL = 500 * 1024;
8187
const uint64_t MAX_BLOCK_SIZE_GROWTH_SPEED_NUMERATOR = 100 * 1024;
8288
const uint64_t MAX_BLOCK_SIZE_GROWTH_SPEED_DENOMINATOR = 365 * 24 * 60 * 60 / DIFFICULTY_TARGET;
@@ -123,8 +129,8 @@ const size_t BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT = 10000; //by def
123129
const size_t BLOCKS_SYNCHRONIZING_DEFAULT_COUNT = 128; //by default, blocks count in blocks downloading
124130
const size_t COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT = 1000;
125131

126-
const int P2P_DEFAULT_PORT = 20236;
127-
const int RPC_DEFAULT_PORT = 21236;
132+
const int P2P_DEFAULT_PORT = 30236;
133+
const int RPC_DEFAULT_PORT = 31236;
128134

129135
const size_t P2P_LOCAL_WHITE_PEERLIST_LIMIT = 1000;
130136
const size_t P2P_LOCAL_GRAY_PEERLIST_LIMIT = 5000;
@@ -139,15 +145,14 @@ const uint32_t P2P_DEFAULT_CONNECTION_TIMEOUT = 5000; //
139145
const uint32_t P2P_DEFAULT_PING_CONNECTION_TIMEOUT = 2000; // 2 seconds
140146
const uint64_t P2P_DEFAULT_INVOKE_TIMEOUT = 60 * 2 * 1000; // 2 minutes
141147
const size_t P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT = 5000; // 5 seconds
142-
const char P2P_STAT_TRUSTED_PUB_KEY[] = "8f80f9a5a434a9f1510d13336228debfee9c918ce505efe225d8c94d045fa115";
148+
const char P2P_STAT_TRUSTED_PUB_KEY[] = "";
143149

144150
const char* const SEED_NODES[] = {
145151

146-
"185.198.58.13:20236",
147-
"185.198.58.31:20236",
148-
"185.45.192.241:20236",
149-
"185.45.192.15:20236",
150-
"192.64.116.142:20236"
152+
"185.198.58.13:30236",
153+
"185.198.58.31:30236",
154+
"185.45.192.241:30236",
155+
"185.45.192.15:30236"
151156

152157
};
153158

@@ -212,7 +217,45 @@ const std::initializer_list<CheckpointData> CHECKPOINTS = {
212217
{172000, "02172bb159f7760b2aae1698a730bfb01525b2e952d96c3e2223966869a41e66"},
213218
{176000, "141c4ab276c7fc66a6d4fd79c9cf8948b2f9f4b44719b5da2b04b70dcfb1ed8f"},
214219
{180000, "29589d17e10de9488c44f6a87b7965c32d85f7c250c4e02fb211480dd9b3bff0"},
215-
{184000, "53fb8da65f4e8b9591382cd81d3034a3e755b878a8f21a3d4c7ee5f05665e2df"}
220+
{184000, "53fb8da65f4e8b9591382cd81d3034a3e755b878a8f21a3d4c7ee5f05665e2df"},
221+
{188000, "321fe8c8f44b53dc9ebefe8c5cfebd6cec96f3c6d87c47f78f9dd581d2232ef6"},
222+
{192000, "1fdbab5e54988c4a52543b59d0fd97794c40b761408837521c40727b13fa0067"},
223+
{196000, "f0646c7f4c7a62dc0abc3df3ec2b10501685058aade348f3d3f03e53e71a1761"},
224+
{200000, "0ab8beff6dd33585dab367aca4012b79e6222399e260a803a828febac7b0f452"},
225+
{204000, "7a23a71036262f3e0a227f0c1ca08beadfb5833b17045b850948ac7e505b7885"},
226+
{208000, "548e608371fcc1ae8a0fe8e9f3854f69e02f13f568c44169c82eee30cbe0929c"},
227+
{212000, "bd7593f657edeb1a6ff1cefedb3ffecab82c5d3e6cb50d1cb1cd5b508032c721"},
228+
{216000, "ffec1a59e354c430ec43ac7e179a0e887add184b96d47cf734de028f2573878d"},
229+
{220000, "f594c1642531430b91391d0695c09252ecc25c499378070a2127e10ea72f8820"},
230+
{224000, "075b31a89f9c4e8f2ef03522e8a52d4803685e01d2afc08919d179fc40c45ab8"},
231+
{228000, "d16008f616ccd035b630294f3bd75ac92f76cddada86925a01bb9e9044d0124b"},
232+
{232000, "4a792ca56385cbaf6d5c87eefbb47781d4fa0fb2b28b1e9a1faae3f7b4fd8a72"},
233+
{236000, "35cefc162199de285efe8f532e7d3a131847ba528726f8b63d4fffd6f7d7cc61"},
234+
{240000, "9008ef78f122f79cee5214f525dcd09e1999a283018033eaec33ff47d8d7553c"},
235+
{244000, "3006c8dee29ef6df2bc3a6cabef428321bc55cbee2570e488f94c1ec38cad240"},
236+
{248000, "8fe4b2bdbca58f942c18bb4cd279db494ff6fad1cf54bd072edcedc57ccb7d91"},
237+
{252000, "0c5d560095a69e55eefc8d2d16b2c75561cee71cdeda353645c4e3d11ccbc991"},
238+
{256000, "e5c6e5ff16883996b9fdff7928ad4e9b9e9d58adce5530eef29181d39e966ec1"},
239+
{260000, "7f6cef4389adebb496defe66e9eee509fbdfdcb8489240e35fc4169a0fee70ff"},
240+
{264000, "32e56053a97e25ebf939ddfeb78c22e039b0b03433aa5888873c6dbd3ed6ed56"},
241+
{268000, "2124d9918d5336a654b2392a6d31e738a5dba39100b90f509bcadd1a1fee8c90"},
242+
{272000, "8a4cd7ba454a175325bdea0abfff81bb61be230319f531d26b42799a8bba942b"},
243+
{276000, "60df2c6dd69583243f0e9fc37405e17b389e2114963017e88e9a98d47fa05f8f"},
244+
{280000, "56848aba4061f8b17ba752617ca14fe6ed0e4d440132e3a94f469ad91d7c6f5c"},
245+
{284000, "e1e315f79f3e50dad4565bf1b9e7b8ecb0fa42b043fe1de6e48569ce363fb209"},
246+
{288000, "7cce7f93442e2ee447d1c4398776e745e8eae12dcfdfb96f4df13823227e9880"},
247+
{292000, "0ddb52388234002246c6ab45675268ba7c4f0955bf6f6e2a2406f4a25e3fc187"},
248+
{296000, "5ef57607f95f185da7cb695eac6f253995704e1805e6c6588fa9745f1066ce1d"},
249+
{300000, "7c13fe58ee1e862f28a8e127670b7b834c2689e4dbd798efad4a9d05f9f1cdee"},
250+
{375000, "4b193fd43754355e27ea232309ec1566da96d793ff91e110d6cce7dff064fdf4"},
251+
{450000, "d268b8467a429ba3ef9f65cedfe0d73fbc29b68efb57a9cabd45845a2e81c823"},
252+
{525000, "3039d0a1b63d284588d38ac55f303f553791090815cae89b653e316b6bb6ae98"},
253+
{600000, "9c5a0f6e78c18c07d02ee9055dac394a95a06bac45399c036b61a0f5a7e45010"},
254+
{675000, "4b8e2475e49b32871e7fe22356dc2588be1be23cddb23178139c1e28fbfe3578"},
255+
{750000, "c387364a1b0e85a4f494568e140af5627fe4cd17bfd60d15f9b17abdce358547"},
256+
{825000, "6e037e44a69be0cf57f9600861ef1cb5119b898b079a2865c222727c2bb427d3"},
257+
{900000, "ec5467538185b89ba2c6334ec1dffdd655f18120aad727bc0aaa7833b1177106"},
258+
{934145, "4a238d5bb901f7362eaa422743e31623b96c3c8bd85bb8c95ad5f858f8950588"}
216259

217260
};
218261

src/CryptoNoteCore/AddBlockErrors.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ enum class AddBlockErrorCode {
2929
ADDED_TO_ALTERNATIVE_AND_SWITCHED,
3030
ALREADY_EXISTS,
3131
REJECTED_AS_ORPHANED,
32-
DESERIALIZATION_FAILED
32+
DESERIALIZATION_FAILED,
33+
FAILED_FTL_CHECK,
34+
FAILED_POISSON_CHECK
3335
};
3436

3537
// custom category:
@@ -55,6 +57,8 @@ class AddBlockErrorCategory : public std::error_category {
5557
case AddBlockErrorCode::ALREADY_EXISTS: return "Block already exists";
5658
case AddBlockErrorCode::REJECTED_AS_ORPHANED: return "Block rejected as orphaned";
5759
case AddBlockErrorCode::DESERIALIZATION_FAILED: return "Deserialization error";
60+
case AddBlockErrorCode::FAILED_FTL_CHECK: return "Failed FTL check";
61+
case AddBlockErrorCode::FAILED_POISSON_CHECK: return "Failed Poisson check";
5862
default: return "Unknown error";
5963
}
6064
}

src/CryptoNoteCore/Core.cpp

+72-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <unordered_set>
2424

2525
#include "Core.h"
26+
#include "Common/int-util.h"
2627
#include "Common/ShuffleGenerator.h"
2728
#include "Common/Math.h"
2829
#include "Common/MemoryInputStream.h"
@@ -269,7 +270,7 @@ uint64_t Core::getBlockTimestampByIndex(uint32_t blockIndex) const {
269270

270271
auto timestamps = chainsLeaves[0]->getLastTimestamps(1, blockIndex, addGenesisBlock);
271272
assert(!(timestamps.size() == 1));
272-
273+
273274
return timestamps[0];
274275
}
275276

@@ -648,11 +649,81 @@ std::error_code Core::addBlock(const CachedBlock& cachedBlock, RawBlock&& rawBlo
648649

649650
notifyObservers(makeDelTransactionMessage(std::move(hashes), Messages::DeleteTransaction::Reason::InBlock));
650651
} else {
652+
651653
cache->pushBlock(cachedBlock, transactions, validatorState, cumulativeBlockSize, emissionChange, currentDifficulty, std::move(rawBlock));
652654
logger(Logging::WARNING) << "Block " << cachedBlock.getBlockHash() << " added to alternative chain. Index: " << (previousBlockIndex + 1);
653655

654656
auto mainChainCache = chainsLeaves[0];
655657
if (cache->getCurrentCumulativeDifficulty() > mainChainCache->getCurrentCumulativeDifficulty()) {
658+
659+
// Poisson check, courtesy of ryo-project
660+
// https://github.com/ryo-currency/ryo-writeups/blob/master/poisson-writeup.md
661+
// For longer reorgs, check if the timestamps are probable - if they aren't the diff algo has failed
662+
// This check is meant to detect an offline bypass of timestamp < time() + ftl check
663+
// It doesn't need to be very strict as it synergises with the median check
664+
const std::vector<BlockTemplate> alt_chain = getAlternativeBlocks();
665+
uint64_t alt_chain_size = getAlternativeBlockCount();
666+
if (alt_chain_size >= CryptoNote::parameters::POISSON_CHECK_TRIGGER)
667+
{
668+
uint64_t high_timestamp = alt_chain.back().timestamp;
669+
Crypto::Hash low_block = alt_chain.front().previousBlockHash;
670+
671+
//Make sure that the high_timestamp is really highest
672+
for (size_t index = 0; index < alt_chain.size(); ++index)
673+
{
674+
if (high_timestamp < alt_chain[index].timestamp)
675+
high_timestamp = alt_chain[index].timestamp;
676+
}
677+
678+
uint64_t block_ftl = CryptoNote::parameters::CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2;
679+
// This would fail later anyway
680+
if (high_timestamp > getAdjustedTime() + block_ftl)
681+
{
682+
logger(Logging::ERROR) << "Attempting to move to an alternate chain, but it failed FTL check! Timestamp: " << high_timestamp << ", limit: " << getAdjustedTime() + block_ftl;
683+
return error::AddBlockErrorCode::FAILED_FTL_CHECK;
684+
}
685+
686+
logger(Logging::WARNING) << "Poisson check triggered by reorg size of " << alt_chain_size;
687+
688+
uint64_t failed_checks = 0, i = 1;
689+
for (; i <= CryptoNote::parameters::POISSON_CHECK_DEPTH; i++)
690+
{
691+
// This means we reached the genesis block
692+
if (low_block == NULL_HASH)
693+
break;
694+
695+
BlockTemplate blk;
696+
blk = getBlockByHash(low_block);
697+
698+
uint64_t low_timestamp = blk.timestamp;
699+
low_block = blk.previousBlockHash;
700+
701+
if (low_timestamp >= high_timestamp)
702+
{
703+
logger(Logging::INFO) << "Skipping check at depth " << i << " due to tampered timestamp on main chain.";
704+
failed_checks++;
705+
continue;
706+
}
707+
708+
double lam = double(high_timestamp - low_timestamp) / double(CryptoNote::parameters::DIFFICULTY_TARGET);
709+
if (calc_poisson_ln(lam, alt_chain_size + i) < CryptoNote::parameters::POISSON_LOG_P_REJECT)
710+
{
711+
logger(Logging::INFO) << "Poisson check at depth " << i << " failed! delta_t: " << (high_timestamp - low_timestamp) << " size: " << alt_chain_size + i;
712+
failed_checks++;
713+
}
714+
}
715+
716+
i--; //Convert to number of checks
717+
logger(Logging::INFO) << "Poisson check result " << failed_checks << " fails out of " << i;
718+
719+
if (failed_checks > i / 2)
720+
{
721+
logger(Logging::ERROR) << "Attempting to move to an alternate chain, but it failed Poisson check! " << failed_checks << " fails out of " << i << " alt_chain_size: " << alt_chain_size;
722+
return error::AddBlockErrorCode::FAILED_POISSON_CHECK;
723+
}
724+
}
725+
726+
656727
size_t endpointIndex =
657728
std::distance(chainsLeaves.begin(), std::find(chainsLeaves.begin(), chainsLeaves.end(), cache));
658729
assert(endpointIndex != chainsStorage.size());

0 commit comments

Comments
 (0)