Skip to content

Commit 8b550cd

Browse files
fix(platform)!: genesis state from core block time (#2003)
Co-authored-by: Ivan Shumkov <[email protected]>
1 parent 77a2bff commit 8b550cd

File tree

16 files changed

+222
-169
lines changed

16 files changed

+222
-169
lines changed

Cargo.lock

Lines changed: 135 additions & 129 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/dashmate/configs/defaults/getBaseConfigFactory.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export default function getBaseConfigFactory(homeDir) {
8686
whitelist: [
8787
'getbestchainlock', 'getblockchaininfo', 'getrawtransaction', 'submitchainlock',
8888
'verifychainlock', 'protxlistdiff', 'quorumlistextended', 'quoruminfo',
89-
'getassetunlockstatuses', 'sendrawtransaction', 'mnsyncstatus',
89+
'getassetunlockstatuses', 'sendrawtransaction', 'mnsyncstatus', 'getblockheader', 'getblockhash',
9090
],
9191
lowPriority: false,
9292
},

packages/dashmate/configs/defaults/getTestnetConfigFactory.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,7 @@ export default function getTestnetConfigFactory(homeDir, getBaseConfig) {
112112
port: 36660,
113113
},
114114
genesis: {
115-
genesis_time: '2024-07-17T17:15:00.000Z',
116-
chain_id: 'dash-testnet-48',
115+
chain_id: 'dash-testnet-49',
117116
validator_quorum_type: 6,
118117
},
119118
},

packages/dashmate/configs/getConfigFileMigrationsFactory.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs)
225225

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

248248
if (options.network === NETWORK_TESTNET) {
249249
options.platform.drive.tenderdash.genesis.chain_id = testnet.get('platform.drive.tenderdash.genesis.chain_id');
250-
options.platform.drive.tenderdash.genesis.genesis_time = testnet.get('platform.drive.tenderdash.genesis.genesis_time');
250+
options.platform.drive.tenderdash.genesis.genesis_time = '2024-07-17T17:15:00.000Z';
251251
options.platform.drive.tenderdash.genesis
252252
.initial_core_chain_locked_height = testnet.get('platform.drive.tenderdash.genesis.initial_core_chain_locked_height');
253253
}
@@ -345,7 +345,7 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs)
345345
if (name !== base.getName()) {
346346
options.platform.drive.tenderdash.genesis.chain_id = testnet.get('platform.drive.tenderdash.genesis.chain_id');
347347
options.platform.drive.tenderdash.genesis.initial_core_chain_locked_height = 14000;
348-
options.platform.drive.tenderdash.genesis.genesis_time = testnet.get('platform.drive.tenderdash.genesis.genesis_time');
348+
options.platform.drive.tenderdash.genesis.genesis_time = '2024-07-17T17:15:00.000Z';
349349
}
350350
}
351351
});
@@ -361,7 +361,7 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs)
361361
if (options.network === NETWORK_TESTNET && name !== base.getName()) {
362362
options.platform.drive.tenderdash.genesis.chain_id = testnet.get('platform.drive.tenderdash.genesis.chain_id');
363363
options.platform.drive.tenderdash.genesis.initial_core_chain_locked_height = 1400;
364-
options.platform.drive.tenderdash.genesis.genesis_time = testnet.get('platform.drive.tenderdash.genesis.genesis_time');
364+
options.platform.drive.tenderdash.genesis.genesis_time = '2024-07-17T17:15:00.000Z';
365365
}
366366
});
367367

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

@@ -729,6 +729,7 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs)
729729

730730
// Update tenderdash image
731731
options.platform.drive.tenderdash.docker.image = base.get('platform.drive.tenderdash.docker.image');
732+
options.core.rpc.users.drive_consensus.whitelist = base.get('core.rpc.users.drive_consensus.whitelist');
732733
});
733734
return configFile;
734735
},

