Skip to content

Commit

Permalink
fix(platform)!: genesis state from core block time (#2003)
Browse files Browse the repository at this point in the history
Co-authored-by: Ivan Shumkov <[email protected]>
  • Loading branch information
QuantumExplorer and shumkov authored Jul 25, 2024
1 parent 77a2bff commit 8b550cd
Show file tree
Hide file tree
Showing 16 changed files with 222 additions and 169 deletions.
264 changes: 135 additions & 129 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/dashmate/configs/defaults/getBaseConfigFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export default function getBaseConfigFactory(homeDir) {
whitelist: [
'getbestchainlock', 'getblockchaininfo', 'getrawtransaction', 'submitchainlock',
'verifychainlock', 'protxlistdiff', 'quorumlistextended', 'quoruminfo',
'getassetunlockstatuses', 'sendrawtransaction', 'mnsyncstatus',
'getassetunlockstatuses', 'sendrawtransaction', 'mnsyncstatus', 'getblockheader', 'getblockhash',
],
lowPriority: false,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ export default function getTestnetConfigFactory(homeDir, getBaseConfig) {
port: 36660,
},
genesis: {
genesis_time: '2024-07-17T17:15:00.000Z',
chain_id: 'dash-testnet-48',
chain_id: 'dash-testnet-49',
validator_quorum_type: 6,
},
},
Expand Down
11 changes: 6 additions & 5 deletions packages/dashmate/configs/getConfigFileMigrationsFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs)

if (options.network === NETWORK_TESTNET) {
options.platform.drive.tenderdash.genesis.chain_id = testnet.get('platform.drive.tenderdash.genesis.chain_id');
options.platform.drive.tenderdash.genesis.genesis_time = testnet.get('platform.drive.tenderdash.genesis.genesis_time');
options.platform.drive.tenderdash.genesis.genesis_time = '2024-07-17T17:15:00.000Z';
}
});
return configFile;
Expand All @@ -247,7 +247,7 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs)

if (options.network === NETWORK_TESTNET) {
options.platform.drive.tenderdash.genesis.chain_id = testnet.get('platform.drive.tenderdash.genesis.chain_id');
options.platform.drive.tenderdash.genesis.genesis_time = testnet.get('platform.drive.tenderdash.genesis.genesis_time');
options.platform.drive.tenderdash.genesis.genesis_time = '2024-07-17T17:15:00.000Z';
options.platform.drive.tenderdash.genesis
.initial_core_chain_locked_height = testnet.get('platform.drive.tenderdash.genesis.initial_core_chain_locked_height');
}
Expand Down Expand Up @@ -345,7 +345,7 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs)
if (name !== base.getName()) {
options.platform.drive.tenderdash.genesis.chain_id = testnet.get('platform.drive.tenderdash.genesis.chain_id');
options.platform.drive.tenderdash.genesis.initial_core_chain_locked_height = 14000;
options.platform.drive.tenderdash.genesis.genesis_time = testnet.get('platform.drive.tenderdash.genesis.genesis_time');
options.platform.drive.tenderdash.genesis.genesis_time = '2024-07-17T17:15:00.000Z';
}
}
});
Expand All @@ -361,7 +361,7 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs)
if (options.network === NETWORK_TESTNET && name !== base.getName()) {
options.platform.drive.tenderdash.genesis.chain_id = testnet.get('platform.drive.tenderdash.genesis.chain_id');
options.platform.drive.tenderdash.genesis.initial_core_chain_locked_height = 1400;
options.platform.drive.tenderdash.genesis.genesis_time = testnet.get('platform.drive.tenderdash.genesis.genesis_time');
options.platform.drive.tenderdash.genesis.genesis_time = '2024-07-17T17:15:00.000Z';
}
});

