Skip to content

Commit e65db6b

Browse files
author
X-CASH-official
committed
Changing difficulty algorithm to Zawy12's LWMA-2
Changing difficulty algorithm to Zawy12's LWMA-2
1 parent cd14f7e commit e65db6b

File tree

7 files changed

+147
-16
lines changed

7 files changed

+147
-16
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ If you want to help out, see [CONTRIBUTING](CONTRIBUTING.md) for a set of guidel
4545
| ------------------------------ | -----------| ----------------- | ---------------------------------------------------------------------------------- |
4646
| 0 | 22-07-2018 | v1 | Genesis block |
4747
| 1 | 22-07-2018 | v7 | Start of the blockchain |
48-
| 95000 | 01-10-2018 | v8 | Adding public transactions (transactions with mixin 0) |
48+
| 95085 | 08-10-2018 | v8 | changing difficulty algorithm to [LWMA-2 developed by Zawy12](https://github.com/zawy12/difficulty-algorithms/issues/3) |
49+
| 145000 | 01-11-2018 | v9 | Adding public transactions, bullet proofs, increased and static ringsize and more! |
4950

5051
Note future releases block heights and dates may change, so make sure to frequently check github, our website, the forums, etc. for the most up to date information.
5152

src/cryptonote_basic/difficulty.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,66 @@ namespace cryptonote {
162162
return (low + time_span - 1) / time_span;
163163
}
164164

165+
// LWMA difficulty algorithm
166+
// Background: https://github.com/zawy12/difficulty-algorithms/issues/3
167+
// Copyright (c) 2017-2018 Zawy (pseudocode)
168+
// MIT license http://www.opensource.org/licenses/mit-license.php
169+
// Copyright (c) 2018 Wownero Inc., a Monero Enterprise Alliance partner company
170+
// Copyright (c) 2018 The Karbowanec developers (initial code)
171+
// Copyright (c) 2018 Haven Protocol (refinements)
172+
// Degnr8, Karbowanec, Masari, Bitcoin Gold, Bitcoin Candy, and Haven have contributed.
173+
// This algorithm is: next_difficulty = harmonic_mean(Difficulties) * T / LWMA(Solvetimes)
174+
// The harmonic_mean(Difficulties) = 1/average(Targets) so it is also:
175+
// next_target = avg(Targets) * LWMA(Solvetimes) / T.
176+
// This is "the best algorithm" because it has lowest root-mean-square error between
177+
// needed & actual difficulty during hash attacks while having the lowest standard
178+
// deviation during stable hashrate. That is, it's the fastest for a given stability and vice versa.
179+
// Do not use "if solvetime < 1 then solvetime = 1" which allows a catastrophic exploit.
180+
// Do not sort timestamps. "Solvetimes" and "LWMA" variables must allow negatives.
181+
// Do not use MTP as most recent block. Do not use (POW)Limits, filtering, or tempering.
182+
// Do not forget to set N (aka DIFFICULTY_WINDOW in Cryptonote) to recommendation below.
183+
// The nodes' future time limit (FTL) aka CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT needs to
184+
// be reduced from 60*60*2 to 500 seconds to prevent timestamp manipulation from miner's with
185+
// > 50% hash power. If this is too small, it can be increased to 1000 at a cost in protection.
186+
// Cryptonote clones: #define DIFFICULTY_BLOCKS_COUNT_V2 DIFFICULTY_WINDOW_V2 + 1
187+
// difficulty_type should be uint64_t
188+
189+
difficulty_type next_difficulty_V8(std::vector<std::uint64_t> timestamps,std::vector<difficulty_type> cumulative_difficulties, uint64_t block_height) {
190+
int64_t T = DIFFICULTY_TARGET_V8; // target solvetime seconds
191+
int64_t N = DIFFICULTY_WINDOW_V8; // N=45, 60, and 90 for T=600, 120, 60.
192+
int64_t L(0), ST, sum_3_ST(0), next_D, prev_D;
193+
194+
// Make sure timestamps & CD vectors are not bigger than they are supposed to be.
195+
assert(timestamps.size() == cumulative_difficulties.size() &&
196+
timestamps.size() <= static_cast<uint64_t>(N+1) );
197+
// If it's a new coin, do startup code.
198+
// Increase difficulty_guess if it needs to be much higher, but guess lower than lowest guess.
199+
uint64_t difficulty_guess = HF_VERSION_LWMA_STARTING_DIFFICULTY;
200+
if (timestamps.size() <= 10 ) { return difficulty_guess; }
201+
// code to lower the difficulty if the blockchain is already at a too high difficulty and its not a new coin
202+
if (block_height <= (HF_VERSION_LWMA_DIFFICULTY_BLOCK_HEIGHT + static_cast<uint64_t>(N +1))) {return difficulty_guess;}
203+
// Use "if" instead of "else if" in case vectors are incorrectly N all the time instead of N+1.
204+
if ( timestamps.size() < static_cast<uint64_t>(N +1) ) { N = timestamps.size()-1; }
205+
206+
// N is most recently solved block. i must be signed
207+
for ( int64_t i = 1; i <= N; i++) {
208+
ST = static_cast<int64_t>(timestamps[i]) - static_cast<int64_t>(timestamps[i-1]);
209+
ST = std::max(-5*T, std::min(ST, 6*T));
210+
L += ST * i ; // Give more weight to most recent blocks.
211+
// Do following inside loop to capture -FTL and +6*T limitations.
212+
if ( i > N-3 ) { sum_3_ST += ST; }
213+
}
214+
// Calculate next_D = avgD * T / LWMA(STs) using integer math
215+
// Do a cast in case L goes negative. Do not limit L. That's done by limiting next_D below.
216+
next_D = (static_cast<int64_t>(cumulative_difficulties[N] - cumulative_difficulties[0])*T*(N+1)*99)/(100*2*L);
217+
// implement LWMA-2 changes from LWMA.
218+
prev_D = cumulative_difficulties[N] - cumulative_difficulties[N-1];
219+
// The following limits are the generous max that should reasonably occur.
220+
next_D = std::max( (prev_D*67)/100, std::min(next_D, (prev_D*150)/100 ));
221+
// N = 90 coins change 108 to 106.
222+
if ( sum_3_ST < (8*T)/10) { next_D = std::max(next_D,(prev_D*108)/100); }
223+
return static_cast<uint64_t>(next_D);
224+
// next_Target = sumTargets*L*2/0.998/T/(N+1)/N/N; // To show the difference.
225+
}
226+
165227
}

