Skip to content

Commit

Permalink
Change CryptonoteConfig parameters and changed difficulty adjustment …
Browse files Browse the repository at this point in the history
…algorithm back to original

CryptoNoteConfig.h
- reduced initial block size
- reduced maximum number of blocks

Currency.cpp
- changed difficulty adjustment algorithm back to original
-LWMA difficulty does not work to produce 9 second blocks. Blocks were coming out too fast at 2 seconds per block and difficulty was not increasing.
  • Loading branch information
aphivantrakul committed Dec 2, 2018
1 parent 098b6a9 commit c38f556
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 63 deletions.
24 changes: 14 additions & 10 deletions src/CryptoNoteConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,39 @@ namespace CryptoNote {
namespace parameters {

const uint64_t DIFFICULTY_TARGET = 9; // seconds
const uint64_t CRYPTONOTE_MAX_BLOCK_NUMBER = ((uint64_t)(-1)); // 18,446,744,073,709,551,616 blocks

const uint64_t CRYPTONOTE_MAX_BLOCK_NUMBER = 500000000;
const size_t CRYPTONOTE_MAX_BLOCK_BLOB_SIZE = 500000000;
const size_t CRYPTONOTE_MAX_TX_SIZE = 1000000000;
const uint64_t CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 0x6; // all Cash2 addresses start with a '2'
const size_t CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW = 60;
const uint64_t CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT = 3 * DIFFICULTY_TARGET;
const size_t BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW = 11;
const uint64_t CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT = 60 * 60 * 2;
const size_t BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW = 60;
const uint64_t MONEY_SUPPLY = UINT64_C(15000000000000000); // 15,000,000.000000000 total coins
const unsigned EMISSION_SPEED_FACTOR = 24;

static_assert(EMISSION_SPEED_FACTOR <= 8 * sizeof(uint64_t), "Bad EMISSION_SPEED_FACTOR");

const size_t CRYPTONOTE_REWARD_BLOCKS_WINDOW = 60 * 24 * 60 * 60 / DIFFICULTY_TARGET; // number of blocks produced in 60 days
const size_t CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE = 1024 * 1024; //size of block (bytes) after which reward for block calculated using block size, 1 mb
const size_t CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE = 200 * 1024; //size of block (bytes) after which reward for block calculated using block size, 200 kb
const size_t CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE = 600;
const size_t CRYPTONOTE_DISPLAY_DECIMAL_POINT = 9; // number of digits after decimal poin
const uint64_t MINIMUM_FEE = 0; // free transactions
const uint64_t DEFAULT_DUST_THRESHOLD = MINIMUM_FEE;
const uint64_t MAX_MIXIN = 3;
const uint64_t EXPECTED_NUMBER_OF_BLOCKS_PER_DAY = 24 * 60 * 60 / DIFFICULTY_TARGET;
const size_t DIFFICULTY_WINDOW = 158; // blocks, N = int(45 * (600 / T) ^ 0.3)), N is the difficulty window, T is the target time
const size_t DIFFICULTY_CUT = 40; // timestamps to cut after sorting (originally 60)
const size_t DIFFICULTY_WINDOW = 3600; // blocks, number of blocks expected in 9 hours
const size_t DIFFICULTY_CUT = 60; // timestamps to cut after sorting
const size_t DIFFICULTY_LAG = 15;

static_assert(2 * DIFFICULTY_CUT <= DIFFICULTY_WINDOW - 2, "Bad DIFFICULTY_WINDOW or DIFFICULTY_CUT");
const size_t MAX_BLOCK_SIZE_INITIAL = 2 * 1024 * 1024; // 2 mb

const size_t MAX_BLOCK_SIZE_INITIAL = 400 * 1024; // 400 kb
const uint64_t MAX_BLOCK_SIZE_GROWTH_SPEED_NUMERATOR = 100 * 1024;
const uint64_t MAX_BLOCK_SIZE_GROWTH_SPEED_DENOMINATOR = 365 * 24 * 60 * 60 / DIFFICULTY_TARGET;
const uint64_t CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS = 1;
const uint64_t CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS = DIFFICULTY_TARGET * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS;
const uint64_t CRYPTONOTE_MEMPOOL_TX_LIVETIME = 60 * 5; //seconds, 5 minutes
const uint64_t CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME = 60 * 5; //seconds, 5 minutes
const uint64_t CRYPTONOTE_MEMPOOL_TX_LIVETIME = 60 * 60; //seconds, 1 hour
const uint64_t CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME = 60 * 60; //seconds, 1 hour
const uint64_t CRYPTONOTE_NUMBER_OF_PERIODS_TO_FORGET_TX_DELETED_FROM_POOL = 1; // CRYPTONOTE_NUMBER_OF_PERIODS_TO_FORGET_TX_DELETED_FROM_POOL * CRYPTONOTE_MEMPOOL_TX_LIVETIME = time to forget tx
const size_t FUSION_TX_MAX_SIZE = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE * 30 / 100;
const size_t FUSION_TX_MIN_INPUT_COUNT = 12;
Expand Down
100 changes: 47 additions & 53 deletions src/CryptoNoteCore/Currency.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// Copyright (c) 2011-2016 The Cryptonote developers
// Copyright (c) 2016-2018 zawy12
// Copyright (c) 2016-2018, The Karbowanec developers
// Copyright (c) 2018 The Cash2 developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
Expand Down Expand Up @@ -87,7 +89,7 @@ bool Currency::generateGenesisBlock() {
}

// genesis block message
// "December 5, 2018. To my mom, dad, and sister, I love you. Bitcoin block 549852 hash 00000000000000000013da30f52759345e332c75c9ca40450f08eb04a342c522"
// "December 5, 2018. To my mom, dad, and sister, I love you. Bitcoin block 551105 hash 000000000000000000174b45aea57bb0ce896fbfcbe699645736c1eb3f7c667a"
m_genesisBlock.baseTransaction.extra =
{
0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x35,
Expand All @@ -97,14 +99,14 @@ bool Currency::generateGenesisBlock() {
0x73, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x49, 0x20, 0x6c, 0x6f,
0x76, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x2e, 0x20, 0x42, 0x69,
0x74, 0x63, 0x6f, 0x69, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
0x6b, 0x20, 0x35, 0x34, 0x39, 0x38, 0x35, 0x32, 0x20, 0x68,
0x6b, 0x20, 0x35, 0x35, 0x31, 0x31, 0x30, 0x35, 0x20, 0x68,
0x61, 0x73, 0x68, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x31, 0x33, 0x64, 0x61, 0x33, 0x30, 0x66, 0x35,
0x32, 0x37, 0x35, 0x39, 0x33, 0x34, 0x35, 0x65, 0x33, 0x33,
0x32, 0x63, 0x37, 0x35, 0x63, 0x39, 0x63, 0x61, 0x34, 0x30,
0x34, 0x35, 0x30, 0x66, 0x30, 0x38, 0x65, 0x62, 0x30, 0x34,
0x61, 0x33, 0x34, 0x32, 0x63, 0x35, 0x32, 0x32
0x30, 0x30, 0x31, 0x37, 0x34, 0x62, 0x34, 0x35, 0x61, 0x65,
0x61, 0x35, 0x37, 0x62, 0x62, 0x30, 0x63, 0x65, 0x38, 0x39,
0x36, 0x66, 0x62, 0x66, 0x63, 0x62, 0x65, 0x36, 0x39, 0x39,
0x36, 0x34, 0x35, 0x37, 0x33, 0x36, 0x63, 0x31, 0x65, 0x62,
0x33, 0x66, 0x37, 0x63, 0x36, 0x36, 0x37, 0x61
};

m_genesisBlock.timestamp = 0;
Expand Down Expand Up @@ -374,69 +376,61 @@ bool Currency::parseAmount(const std::string& str, uint64_t& amount) const {
return Common::fromString(strAmount, amount);
}

difficulty_type Currency::nextDifficulty(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulativeDifficulties) const
{
difficulty_type Currency::nextDifficulty(std::vector<uint64_t> timestamps,
std::vector<difficulty_type> cumulativeDifficulties) const {
assert(m_difficultyWindow >= 2);

if (timestamps.size() > m_difficultyWindow) {
timestamps.resize(m_difficultyWindow);
cumulativeDifficulties.resize(m_difficultyWindow);
}

assert(timestamps.size() == cumulativeDifficulties.size());
assert(timestamps.size() <= m_difficultyWindow);
size_t length = timestamps.size();
assert(length == cumulativeDifficulties.size());
assert(length <= m_difficultyWindow);
if (length <= 1) {
return 1;
}

// LWMA-2 difficulty algorithm
// Copyright (c) 2017-2018 Zawy, MIT License
// https://github.com/zawy12/difficulty-algorithms/issues/3
// See commented version for required config file changes.
// N = int(45 * (600 / T) ^ 0.3));
if (length < 10)
{
return 1000000;
}

int64_t T = m_difficultyTarget; // target solvetime seconds
int64_t N = m_difficultyWindow; // N=45, 60, and 90 for T=600, 120, 60.
int64_t FTL = m_blockFutureTimeLimit; // < 3xT
int64_t L(0), ST, sum_3_ST(0), next_D, prev_D;

// If it's a new coin, do startup code.
// Increase difficulty_guess if it needs to be much higher, but guess lower than lowest guess.
uint64_t difficulty_guess = 100000;
sort(timestamps.begin(), timestamps.end());

// set difficulty of genesis block to 1
if (timestamps.size() == 0)
{
return 1;
size_t cutBegin, cutEnd;
assert(2 * m_difficultyCut <= m_difficultyWindow - 2);
if (length <= m_difficultyWindow - 2 * m_difficultyCut) {
cutBegin = 0;
cutEnd = length;
} else {
cutBegin = (length - (m_difficultyWindow - 2 * m_difficultyCut) + 1) / 2;
cutEnd = cutBegin + (m_difficultyWindow - 2 * m_difficultyCut);
}
assert(/*cut_begin >= 0 &&*/ cutBegin + 2 <= cutEnd && cutEnd <= length);
uint64_t timeSpan = timestamps[cutEnd - 1] - timestamps[cutBegin];
if (timeSpan == 0) {
timeSpan = 1;
}

if (timestamps.size() <= 10 )
{
return difficulty_guess;
difficulty_type totalWork = cumulativeDifficulties[cutEnd - 1] - cumulativeDifficulties[cutBegin];
assert(totalWork > 0);

uint64_t low, high;
low = mul128(totalWork, m_difficultyTarget, &high);
if (high != 0 || low + timeSpan - 1 < low) {
return 0;
}

if (timestamps.size() < static_cast<uint64_t>(N + 1))
{
N = timestamps.size() - 1;
}

for (int64_t i = 1; i <= N; i++) {
ST = std::max(-FTL, std::min( static_cast<int64_t>(timestamps[i]) - static_cast<int64_t>(timestamps[i - 1]), 6 * T));
L += ST * i ;
if (i > N - 3)
{
sum_3_ST += ST;
}
}
next_D = (static_cast<int64_t>(cumulativeDifficulties[N] - cumulativeDifficulties[0]) * T * (N + 1) * 99) / (100 * 2 * L);

// implement LWMA-2 changes from LWMA. Large coins change 8 to 7, and 110 to 107.
// N = 90 coins change 110 to 107. The 110 setting may turn out to be too high. Waiting on live data.
prev_D = cumulativeDifficulties[N] - cumulativeDifficulties[N - 1];
next_D = std::max((prev_D * 67) / 100, std::min(next_D, (prev_D * 150) / 100));
if (sum_3_ST < (8 * T) / 10)
difficulty_type difficulty = (low + timeSpan - 1) / timeSpan;

if (difficulty < 30000000000000) // 10,000,000,000,000 per miner expected to mine Cash2 on launch day
{
next_D = std::max(next_D, (prev_D * 110) / 100);
return 30000000000000;
}

return static_cast<uint64_t>(next_D);
return difficulty;
}

bool Currency::checkProofOfWork(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic,
Expand Down

2 comments on commit c38f556

@cryptozeny
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you trying T=9? Its awesome if it is working correctly... 🤔

@zawy12
Copy link

@zawy12 zawy12 commented on c38f556 Dec 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copy-pasted your LWMA2 to my testing program and took out the resize-related statements including the difficulty guess and the solvetime was exactly 9 like it should be. If you want to use LWMA-1 or LWMA-3 (the same as your but the exploit is removed) then you should copy-paste the LWMA from the LWMA page. It's written now so that you you only need to change send it the correct variables. It does not need modification inside the algorithm which should prevent a lot of problems (it's now plug-and-play for CN-type coins) except that where indicated you un-comment some lines to make it work like LWMA-3 instead of LWMA-1.

The core code of your LWMA-2 calculation (that should not be used by anyone) which works correctly (except for the exploit) is:

difficulty_type LWMA2( std::vector<uint64_t> timestamps, 
   std::vector<difficulty_type> cumulative_difficulties, uint64_t uT, uint64_t uN)
{
  int64_t T = uT, N = uN, FTL = 3*T, L(0), ST, sum_3_ST(0), next_D, prev_D;
  
  for (int64_t i = 1; i <= N; i++) {  
    ST = std::max(-FTL, std::min( static_cast<int64_t>(timestamps[i]) - 
                 static_cast<int64_t>(timestamps[i - 1]), 6 * T));
    L +=  ST * i ; 
    if (i > N - 3) { sum_3_ST += ST; } 
  }
  next_D = (static_cast<int64_t>(cumulative_difficulties[N]-cumulative_difficulties[0]) * 
                     T*(N+1)*99)/(100*2*L);
  prev_D = cumulative_difficulties[N] - cumulative_difficulties[N - 1];
  next_D = std::max((prev_D * 67) / 100, std::min(next_D, (prev_D * 150) / 100));
  if (sum_3_ST < (8*T)/10) { next_D = std::max(next_D, (prev_D * 110) / 100); }

  return static_cast<uint64_t>(next_D);
}

Please sign in to comment.