packages/dashmate/src/listr/tasks/setup/local/configureTenderdashTaskFactory.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@ export default function configureTenderdashTaskFactory() {
2323
const randomChainIdPart = Math.floor(Math.random() * 60) + 1;
2424
const chainId = `dashmate_local_${randomChainIdPart}`;
2525

26-
const genesisTime = new Date().toISOString();
27-
2826
platformConfigs.forEach((config, index) => {
29-
config.set('platform.drive.tenderdash.genesis.genesis_time', genesisTime);
3027
config.set('platform.drive.tenderdash.genesis.chain_id', chainId);
3128

3229
const p2pPeers = platformConfigs

packages/rs-drive-abci/src/error/execution.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use dashcore_rpc::dashcore::consensus::encode::Error as DashCoreConsensusEncodeError;
22
use dpp::bls_signatures::BlsError;
3+
use dpp::identity::TimestampMillis;
34
use dpp::version::FeatureVersion;
45
use drive::error::Error as DriveError;
56

@@ -68,6 +69,17 @@ pub enum ExecutionError {
6869
chain_lock_height: u32,
6970
},
7071

72+
/// Genesis time is in the future.
73+
#[error("genesis time {genesis_time} for initial height {initial_height} is in the future. current time is {current_time}")]
74+
InitializationGenesisTimeInFuture {
75+
/// initial height (requested or fork)
76+
initial_height: u32,
77+
/// genesis time
78+
genesis_time: TimestampMillis,
79+
/// current time
80+
current_time: TimestampMillis,
81+
},
82+
7183
/// An error occurred during initialization.
7284
#[error("initialization error: {0}")]
7385
InitializationError(&'static str),

packages/rs-drive-abci/src/execution/engine/initialization/init_chain/v0/mod.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use crate::platform_types::platform_state::PlatformState;
1313
use dpp::version::PlatformVersion;
1414
use std::sync::Arc;
1515
use tenderdash_abci::proto::abci::{RequestInitChain, ResponseInitChain, ValidatorSetUpdate};
16+
use tenderdash_abci::proto::google::protobuf::Timestamp;
17+
use tenderdash_abci::proto::serializers::timestamp::FromMilis;
1618

1719
impl<C> Platform<C>
1820
where
@@ -31,13 +33,16 @@ where
3133
)?;
3234

3335
// Wait until we have an initial core height to start the chain
34-
let core_height = loop {
35-
match self.initial_core_height(request.initial_core_height, platform_version) {
36+
let (core_height, genesis_time) = loop {
37+
match self.initial_core_height_and_time(request.initial_core_height, platform_version) {
3638
Ok(height) => break height,
3739
Err(e) => match e {
3840
Error::Execution(ExecutionError::InitializationForkNotActive(_))
3941
| Error::Execution(ExecutionError::InitializationHeightIsNotLocked {
4042
..
43+
})
44+
| Error::Execution(ExecutionError::InitializationGenesisTimeInFuture {
45+
..
4146
}) => {
4247
tracing::warn!(
4348
error = ?e,
@@ -52,8 +57,6 @@ where
5257
}
5358
};
5459

55-
let genesis_time = request.genesis_time;
56-
5760
// Create genesis drive state
5861
self.create_genesis_state(genesis_time, Some(transaction), platform_version)?;
5962

@@ -127,12 +130,12 @@ where
127130
.map_err(GroveDB)?;
128131

129132
Ok(ResponseInitChain {
130-
consensus_params: None, //todo
133+
consensus_params: None,
131134
app_hash: app_hash.to_vec(),
132135
validator_set_update: Some(validator_set),
133136
next_core_chain_lock_update: None,
134137
initial_core_height: core_height, // we send back the core height when the fork happens
135-
genesis_time: None,
138+
genesis_time: Some(Timestamp::from_milis(genesis_time)),
136139
})
137140
}
138141
}

packages/rs-drive-abci/src/execution/platform_events/initialization/initial_core_height/mod.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::error::execution::ExecutionError;
44
use crate::error::Error;
55
use crate::platform_types::platform::Platform;
66
use crate::rpc::core::CoreRPCLike;
7+
use dpp::prelude::{CoreBlockHeight, TimestampMillis};
78
use dpp::version::PlatformVersion;
89

910
impl<C> Platform<C>
@@ -26,20 +27,20 @@ where
2627
/// * `requested` core height is before mn_rr fork
2728
/// * `requested` core height is after current best chain lock
2829
///
29-
pub(in crate::execution) fn initial_core_height(
30+
pub(in crate::execution) fn initial_core_height_and_time(
3031
&self,
3132
requested: Option<u32>,
3233
platform_version: &PlatformVersion,
33-
) -> Result<u32, Error> {
34+
) -> Result<(CoreBlockHeight, TimestampMillis), Error> {
3435
match platform_version
3536
.drive_abci
3637
.methods
3738
.initialization
38-
.initial_core_height
39+
.initial_core_height_and_time
3940
{
40-
0 => self.initial_core_height_v0(requested),
41+
0 => self.initial_core_height_and_time_v0(requested),
4142
version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch {
42-
method: "initial_core_height".to_string(),
43+
method: "initial_core_height_and_time".to_string(),
4344
known_versions: vec![0],
4445
received: version,
4546
})),

packages/rs-drive-abci/src/execution/platform_events/initialization/initial_core_height/v0/mod.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use crate::error::execution::ExecutionError;
22
use crate::error::Error;
33
use crate::platform_types::platform::Platform;
44
use crate::rpc::core::CoreRPCLike;
5+
use dpp::prelude::{CoreBlockHeight, TimestampMillis};
6+
use std::time::{SystemTime, UNIX_EPOCH};
57

68
impl<C> Platform<C>
79
where
@@ -23,10 +25,10 @@ where
2325
/// * `requested` core height is before mn_rr fork
2426
/// * `requested` core height is after current best chain lock
2527
///
26-
pub(in crate::execution::platform_events) fn initial_core_height_v0(
28+
pub(in crate::execution::platform_events) fn initial_core_height_and_time_v0(
2729
&self,
2830
requested: Option<u32>,
29-
) -> Result<u32, Error> {
31+
) -> Result<(CoreBlockHeight, TimestampMillis), Error> {
3032
let fork_info = self.core_rpc.get_fork_info("mn_rr")?.ok_or(
3133
ExecutionError::InitializationForkNotActive("fork is not yet known".to_string()),
3234
)?;
@@ -60,15 +62,24 @@ where
6062
// Make sure initial height is chain locked
6163
let chain_lock_height = self.core_rpc.get_best_chain_lock()?.block_height;
6264

63-
// TODO (Lukazs) in my opinion, the condition should be:
64-
//
65-
// `mn_rr_fork <= requested && requested <= best`
66-
//
67-
// but it results in 1440 <= 1243 <= 1545
68-
//
69-
// So, fork_info.since differs? is it non-deterministic?
7065
if initial_height <= chain_lock_height {
71-
Ok(initial_height)
66+
let block_time = self.core_rpc.get_block_time_from_height(initial_height)?;
67+
68+
let current_time = SystemTime::now()
69+
.duration_since(UNIX_EPOCH)
70+
.expect("Time went backwards") // Copilot rocks :))
71+
.as_millis() as TimestampMillis;
72+
73+
if block_time > current_time {
74+
return Err(ExecutionError::InitializationGenesisTimeInFuture {
75+
initial_height,
76+
genesis_time: block_time,
77+
current_time,
78+
}
79+
.into());
80+
}
81+
82+
Ok((initial_height, block_time))
7283
} else {
7384
Err(ExecutionError::InitializationHeightIsNotLocked {
7485
initial_height,

packages/rs-drive-abci/src/rpc/core.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use dashcore_rpc::dashcore_rpc_json::{
66
};
77
use dashcore_rpc::json::GetRawTransactionResult;
88
use dashcore_rpc::{Auth, Client, Error, RpcApi};
9-
use dpp::dashcore::InstantLock;
9+
use dpp::dashcore::{Header, InstantLock};
10+
use dpp::prelude::TimestampMillis;
1011
use serde_json::Value;
1112
use std::collections::HashMap;
1213
use std::time::Duration;
@@ -22,6 +23,12 @@ pub trait CoreRPCLike {
2223
/// Get block hash by height
2324
fn get_block_hash(&self, height: CoreHeight) -> Result<BlockHash, Error>;
2425

26+
/// Get block hash by height
27+
fn get_block_header(&self, block_hash: &BlockHash) -> Result<Header, Error>;
28+
29+
/// Get block time of a chain locked core height
30+
fn get_block_time_from_height(&self, height: CoreHeight) -> Result<TimestampMillis, Error>;
31+
2532
/// Get the best chain lock
2633
fn get_best_chain_lock(&self) -> Result<ChainLock, Error>;
2734

@@ -212,6 +219,17 @@ impl CoreRPCLike for DefaultCoreRPC {
212219
retry!(self.inner.get_block_hash(height))
213220
}
214221

222+
fn get_block_header(&self, block_hash: &BlockHash) -> Result<Header, Error> {
223+
retry!(self.inner.get_block_header(block_hash))
224+
}
225+
226+
fn get_block_time_from_height(&self, height: CoreHeight) -> Result<TimestampMillis, Error> {
227+
let block_hash = self.get_block_hash(height)?;
228+
let block_header = self.get_block_header(&block_hash)?;
229+
let block_time = block_header.time as u64 * 1000;
230+
Ok(block_time)
231+
}
232+
215233
fn get_best_chain_lock(&self) -> Result<ChainLock, Error> {
216234
retry!(self.inner.get_best_chain_lock())
217235
}

0 commit comments

Comments
 (0)