src/cryptonote_basic/difficulty.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,5 @@ namespace cryptonote
5353
*/
5454
bool check_hash(const crypto::hash &hash, difficulty_type difficulty);
5555
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
56+
difficulty_type next_difficulty_V8(std::vector<std::uint64_t> timestamps,std::vector<difficulty_type> cumulative_difficulties, uint64_t block_height);
5657
}

src/cryptonote_config.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,16 @@
8484
#define PREMINE_BLOCK_HEIGHT 1
8585
#define PREMINE_BLOCK_REWARD ((uint64_t)(40000000000000000))
8686

87+
// LWMA difficulty
88+
#define HF_VERSION_LWMA_DIFFICULTY 8
89+
#define HF_VERSION_LWMA_DIFFICULTY_BLOCK_HEIGHT 95085
90+
#define HF_VERSION_LWMA_STARTING_DIFFICULTY 30000000
91+
#define DIFFICULTY_TARGET_V8 60 // seconds
92+
#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V8 30 // (11)
93+
#define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V8 60*4 // (60*10)
94+
#define DIFFICULTY_WINDOW_V8 120 // (60)
95+
#define DIFFICULTY_BLOCKS_COUNT_V8 121 //DIFFICULTY_WINDOW_V8 + 1 has to be +1 so N = N
96+
8797
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 DIFFICULTY_TARGET_V1 * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS
8898
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2 DIFFICULTY_TARGET_V2 * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS
8999
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS 1