Expand All @@ -373,7 +373,7 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs)
if (options.network === NETWORK_TESTNET && name !== base.getName()) {
options.platform.drive.tenderdash.genesis.chain_id = testnet.get('platform.drive.tenderdash.genesis.chain_id');
options.platform.drive.tenderdash.genesis.initial_core_chain_locked_height = 1400;
options.platform.drive.tenderdash.genesis.genesis_time = testnet.get('platform.drive.tenderdash.genesis.genesis_time');
options.platform.drive.tenderdash.genesis.genesis_time = '2024-07-17T17:15:00.000Z';
}
});

Expand Down Expand Up @@ -729,6 +729,7 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs)

// Update tenderdash image
options.platform.drive.tenderdash.docker.image = base.get('platform.drive.tenderdash.docker.image');
options.core.rpc.users.drive_consensus.whitelist = base.get('core.rpc.users.drive_consensus.whitelist');
});
return configFile;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ export default function configureTenderdashTaskFactory() {
const randomChainIdPart = Math.floor(Math.random() * 60) + 1;
const chainId = `dashmate_local_${randomChainIdPart}`;

const genesisTime = new Date().toISOString();

platformConfigs.forEach((config, index) => {
config.set('platform.drive.tenderdash.genesis.genesis_time', genesisTime);
config.set('platform.drive.tenderdash.genesis.chain_id', chainId);

const p2pPeers = platformConfigs
Expand Down
12 changes: 12 additions & 0 deletions packages/rs-drive-abci/src/error/execution.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use dashcore_rpc::dashcore::consensus::encode::Error as DashCoreConsensusEncodeError;
use dpp::bls_signatures::BlsError;
use dpp::identity::TimestampMillis;
use dpp::version::FeatureVersion;
use drive::error::Error as DriveError;

Expand Down Expand Up @@ -68,6 +69,17 @@ pub enum ExecutionError {
chain_lock_height: u32,
},

/// Genesis time is in the future.
#[error("genesis time {genesis_time} for initial height {initial_height} is in the future. current time is {current_time}")]
InitializationGenesisTimeInFuture {
/// initial height (requested or fork)
initial_height: u32,
/// genesis time
genesis_time: TimestampMillis,
/// current time
current_time: TimestampMillis,
},

/// An error occurred during initialization.
#[error("initialization error: {0}")]
InitializationError(&'static str),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use crate::platform_types::platform_state::PlatformState;
use dpp::version::PlatformVersion;
use std::sync::Arc;
use tenderdash_abci::proto::abci::{RequestInitChain, ResponseInitChain, ValidatorSetUpdate};
use tenderdash_abci::proto::google::protobuf::Timestamp;
use tenderdash_abci::proto::serializers::timestamp::FromMilis;

impl<C> Platform<C>
where
Expand All @@ -31,13 +33,16 @@ where
)?;

// Wait until we have an initial core height to start the chain
let core_height = loop {
match self.initial_core_height(request.initial_core_height, platform_version) {
let (core_height, genesis_time) = loop {
match self.initial_core_height_and_time(request.initial_core_height, platform_version) {
Ok(height) => break height,
Err(e) => match e {
Error::Execution(ExecutionError::InitializationForkNotActive(_))
| Error::Execution(ExecutionError::InitializationHeightIsNotLocked {
..
})
| Error::Execution(ExecutionError::InitializationGenesisTimeInFuture {
..
}) => {
tracing::warn!(
error = ?e,
Expand All @@ -52,8 +57,6 @@ where
}
};

let genesis_time = request.genesis_time;

// Create genesis drive state
self.create_genesis_state(genesis_time, Some(transaction), platform_version)?;

Expand Down Expand Up @@ -127,12 +130,12 @@ where
.map_err(GroveDB)?;

Ok(ResponseInitChain {
consensus_params: None, //todo
consensus_params: None,
app_hash: app_hash.to_vec(),
validator_set_update: Some(validator_set),
next_core_chain_lock_update: None,
initial_core_height: core_height, // we send back the core height when the fork happens
genesis_time: None,
genesis_time: Some(Timestamp::from_milis(genesis_time)),
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::error::execution::ExecutionError;
use crate::error::Error;
use crate::platform_types::platform::Platform;
use crate::rpc::core::CoreRPCLike;
use dpp::prelude::{CoreBlockHeight, TimestampMillis};
use dpp::version::PlatformVersion;

impl<C> Platform<C>
Expand All @@ -26,20 +27,20 @@ where
/// * `requested` core height is before mn_rr fork
/// * `requested` core height is after current best chain lock
///
pub(in crate::execution) fn initial_core_height(
pub(in crate::execution) fn initial_core_height_and_time(
&self,
requested: Option<u32>,
platform_version: &PlatformVersion,
) -> Result<u32, Error> {
) -> Result<(CoreBlockHeight, TimestampMillis), Error> {
match platform_version
.drive_abci
.methods
.initialization
.initial_core_height
.initial_core_height_and_time
{
0 => self.initial_core_height_v0(requested),
0 => self.initial_core_height_and_time_v0(requested),
version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch {
method: "initial_core_height".to_string(),
method: "initial_core_height_and_time".to_string(),
known_versions: vec![0],
received: version,
})),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use crate::error::execution::ExecutionError;
use crate::error::Error;
use crate::platform_types::platform::Platform;
use crate::rpc::core::CoreRPCLike;
use dpp::prelude::{CoreBlockHeight, TimestampMillis};
use std::time::{SystemTime, UNIX_EPOCH};

impl<C> Platform<C>
where
Expand All @@ -23,10 +25,10 @@ where
/// * `requested` core height is before mn_rr fork
/// * `requested` core height is after current best chain lock
///
pub(in crate::execution::platform_events) fn initial_core_height_v0(
pub(in crate::execution::platform_events) fn initial_core_height_and_time_v0(
&self,
requested: Option<u32>,
) -> Result<u32, Error> {
) -> Result<(CoreBlockHeight, TimestampMillis), Error> {
let fork_info = self.core_rpc.get_fork_info("mn_rr")?.ok_or(
ExecutionError::InitializationForkNotActive("fork is not yet known".to_string()),
)?;
Expand Down Expand Up @@ -60,15 +62,24 @@ where
// Make sure initial height is chain locked
let chain_lock_height = self.core_rpc.get_best_chain_lock()?.block_height;

// TODO (Lukazs) in my opinion, the condition should be:
//
// `mn_rr_fork <= requested && requested <= best`
//
// but it results in 1440 <= 1243 <= 1545
//
// So, fork_info.since differs? is it non-deterministic?
if initial_height <= chain_lock_height {
Ok(initial_height)
let block_time = self.core_rpc.get_block_time_from_height(initial_height)?;

let current_time = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards") // Copilot rocks :))
.as_millis() as TimestampMillis;

if block_time > current_time {
return Err(ExecutionError::InitializationGenesisTimeInFuture {
initial_height,
genesis_time: block_time,
current_time,
}
.into());
}

Ok((initial_height, block_time))
} else {
Err(ExecutionError::InitializationHeightIsNotLocked {
initial_height,
Expand Down
20 changes: 19 additions & 1 deletion packages/rs-drive-abci/src/rpc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use dashcore_rpc::dashcore_rpc_json::{
};
use dashcore_rpc::json::GetRawTransactionResult;
use dashcore_rpc::{Auth, Client, Error, RpcApi};
use dpp::dashcore::InstantLock;
use dpp::dashcore::{Header, InstantLock};
use dpp::prelude::TimestampMillis;
use serde_json::Value;
use std::collections::HashMap;
use std::time::Duration;
Expand All @@ -22,6 +23,12 @@ pub trait CoreRPCLike {
/// Get block hash by height
fn get_block_hash(&self, height: CoreHeight) -> Result<BlockHash, Error>;

/// Get block hash by height
fn get_block_header(&self, block_hash: &BlockHash) -> Result<Header, Error>;

/// Get block time of a chain locked core height
fn get_block_time_from_height(&self, height: CoreHeight) -> Result<TimestampMillis, Error>;

/// Get the best chain lock
fn get_best_chain_lock(&self) -> Result<ChainLock, Error>;

Expand Down Expand Up @@ -212,6 +219,17 @@ impl CoreRPCLike for DefaultCoreRPC {
retry!(self.inner.get_block_hash(height))
}

fn get_block_header(&self, block_hash: &BlockHash) -> Result<Header, Error> {
retry!(self.inner.get_block_header(block_hash))
}

fn get_block_time_from_height(&self, height: CoreHeight) -> Result<TimestampMillis, Error> {
let block_hash = self.get_block_hash(height)?;
let block_header = self.get_block_header(&block_hash)?;
let block_time = block_header.time as u64 * 1000;
Ok(block_time)
}

fn get_best_chain_lock(&self) -> Result<ChainLock, Error> {
retry!(self.inner.get_best_chain_lock())
}
Expand Down
5 changes: 5 additions & 0 deletions packages/rs-drive-abci/tests/strategy_tests/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,11 @@ pub(crate) fn run_chain_for_strategy<'a>(
})
.collect();

platform
.core_rpc
.expect_get_block_time_from_height()
.returning(|_| Ok(GENESIS_TIME_MS));

platform
.core_rpc
.expect_get_best_chain_lock()
Expand Down
6 changes: 3 additions & 3 deletions packages/rs-drive-abci/tests/strategy_tests/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ mod tests {
.unwrap()
.unwrap()
),
"065668f27dd4e3611a6aec4797fdd47acbd7356ae84eb711b8289dab8f09ea31".to_string()
"e8e42170ec547a2170d1128b8ec51cd56a3e2d72fea24c797bd87851e6a0aa95".to_string()
)
}

Expand Down Expand Up @@ -1915,7 +1915,7 @@ mod tests {
.unwrap()
.unwrap()
),
"8c63acd8e6f41f316ea8257e3abc828a5b4d94726fb51575c5cb1288e9605086".to_string()
"6a3782a2868634fc1cdf5752f365374829d020a5c2019eeb55beacf08653c43f".to_string()
)
}

Expand Down Expand Up @@ -2050,7 +2050,7 @@ mod tests {
.unwrap()
.unwrap()
),
"77bb976ad70a75cdbf044ec311feb8581bb13dea4e66d0fa7b9abc52157b422a".to_string()
"cf8561aaab49bc8bcbe1468c9e890ee0c9c01794e9a52d45d86b0b41ccc44133".to_string()
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ pub struct DriveAbciMasternodeIdentitiesUpdatesMethodVersions {

#[derive(Clone, Debug, Default)]
pub struct DriveAbciInitializationMethodVersions {
pub initial_core_height: FeatureVersion,
pub initial_core_height_and_time: FeatureVersion,
pub create_genesis_state: FeatureVersion,
}

Expand Down
2 changes: 1 addition & 1 deletion packages/rs-platform-version/src/version/mocks/v2_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ pub const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion {
finalize_block_proposal: 0,
},
initialization: DriveAbciInitializationMethodVersions {
initial_core_height: 0,
initial_core_height_and_time: 0,
create_genesis_state: 0,
},
core_based_updates: DriveAbciCoreBasedUpdatesMethodVersions {
Expand Down
2 changes: 1 addition & 1 deletion packages/rs-platform-version/src/version/mocks/v3_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ pub const TEST_PLATFORM_V3: PlatformVersion = PlatformVersion {
finalize_block_proposal: 0,
},
initialization: DriveAbciInitializationMethodVersions {
initial_core_height: 0,
initial_core_height_and_time: 0,
create_genesis_state: 0,
},
core_based_updates: DriveAbciCoreBasedUpdatesMethodVersions {
Expand Down
2 changes: 1 addition & 1 deletion packages/rs-platform-version/src/version/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ pub const PLATFORM_V1: PlatformVersion = PlatformVersion {
finalize_block_proposal: 0,
},
initialization: DriveAbciInitializationMethodVersions {
initial_core_height: 0,
initial_core_height_and_time: 0,
create_genesis_state: 0,
},
core_based_updates: DriveAbciCoreBasedUpdatesMethodVersions {
Expand Down

0 comments on commit 8b550cd

Please sign in to comment.