2021-06-18 01:06:51 +02:00
// Copyright (c) 2018-2021, The Loki Project
2015-09-01 10:40:33 +02:00
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2021-06-18 01:06:51 +02:00
# include <array>
2015-09-01 10:40:33 +02:00
# include "hardfork.h"
2021-06-18 01:06:51 +02:00
namespace cryptonote {
2019-09-13 07:46:15 +02:00
// version 7 from the start of the blockchain, inhereted from Monero mainnet
2021-06-18 01:06:51 +02:00
static constexpr std : : array mainnet_hard_forks =
{
hard_fork { 7 , 0 , 0 , 1503046577 } , // Loki 0.1: Loki is born
hard_fork { 8 , 0 , 64324 , 1533006000 /*2018-07-31 03:00 UTC*/ } , // Loki 0.2: New emissions schedule
hard_fork { 9 , 0 , 101250 , 1537444800 /*2018-09-20 12:00 UTC*/ } , // Loki 1: Service nodes launched
hard_fork { 10 , 0 , 161849 , 1544743800 /*2018-12-13 23:30 UTC*/ } , // Loki 2: Bulletproofs, gov fee batching
hard_fork { 11 , 0 , 234767 , 1554170400 /*2019-03-26 13:00 AEDT*/ } , // Loki 3: Infinite staking, CN-Turtle
hard_fork { 12 , 0 , 321467 , 1563940800 /*2019-07-24 14:00 AEDT*/ } , // Loki 4: Checkpointing, RandomXL, decommissioning, Storage Server launched
hard_fork { 13 , 0 , 385824 , 1571850000 /*2019-10-23 19:00 AEDT*/ } , // Loki 5: Checkpointing enforced
hard_fork { 14 , 0 , 442333 , 1578528000 /*2020-01-09 00:00 UTC*/ } , // Loki 6: Blink, Lokinet launched on mainnet
hard_fork { 15 , 0 , 496969 , 1585105200 /*2020-03-25 14:00 AEDT (03:00 UTC)*/ } , // Loki 7: ONS (Session)
hard_fork { 16 , 0 , 641111 , 1602464400 /*2020-10-12 12:00 AEDT (01:00 UTC)*/ } , // Loki 8: Pulse
hard_fork { 17 , 0 , 770711 , 1618016400 /*Saturday, April 10, 2021 1:00:00 UTC*/ } , // Oxen 8: Eliminate 6/block emissions after 180 days (not a separate release)
hard_fork { 18 , 0 , 785000 , 1619736143 /*Thursday, April 29, 2021 22:42:23 UTC*/ } , // Oxen 9: Timesync, new proofs, reasons, wallet ONS
2021-07-06 05:06:26 +02:00
hard_fork { 18 , 1 , 839009 , 1626217200 /*Tuesday, July 13, 2021 23:00 UTC */ } , // Oxen 9.2: mandatory SS 2.2.0 & lokinet 0.9.5 updates
2019-09-13 07:46:15 +02:00
} ;
2021-06-18 01:06:51 +02:00
static constexpr std : : array testnet_hard_forks =
{
hard_fork { 7 , 0 , 0 , 1533631121 } , // Testnet was rebooted during Loki 3 development
hard_fork { 8 , 0 , 2 , 1533631122 } ,
hard_fork { 9 , 0 , 3 , 1533631123 } ,
hard_fork { 10 , 0 , 4 , 1542681077 } ,
hard_fork { 11 , 0 , 5 , 1551223964 } ,
hard_fork { 12 , 0 , 75471 , 1561608000 } , // 2019-06-28 14:00 AEDT
hard_fork { 13 , 0 , 127028 , 1568440800 } , // 2019-09-13 16:00 AEDT
hard_fork { 14 , 0 , 174630 , 1575075600 } , // 2019-11-30 07:00 UTC
hard_fork { 15 , 0 , 244777 , 1583940000 } , // 2020-03-11 15:20 UTC
hard_fork { 16 , 0 , 382222 , 1600468200 } , // 2020-09-18 22:30 UTC
hard_fork { 17 , 0 , 447275 , 1608276840 } , // 2020-12-18 05:34 UTC
hard_fork { 18 , 0 , 501750 , 1616631051 } , // 2021-03-25 12:10 UTC
hard_fork { 18 , 1 , 578637 , 1624040400 } , // 2021-06-18 18:20 UTC
2022-04-29 01:51:14 +02:00
hard_fork { 19 , 0 , 732355 , 1650402545 } ,
2019-09-13 07:46:15 +02:00
} ;
2021-06-18 01:06:51 +02:00
static constexpr std : : array devnet_hard_forks =
2019-09-13 07:46:15 +02:00
{
2021-06-18 01:06:51 +02:00
hard_fork { 7 , 0 , 0 , 1599848400 } ,
hard_fork { 11 , 0 , 2 , 1599848400 } ,
hard_fork { 12 , 0 , 3 , 1599848400 } ,
hard_fork { 13 , 0 , 4 , 1599848400 } ,
hard_fork { 15 , 0 , 5 , 1599848400 } ,
2022-04-29 01:51:14 +02:00
hard_fork { 16 , 0 , 100 , 1599848400 } ,
hard_fork { 17 , 0 , 151 , 1599848400 } ,
hard_fork { 18 , 0 , 152 , 1599848400 } ,
hard_fork { 19 , 0 , 153 , 1599848400 } ,
2019-09-13 07:46:15 +02:00
} ;
2019-09-17 08:08:37 +02:00
2021-06-18 01:06:51 +02:00
template < size_t N >
static constexpr bool is_ordered ( const std : : array < hard_fork , N > & forks ) {
if ( N = = 0 | | forks [ 0 ] . version < 7 )
2015-09-01 10:40:33 +02:00
return false ;
2021-06-18 01:06:51 +02:00
for ( size_t i = 1 ; i < N ; i + + ) {
auto & hf = forks [ i ] ;
auto & prev = forks [ i - 1 ] ;
if ( // [major,snoderevision] pair must be strictly increasing (lexicographically)
std : : make_pair ( hf . version , hf . snode_revision ) < = std : : make_pair ( prev . version , prev . snode_revision )
// height must be strictly increasing; time must be weakly increasing
| | hf . height < = prev . height | | hf . time < prev . time )
return false ;
2015-09-01 10:40:33 +02:00
}
return true ;
}
2021-06-18 01:06:51 +02:00
static_assert ( is_ordered ( mainnet_hard_forks ) ,
" Invalid mainnet hard forks: version must start at 7, major versions and heights must be strictly increasing, and timestamps must be non-decreasing " ) ;
static_assert ( is_ordered ( testnet_hard_forks ) ,
" Invalid testnet hard forks: version must start at 7, versions and heights must be strictly increasing, and timestamps must be non-decreasing " ) ;
static_assert ( is_ordered ( devnet_hard_forks ) ,
" Invalid devnet hard forks: version must start at 7, versions and heights must be strictly increasing, and timestamps must be non-decreasing " ) ;
2015-09-26 17:22:57 +02:00
2021-06-18 01:06:51 +02:00
std : : vector < hard_fork > fakechain_hardforks ;
2015-09-26 17:22:57 +02:00
2021-06-18 01:06:51 +02:00
std : : pair < const hard_fork * , const hard_fork * > get_hard_forks ( network_type type )
2015-09-01 10:40:33 +02:00
{
2021-06-18 01:06:51 +02:00
if ( type = = network_type : : MAINNET ) return { & mainnet_hard_forks [ 0 ] , & mainnet_hard_forks [ mainnet_hard_forks . size ( ) ] } ;
if ( type = = network_type : : TESTNET ) return { & testnet_hard_forks [ 0 ] , & testnet_hard_forks [ testnet_hard_forks . size ( ) ] } ;
if ( type = = network_type : : DEVNET ) return { & devnet_hard_forks [ 0 ] , & devnet_hard_forks [ devnet_hard_forks . size ( ) ] } ;
if ( type = = network_type : : FAKECHAIN ) return { fakechain_hardforks . data ( ) , fakechain_hardforks . data ( ) + fakechain_hardforks . size ( ) } ;
return { nullptr , nullptr } ;
2015-10-16 20:38:44 +02:00
}
2019-01-01 19:26:46 +01:00
2021-06-18 01:06:51 +02:00
std : : pair < std : : optional < uint64_t > , std : : optional < uint64_t > >
get_hard_fork_heights ( network_type nettype , uint8_t version ) {
std : : pair < std : : optional < uint64_t > , std : : optional < uint64_t > > found ;
for ( auto [ it , end ] = get_hard_forks ( nettype ) ; it ! = end ; it + + ) {
if ( it - > version > version ) { // This (and anything else) are in the future
if ( found . first ) // Found something suitable in the previous iteration, so one before this hf is the max
found . second = it - > height - 1 ;
2019-01-01 19:26:46 +01:00
break ;
2021-07-09 07:55:47 +02:00
} else if ( it - > version = = version & & ! found . first ) {
2021-06-18 01:06:51 +02:00
found . first = it - > height ;
2015-09-01 10:40:33 +02:00
}
}
2021-06-18 01:06:51 +02:00
return found ;
2015-09-01 10:40:33 +02:00
}
2021-06-18 01:06:51 +02:00
uint8_t hard_fork_ceil ( network_type nettype , uint8_t version ) {
auto [ it , end ] = get_hard_forks ( nettype ) ;
for ( ; it ! = end ; it + + )
if ( it - > version > = version )
return it - > version ;
2015-09-01 10:40:33 +02:00
2021-06-18 01:06:51 +02:00
return version ;
2015-09-01 10:40:33 +02:00
}
2021-06-18 01:06:51 +02:00
std : : pair < uint8_t , uint8_t >
get_network_version_revision ( network_type nettype , uint64_t height ) {
std : : pair < uint8_t , uint8_t > result ;
for ( auto [ it , end ] = get_hard_forks ( nettype ) ; it ! = end ; it + + ) {
if ( it - > height < = height )
result = { it - > version , it - > snode_revision } ;
else
break ;
2015-11-09 22:22:32 +01:00
}
2021-06-18 01:06:51 +02:00
return result ;
2015-11-09 22:22:32 +01:00
}
2021-06-18 01:06:51 +02:00
bool is_hard_fork_at_least ( network_type type , uint8_t version , uint64_t height ) {
return get_network_version ( type , height ) > = version ;
2015-12-19 15:52:30 +01:00
}
2021-06-18 01:06:51 +02:00
std : : pair < uint8_t , uint8_t >
get_ideal_block_version ( network_type nettype , uint64_t height )
2016-08-12 20:19:25 +02:00
{
2021-06-18 01:06:51 +02:00
std : : pair < uint8_t , uint8_t > result ;
for ( auto [ it , end ] = get_hard_forks ( nettype ) ; it ! = end ; it + + ) {
if ( it - > height < = height )
result . first = it - > version ;
result . second = it - > version ;
2016-08-12 20:19:25 +02:00
}
2021-06-18 01:06:51 +02:00
return result ;
2016-08-12 20:19:25 +02:00
}
2015-09-19 17:34:29 +02:00
}