src/cryptonote_core/blockchain.cpp

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,10 @@ static const struct {
9595
// version 7 starts from block 1, which is on or around July 18, 2018. This version includes the new POW cryptonight_v7 algorithm.
9696
{ 7, 1, 0, 1531962000 },
9797

98-
// version 8 starts from block 157000, which is on or around Nov 14, 2018. This version includes bullet proofs, a substantial increase in the ringsize, a fixed ring size, and a few other items.
99-
{ 8, 157000, 0, 1541809000 },
98+
// version 8 starts from block 95085, which is on or around Oct 8, 2018. This version includes a new difficulty algorithm.
99+
{ 8, 95085, 0, 1538524800 },
100+
101+
// version 9 starts from block 157000, which is on or around Nov 14, 2018. This version includes bullet proofs, public transactions, a substantial increase in the ringsize, a fixed ring size, and a few other items.
100102
};
101103
static const uint64_t mainnet_hard_fork_version_1_till = 1;
102104

@@ -112,8 +114,10 @@ static const struct {
112114
// version 7 starts from block 1, which is on or around July 18, 2018. This version includes the new POW cryptonight_v7 algorithm.
113115
{ 7, 1, 0, 1531962000 },
114116

115-
// version 8 starts from block 146000, which is on or around Nov 7, 2018. This version includes bullet proofs, a substantial increase in the ringsize, a fixed ring size, and a few other items.
116-
{ 8, 146000, 0, 1541203200 },
117+
// version 8 starts from block 105000, which is on or around Oct 8, 2018. This version includes a new difficulty algorithm.
118+
{ 8, 105000, 0, 1538524800 },
119+
120+
// version 9 starts from block 146000, which is on or around Nov 14, 2018. This version includes bullet proofs, public transactions, a substantial increase in the ringsize, a fixed ring size, and a few other items.
117121
};
118122
static const uint64_t testnet_hard_fork_version_1_till = 1;
119123

@@ -784,11 +788,16 @@ bool Blockchain::get_block_by_hash(const crypto::hash &h, block &blk, bool *orph
784788
// less blocks than desired if there aren't enough.
785789
difficulty_type Blockchain::get_difficulty_for_next_block()
786790
{
791+
difficulty_type diff;
792+
uint64_t block_height = m_db->height();
793+
uint8_t version = get_current_hard_fork_version();
794+
if (version < HF_VERSION_LWMA_DIFFICULTY)
795+
{
787796
LOG_PRINT_L3("Blockchain::" << __func__);
788797
CRITICAL_REGION_LOCAL(m_blockchain_lock);
789798
std::vector<uint64_t> timestamps;
790799
std::vector<difficulty_type> difficulties;
791-
auto height = m_db->height();
800+
auto height = m_db->height();
792801
// ND: Speedup
793802
// 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty,
794803
// then when the next block difficulty is queried, push the latest height data and
@@ -799,12 +808,10 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
799808
uint64_t index = height - 1;
800809
m_timestamps.push_back(m_db->get_block_timestamp(index));
801810
m_difficulties.push_back(m_db->get_block_cumulative_difficulty(index));
802-
803811
while (m_timestamps.size() > DIFFICULTY_BLOCKS_COUNT)
804812
m_timestamps.erase(m_timestamps.begin());
805813
while (m_difficulties.size() > DIFFICULTY_BLOCKS_COUNT)
806814
m_difficulties.erase(m_difficulties.begin());
807-
808815
m_timestamps_and_difficulties_height = height;
809816
timestamps = m_timestamps;
810817
difficulties = m_difficulties;
@@ -814,21 +821,71 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
814821
size_t offset = height - std::min < size_t > (height, static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT));
815822
if (offset == 0)
816823
++offset;
817-
818824
timestamps.clear();
819825
difficulties.clear();
820826
for (; offset < height; offset++)
821827
{
822828
timestamps.push_back(m_db->get_block_timestamp(offset));
823829
difficulties.push_back(m_db->get_block_cumulative_difficulty(offset));
824830
}
825-
826831
m_timestamps_and_difficulties_height = height;
827832
m_timestamps = timestamps;
828833
m_difficulties = difficulties;
829834
}
830835
size_t target = get_difficulty_target();
831-
return next_difficulty(timestamps, difficulties, target);
836+
diff = next_difficulty(timestamps, difficulties, target);
837+
}
838+
if (version >= HF_VERSION_LWMA_DIFFICULTY)
839+
{
840+
LOG_PRINT_L3("Blockchain::" << __func__);
841+
CRITICAL_REGION_LOCAL(m_blockchain_lock);
842+
std::vector<uint64_t> timestamps;
843+
std::vector<difficulty_type> difficulties;
844+
auto height = m_db->height();
845+
size_t difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V8;
846+
// ND: Speedup
847+
// 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty,
848+
// then when the next block difficulty is queried, push the latest height data and
849+
// pop the oldest one from the list. This only requires 1x read per height instead
850+
// of doing 735 (DIFFICULTY_BLOCKS_COUNT).
851+
if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= difficulty_blocks_count)
852+
{
853+
uint64_t index = height - 1;
854+
m_timestamps.push_back(m_db->get_block_timestamp(index));
855+
m_difficulties.push_back(m_db->get_block_cumulative_difficulty(index));
856+
while (m_timestamps.size() > difficulty_blocks_count)
857+
m_timestamps.erase(m_timestamps.begin());
858+
while (m_difficulties.size() > difficulty_blocks_count)
859+
m_difficulties.erase(m_difficulties.begin());
860+
m_timestamps_and_difficulties_height = height;
861+
timestamps = m_timestamps;
862+
difficulties = m_difficulties;
863+
}
864+
else
865+
{
866+
size_t offset = height - std::min < size_t > (height, static_cast<size_t>(difficulty_blocks_count));
867+
if (offset == 0)
868+
++offset;
869+
timestamps.clear();
870+
difficulties.clear();
871+
if (height > offset)
872+
{
873+
timestamps.reserve(height - offset);
874+
difficulties.reserve(height - offset);
875+
}
876+
for (; offset < height; offset++)
877+
{
878+
timestamps.push_back(m_db->get_block_timestamp(offset));
879+
difficulties.push_back(m_db->get_block_cumulative_difficulty(offset));
880+
}
881+
m_timestamps_and_difficulties_height = height;
882+
m_timestamps = timestamps;
883+
m_difficulties = difficulties;
884+
}
885+
size_t target = get_difficulty_target();
886+
diff = next_difficulty_V8(timestamps, difficulties, block_height);
887+
}
888+
return diff;
832889
}
833890
//------------------------------------------------------------------
834891
// This function removes blocks from the blockchain until it gets to the
@@ -2487,12 +2544,12 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
24872544
}
24882545
}
24892546

2490-
// from v8, allow bulletproofs
2491-
if (hf_version < 8) {
2547+
// from v9, allow bulletproofs
2548+
if (hf_version < 9) {
24922549
const bool bulletproof = tx.rct_signatures.type == rct::RCTTypeFullBulletproof || tx.rct_signatures.type == rct::RCTTypeSimpleBulletproof;
24932550
if (bulletproof || !tx.rct_signatures.p.bulletproofs.empty())
24942551
{
2495-
MERROR("Bulletproofs are not allowed before v8");
2552+
MERROR("Bulletproofs are not allowed before v9");
24962553
tvc.m_invalid_output = true;
24972554
return false;
24982555
}

src/version.cpp.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#define DEF_XCASH_VERSION_TAG "@VERSIONTAG@"
2-
#define DEF_XCASH_VERSION "1.2.2"
2+
#define DEF_XCASH_VERSION "1.3.0"
33
#define DEF_XCASH_RELEASE_NAME ""
44
#define DEF_XCASH_VERSION_FULL DEF_XCASH_VERSION "-" DEF_XCASH_VERSION_TAG
55

src/wallet/wallet2.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ size_t estimate_tx_size(bool use_rct, int n_inputs, int mixin, int n_outputs, si
576576

577577
uint8_t get_bulletproof_fork()
578578
{
579-
return 8;
579+
return 9;
580580
}
581581

582582
crypto::hash8 get_short_payment_id(const tools::wallet2::pending_tx &ptx, hw::device &hwdev)

0 commit comments

Comments
 (0)